def __init__(self, x0=0.8,y0=0.3,theta0=-0.03, odom_lin_sigma=0.025, odom_ang_sigma=np.deg2rad(2),
                     meas_rng_noise=0.2,  meas_ang_noise=np.deg2rad(10)):
     '''
     Initializes publishers, subscribers and the particle filter.
     '''
     # Publishers
     self.pub_lines = rospy.Publisher("lines", Marker)
     self.pub_odom = rospy.Publisher("predicted_odom", Odometry)
     self.pub_uncertainity = rospy.Publisher("uncertainity",  Marker)
     
     # Subscribers
     self.sub_scan = rospy.Subscriber("scan", LaserScan, self.laser_callback)
     self.sub_odom = rospy.Subscriber("odom", Odometry, self.odom_callback)
     
     # TF
     self.tfBroad = tf.TransformBroadcaster()
     
     # Incremental odometry
     self.last_odom = None
     self.odom = None
     
     # Flags
     self.new_odom = False
     self.new_laser = False
     self.pub = False
     
     # Particle filter
     self.ekf = EKF(get_map(), x0, y0, theta0, odom_lin_sigma, odom_ang_sigma, meas_rng_noise, meas_ang_noise)
示例#2
0
    def __init__(self, xinit, odom_lin_sigma, odom_ang_sigma, meas_rng_noise,
                 meas_ang_noise, rob2sensor):
        """Initialize publishers, subscribers and the filter."""
        # Publishers
        self.pub_laser = rospy.Publisher("ekf_laser", LaserScan, queue_size=2)
        self.pub_lines = rospy.Publisher("linesekf", Marker, queue_size=2)
        self.pub_odom = rospy.Publisher("predicted_odom",
                                        Odometry,
                                        queue_size=2)
        self.pub_uncertainity = rospy.Publisher("uncertainity",
                                                Marker,
                                                queue_size=2)

        # Subscribers
        self.sub_laser = rospy.Subscriber("scan", LaserScan, self.cbk_laser)
        self.sub_scan = rospy.Subscriber("lines", Marker, self.cbk_lines)
        self.sub_odom = rospy.Subscriber("odom", Odometry, self.cbk_odom)

        # TF
        self.tfBroad = tf.TransformBroadcaster()

        # Incremental odometry
        self.last_odom = None
        self.odom = None

        # Times
        self.time = rospy.Time(0)
        self.odomtime = rospy.Time(0)
        self.linestime = rospy.Time(0)

        # Flags
        self.uk = None
        self.lines = None
        self.new_odom = False
        self.new_laser = False
        self.pub = False

        # Filter
        self.ekf = EKF(xinit, odom_lin_sigma, odom_ang_sigma, meas_rng_noise,
                       meas_ang_noise)

        # Transformation from robot to sensor
        self.robot2sensor = np.array(rob2sensor)
        print self.robot2sensor
示例#3
0
    def __init__(self, xinit, odom_lin_sigma, odom_ang_sigma, meas_rng_noise,
                 meas_ang_noise, rob2sensor):
        """Initialize publishers, subscribers and the filter."""
        # Publishers
        self.pub_laser = rospy.Publisher("ekf_laser",  LaserScan, queue_size=2)
        self.pub_lines = rospy.Publisher("linesekf", Marker, queue_size=2)
        self.pub_odom = rospy.Publisher("predicted_odom", Odometry,
                                        queue_size=2)
        self.pub_uncertainity = rospy.Publisher("uncertainity",  Marker,
                                                queue_size=2)

        # Subscribers
        self.sub_laser = rospy.Subscriber("scan", LaserScan, self.cbk_laser)
        self.sub_scan = rospy.Subscriber("lines", Marker, self.cbk_lines)
        self.sub_odom = rospy.Subscriber("odom", Odometry, self.cbk_odom)

        # TF
        self.tfBroad = tf.TransformBroadcaster()

        # Incremental odometry
        self.last_odom = None
        self.odom = None

        # Times
        self.time = rospy.Time(0)
        self.odomtime = rospy.Time(0)
        self.linestime = rospy.Time(0)

        # Flags
        self.uk = None
        self.lines = None
        self.new_odom = False
        self.new_laser = False
        self.pub = False

        # Filter
        self.ekf = EKF(xinit, odom_lin_sigma, odom_ang_sigma, meas_rng_noise,
                       meas_ang_noise)

        # Transformation from robot to sensor
        self.robot2sensor = np.array(rob2sensor)
        print self.robot2sensor
