예제 #1
0
class TJ2RomiPfNode:
    def __init__(self):
        self.node_name = "tj2_romi_pf"
        rospy.init_node(self.node_name,
                        # disable_signals=True
                        # log_level=rospy.DEBUG
                        )
        # rospy.on_shutdown(self.shutdown_hook)

        self.map_frame = rospy.get_param("~map_frame", "map")
        self.base_frame = rospy.get_param("~base_frame", "base_link")
        self.map_service_name = rospy.get_param("~static_map", "static_map")

        self.show_particles = rospy.get_param("~publish_particles", True)

        self.initial_range = rospy.get_param("~initial_range", None)
        self.input_std = rospy.get_param("~input_std", None)
        self.meas_std_val = rospy.get_param("~meas_std_val", 0.007)
        self.num_particles = rospy.get_param("~num_particles", 100)
        self.input_std = rospy.get_param("~input_std", None)

        if self.initial_range is None:
            self.initial_range = [1.0, 1.0, 1.0]
        if self.input_std is None:
            self.input_std = [0.007, 0.007]
        self.input_vector = np.zeros(len(self.input_std))

        self.pf = ParticleFilter(self.num_particles, self.meas_std_val,
                                 self.input_std)
        self.prev_pf_time = rospy.Time.now().to_sec()

        self.map_raytracer = MapRaytracer(self.base_frame, "ultrasonic1",
                                          "ultrasonic2")

        self.ultrasonic1_sub = rospy.Subscriber("ultrasonic1",
                                                Float64,
                                                self.ultrasonic1_callback,
                                                queue_size=25)
        self.ultrasonic2_sub = rospy.Subscriber("ultrasonic2",
                                                Float64,
                                                self.ultrasonic2_callback,
                                                queue_size=25)
        self.odom_sub = rospy.Subscriber("odom",
                                         Odometry,
                                         self.odom_callback,
                                         queue_size=25)

        self.particles_pub = rospy.Publisher("pf_particles",
                                             PoseArray,
                                             queue_size=5)

        self.broadcaster = tf2_ros.TransformBroadcaster()

        self.get_map = rospy.ServiceProxy(self.map_service_name, GetMap)
        rospy.loginfo("Waiting for service %s" % self.map_service_name)
        rospy.wait_for_service(self.map_service_name)
        self.map_msg = self.get_map().map
        self.map_raytracer.set_map(self.map_msg)

        rospy.loginfo("%s init done" % self.node_name)

    def ultrasonic1_callback(self, msg):
        self.pf.update(msg.data, "ultrasonic1")

    def ultrasonic2_callback(self, msg):
        self.pf.update(msg.data, "ultrasonic2")

    def odom_callback(self, msg):
        current_time = msg.header.stamp.to_sec()
        dt = current_time - self.prev_pf_time
        self.prev_pf_time = current_time

        self.input_vector[0] = -msg.twist.twist.linear.x
        self.input_vector[1] = -msg.twist.twist.angular.z
        self.pf.predict(self.input_vector, dt)

    def publish_all_pose(self):
        mean = self.pf.mean()

        # TODO: first cancel out odom transform, then apply map transform
        msg = TransformStamped()
        msg.header.stamp = rospy.Time.now()
        msg.header.frame_id = self.map_frame
        msg.child_frame_id = self.base_frame
        msg.transform.translation.x = mean[0]
        msg.transform.translation.y = mean[1]
        msg.transform.translation.z = mean[2]
        msg.transform.rotation.w = 1.0
        self.broadcaster.sendTransform(msg)

    def publish_particles(self):
        particles_msg = PoseArray()
        particles_msg.header.frame_id = self.map_frame
        particles_msg.header.stamp = rospy.Time.now()

        for particle in self.pf.particles:
            pose_msg = Pose()
            pose_msg.position.x = particle[0]
            pose_msg.position.y = particle[1]
            pose_msg.position.z = particle[2]
            particles_msg.poses.append(pose_msg)

        self.particles_pub.publish(particles_msg)

    def run(self):
        rate = rospy.Rate(30.0)

        while True:
            rate.sleep()
            if rospy.is_shutdown():
                break
            self.pf.check_resample()

            self.publish_all_pose()

            if self.show_particles:
                self.publish_particles()