class LocalizationNode(object):
    '''
    Class to hold all ROS related transactions to use split and merge algorithm.
    '''
    
    #===========================================================================
    def __init__(self, x0=0.8,y0=0.3,theta0=-0.03, odom_lin_sigma=0.025, odom_ang_sigma=np.deg2rad(2),
                        meas_rng_noise=0.2,  meas_ang_noise=np.deg2rad(10)):
        '''
        Initializes publishers, subscribers and the particle filter.
        '''
        # Publishers
        self.pub_lines = rospy.Publisher("lines", Marker)
        self.pub_odom = rospy.Publisher("predicted_odom", Odometry)
        self.pub_uncertainity = rospy.Publisher("uncertainity",  Marker)
        
        # Subscribers
        self.sub_scan = rospy.Subscriber("scan", LaserScan, self.laser_callback)
        self.sub_odom = rospy.Subscriber("odom", Odometry, self.odom_callback)
        
        # TF
        self.tfBroad = tf.TransformBroadcaster()
        
        # Incremental odometry
        self.last_odom = None
        self.odom = None
        
        # Flags
        self.new_odom = False
        self.new_laser = False
        self.pub = False
        
        # Particle filter
        self.ekf = EKF(get_map(), x0, y0, theta0, odom_lin_sigma, odom_ang_sigma, meas_rng_noise, meas_ang_noise)
    
    #===========================================================================
    def odom_callback(self, msg):
        '''
        Publishes a tf based on the odometry of the robot and calculates the incremental odometry as seen from the vehicle frame.
        '''
        # Save time
        self.time = msg.header.stamp
        
        # Translation
        trans = (msg.pose.pose.position.x, 
                 msg.pose.pose.position.y, 
                 msg.pose.pose.position.z)
        
        # Rotation
        rot = (msg.pose.pose.orientation.x,
               msg.pose.pose.orientation.y,
               msg.pose.pose.orientation.z,
               msg.pose.pose.orientation.w)
        
        # Publish transform
        self.tfBroad.sendTransform(translation = trans,
                                   rotation = rot, 
                                   time = msg.header.stamp,
                                   child = '/openni_depth_frame',
                                   parent = '/world')
                                   
        # Incremental odometry
        if self.last_odom is not None:
            
            # Increment computation
            delta_x = msg.pose.pose.position.x - self.last_odom.pose.pose.position.x
            delta_y = msg.pose.pose.position.y - self.last_odom.pose.pose.position.y
            yaw = yaw_from_quaternion(msg.pose.pose.orientation)
            lyaw = yaw_from_quaternion(self.last_odom.pose.pose.orientation)
            
            # Odometry seen from vehicle frame
            self.uk = np.array([delta_x * np.cos(lyaw) + delta_y * np.sin(lyaw),
                              - delta_x * np.sin(lyaw) + delta_y * np.cos(lyaw),
                                angle_wrap(yaw - lyaw)])
            
            # Flag
            self.new_odom = True
        
        # For next loop
        self.last_odom = msg
        
    
    #===========================================================================
    def laser_callback(self, msg):
        '''
        Function called each time a LaserScan message with topic "scan" arrives. 
        '''
        # Save time
        self.time = msg.header.stamp
        
        # Project LaserScan to points in space
        rng = np.array(msg.ranges)
        ang = np.linspace(msg.angle_min, msg.angle_max, len(msg.ranges))
        points = np.vstack((rng * np.cos(ang),
                            rng * np.sin(ang)))
                            
        # Filter long ranges
        cond = rng < msg.range_max
        points = points[:, rng < msg.range_max]
        
        # Use split and merge to obtain lines and publish
        self.lines = splitandmerge(points, split_thres=0.1,
                                      inter_thres=0.3,
                                      min_points=6,
                                      dist_thres=0.12,
                                      ang_thres=np.deg2rad(10))

        # Have valid points
        if self.lines is not None:
            
            # Publish results
            publish_lines(self.lines, self.pub_lines, frame='/robot',
                      time=msg.header.stamp, ns='scan_lines_robot', color=(0,0,1))
            
            # Flag
            self.new_laser = True
    
    #===========================================================================
    def iterate(self):
        '''
        Main loop of the filter.
        '''
        # Prediction
        if self.new_odom:
            
            self.ekf.predict(self.uk.copy())
            self.new_odom = False
            self.pub = True
            
        # Weightimg and resampling
        if self.new_laser:
            
            Innovk_List, H_k_List, S_f_List, Rk_List=self.ekf.data_association(self.lines.copy())
            self.ekf.update_position(Innovk_List, H_k_List, S_f_List, Rk_List)
            self.new_laser = False
            self.pub = True
            
        # Publish results
        if self.pub:
            self.publish_results()
            self.pub = False
    
    #===========================================================================
    def publish_results(self):
        '''
        Publishes all results from the filter.
        '''
        # Map of the room
        map_lines = get_map()
        publish_lines(map_lines, self.pub_lines, frame='/world', ns='map', color=(0,1,0))
        
        msg_odom, msg_ellipse, trans, rot = get_ekf_msgs(self.ekf)

        self.pub_odom.publish(msg_odom)
        self.pub_uncertainity.publish(msg_ellipse)
        self.tfBroad.sendTransform(translation = trans,
                                   rotation = rot, 
                                   time = self.time,
                                   child = '/robot',
                                   parent = '/world')
示例#5
0
class LocalizationNode(object):
    """Class to hold all ROS related transactions."""

    # ==========================================================================
    def __init__(self, xinit, odom_lin_sigma, odom_ang_sigma, meas_rng_noise,
                 meas_ang_noise, rob2sensor):
        """Initialize publishers, subscribers and the filter."""
        # Publishers
        self.pub_laser = rospy.Publisher("ekf_laser",  LaserScan, queue_size=2)
        self.pub_lines = rospy.Publisher("linesekf", Marker, queue_size=2)
        self.pub_odom = rospy.Publisher("predicted_odom", Odometry,
                                        queue_size=2)
        self.pub_uncertainity = rospy.Publisher("uncertainity",  Marker,
                                                queue_size=2)

        # Subscribers
        self.sub_laser = rospy.Subscriber("scan", LaserScan, self.cbk_laser)
        self.sub_scan = rospy.Subscriber("lines", Marker, self.cbk_lines)
        self.sub_odom = rospy.Subscriber("odom", Odometry, self.cbk_odom)

        # TF
        self.tfBroad = tf.TransformBroadcaster()

        # Incremental odometry
        self.last_odom = None
        self.odom = None

        # Times
        self.time = rospy.Time(0)
        self.odomtime = rospy.Time(0)
        self.linestime = rospy.Time(0)

        # Flags
        self.uk = None
        self.lines = None
        self.new_odom = False
        self.new_laser = False
        self.pub = False

        # Filter
        self.ekf = EKF(xinit, odom_lin_sigma, odom_ang_sigma, meas_rng_noise,
                       meas_ang_noise)

        # Transformation from robot to sensor
        self.robot2sensor = np.array(rob2sensor)
        print self.robot2sensor

    # ==========================================================================
    def cbk_laser(self, msg):
        """Republish laser scan in the EKF solution frame."""
        msg.header.frame_id = 'sensor'
        self.pub_laser.publish(msg)

    # ==========================================================================
    def cbk_odom(self, msg):
        """Publish tf and calculate incremental odometry."""
        # Save time
        self.odomtime = msg.header.stamp
        self.odom = msg

        # Translation
        trans = (msg.pose.pose.position.x,
                 msg.pose.pose.position.y,
                 msg.pose.pose.position.z)

        # Rotation
        rot = (msg.pose.pose.orientation.x,
               msg.pose.pose.orientation.y,
               msg.pose.pose.orientation.z,
               msg.pose.pose.orientation.w)

        # Publish transform
        self.tfBroad.sendTransform(translation=self.robot2sensor,
                                   rotation=(0, 0, 0, 1),
                                   time=msg.header.stamp,
                                   child='sensor',
                                   parent='robot')
        self.tfBroad.sendTransform(translation=self.robot2sensor,
                                   rotation=(0, 0, 0, 1),
                                   time=msg.header.stamp,
                                   child='camera_depth_frame',
                                   parent='base_footprint')
        self.tfBroad.sendTransform(translation=trans,
                                   rotation=rot,
                                   time=msg.header.stamp,
                                   child='base_footprint',
                                   parent='world')
        self.tfBroad.sendTransform(translation=(0, 0, 0),
                                   rotation=(0, 0, 0, 1),
                                   time=msg.header.stamp,
                                   child='odom',
                                   parent='world')

        # Incremental odometry
        if self.last_odom is not None:

            # Increment computation
            delta_x = msg.pose.pose.position.x - \
                self.last_odom.pose.pose.position.x
            delta_y = msg.pose.pose.position.y - \
                self.last_odom.pose.pose.position.y
            yaw = funcs.yaw_from_quaternion(msg.pose.pose.orientation)
            lyaw = funcs.yaw_from_quaternion(
                self.last_odom.pose.pose.orientation)

            # Odometry seen from vehicle frame
            self.uk = np.array([delta_x*np.cos(lyaw) + delta_y*np.sin(lyaw),
                               -delta_x*np.sin(lyaw) + delta_y*np.cos(lyaw),
                                funcs.angle_wrap(yaw - lyaw)])

            # Flag available
            self.new_odom = True

        # Save initial odometry for increment
        else:
            self.last_odom = msg

    # ==========================================================================
    def cbk_lines(self, msg):
        """Republish the laser scam in the /robot frame."""
        # Save time
        self.linestime = msg.header.stamp

        # Get the lines
        if len(msg.points) > 0:

            # Structure for the lines
            self.lines = np.zeros((len(msg.points) / 2, 4))

            for i in range(0, len(msg.points)/2):
                # Get start and end points
                pt1 = msg.points[2*i]
                pt2 = msg.points[2*i+1]

                # Transform to robot frame
                pt1R = funcs.comp(self.robot2sensor, [pt1.x, pt1.y, 0.0])
                pt2R = funcs.comp(self.robot2sensor, [pt2.x, pt2.y, 0.0])

                # Append to line list
                self.lines[i, :2] = pt1R[:2]
                self.lines[i, 2:] = pt2R[:2]

            # Flag
            self.new_laser = True

            # Publish
            funcs.publish_lines(self.lines, self.pub_lines, frame='robot',
                                time=msg.header.stamp, ns='lines_robot',
                                color=(0, 0, 1))

    # ==========================================================================
    def iterate(self):
        """Main loop of the filter."""
        # Prediction
        if self.new_odom:
            # Make prediction (copy needed to ensure no paral thread)
            self.ekf.predict(self.uk.copy())
            self.last_odom = self.odom  # new start odom for incremental
            self.new_odom = False
            self.pub = True
            self.time = self.odomtime

        # Data association and update
        if self.new_laser:
            # Make data association and update
            temp = self.ekf.data_association(self.lines.copy())
            Hk_list, Vk_list, Sk_list, Rk_list = temp
            self.ekf.update_position(Hk_list, Vk_list, Sk_list, Rk_list)
            self.new_laser = False
            self.pub = True
            self.time = self.linestime

        # Publish results
        if self.pub:
            self.publish_results()
            self.pub = False

    # ==========================================================================
    def publish_results(self):
        """Publishe results from the filter."""
        # Map of the room (ground truth)
        funcs.publish_lines(self.ekf.map, self.pub_lines, frame='world',
                            ns='map', color=(0, 1, 0))

        # Get filter data
        odom, ellipse, trans, rot, dummy = funcs.get_ekf_msgs(self.ekf)

        # Publish results
        self.pub_odom.publish(odom)
        self.pub_uncertainity.publish(ellipse)
        self.tfBroad.sendTransform(translation=trans,
                                   rotation=rot,
                                   time=self.time,
                                   child='robot',
                                   parent='world')