def pose_callback(self, msg):
        '''handles arrival of pose messages
           :type msg: PoseStamped'''
        cam_pose = msg.pose

        # two camera poses and TFs are available
        if self.last_cam_pose is not None and self.has_tfs:
            # actually not the base_link poses, but camera poses from perspective of base_link frame
            last_base_pose = tf2_geometry_msgs.do_transform_pose(
                PoseStamped(pose=self.last_cam_pose), self.base_link_to_camera_tf).pose
            base_pose = tf2_geometry_msgs.do_transform_pose(
                PoseStamped(pose=cam_pose), self.base_link_to_camera_tf).pose
            # transform to actual base_link poses (still in base_link frame)
            transform_pose(last_base_pose, self.camera_to_base_link_tf.transform)
            transform_pose(base_pose, self.camera_to_base_link_tf.transform)

            # get difference
            delta_transform = get_relative_transform(
                last_base_pose.position, last_base_pose.orientation, base_pose.position, base_pose.orientation)

            # everything seems to be working fine
            if not self.enabled:
                rospy.loginfo('ORBSLAM2PoseSubscriber enabled')
                self.enabled = True

            # hand in the update
            self.callback(delta_transform)
            if self.do_plot:
                plotting.add_transform(self, delta_transform)

        # delay poses until TFs initialized
        if self.last_cam_pose is None or self.has_tfs:
            self.last_cam_pose = cam_pose
Exemple #2
0
    def pose_callback(self, msg):
        '''handles arrival of pose messages'''
        # strip potential header and cov
        pose, stamp = (msg.pose, msg.header.stamp) if self.is_stamped else (msg, None)
        pose = pose.pose if self.is_with_covariance else pose

        # IMU enhanced mode
        if self.is_roll_pitch_imu:
            # check IMU availability
            imu = self.imu_subscriber.get_last_imu() if stamp is None else self.imu_subscriber.get_imu_at_time(stamp)
            if imu is None:
                rospy.logwarn('PoseSubscriber: IMU data unavailable. Suspending pose updates.')
                self.enabled = False
                return
            self.global_orientation = imu.orientation
            # replace roll and pitch with IMU values
            _, pitch, roll = euler_from_quaternion(unpack_quaternion(imu.orientation), axes='rzyx')
            yaw, _, _ = euler_from_quaternion(unpack_quaternion(pose.orientation), axes='rzyx')
            pose.orientation = Quaternion(*quaternion_from_euler(yaw, pitch, roll, axes='rzyx'))

        if self.last_pose is not None:
            # get difference
            delta_transform = get_relative_transform(
                self.last_pose.position, self.last_pose.orientation,
                pose.position, pose.orientation)

            self.enabled = True

            # hand in the update
            self.callback(delta_transform)
            if self.do_plot:
                plotting.add_transform(self, delta_transform)

        self.last_pose = pose
        self.last_pose_time = stamp
Exemple #3
0
    def __init__(self,
                 gps_topic='/mavros/global_position/global',
                 initial_heading=0.,
                 **kwargs):
        super(GPSSubscriber, self).__init__(**kwargs)
        # params
        self.gps_topic = gps_topic

        self.orig_ll = None
        self.last_position = Vector3()

        if self.do_plot and initial_heading != 0.:
            q = Quaternion(*quaternion_from_euler(0, 0, initial_heading))
            plotting.add_transform(
                self, Transform(translation=Vector3(0., 0., 0.), rotation=q))

        self.sub_gps = rospy.Subscriber(self.gps_topic, NavSatFix,
                                        self.gps_callback)
    def state_callback(self, msg):
        '''handles arrival of ORBState messages, validates queued TFs and processes them'''
        if msg.state == ORBState.OK:
            # update 'ok' time frame
            if self.first_ok_time is None:
                self.first_ok_time = msg.header.stamp
            self.last_ok_time = msg.header.stamp

            while len(self.tf_queue) > 1:  # need two or moar for a diff
                # discard an invalid TF
                if self.tf_queue[0].header.stamp < self.first_ok_time:
                    self.tf_queue.popleft()
                    continue

                # pending 'ok' state
                if self.tf_queue[0].header.stamp > self.last_ok_time or self.tf_queue[1].header.stamp > self.last_ok_time:
                    # wait for clearance
                    return

                # assume sequential timestamps
                assert(self.tf_queue[0].header.stamp <= self.tf_queue[1].header.stamp)

                # everything seems to be working fine
                if not self.enabled:
                    rospy.loginfo('ORBSLAM2Subscriber enabled')
                self.enabled = True

                # get TFs and let's go
                tf1 = self.tf_queue.popleft().transform
                tf2 = self.tf_queue[0].transform

                # get difference
                delta_transform = get_relative_transform(tf1.translation, tf1.rotation, tf2.translation, tf2.rotation)

                # hand in the update
                self.callback(delta_transform)
                if self.do_plot:
                    plotting.add_transform(self, delta_transform)

                rospy.logdebug('ORBSLAM2Subscriber: tf processed')

        else:
            # not 'ok'
            self.disable()
Exemple #5
0
    def imu_callback(self, msg):
        '''handles arrival of Imu messages
           :type msg: Imu'''
        # maintain IMU log for `get_imu_at_time`
        if self.is_imu_log_enabled:
            with self.imu_queue_mutex:
                self.imu_queue.append(msg)
                # discard old messages
                while self.imu_queue[
                        0].header.stamp + self.imu_log_duration < msg.header.stamp:
                    self.imu_queue.popleft()

        # provide rotation
        if self.callback is not None and self.last_imu is not None:

            # check if `orientation` is available (it's a bit smoother than `angular_velocity`)
            if self.last_imu.orientation_covariance[
                    0] != -1 and msg.orientation_covariance[0] != -1:
                delta_transform = get_relative_transform(
                    Vector3(), self.last_imu.orientation, Vector3(),
                    msg.orientation)

            else:
                # integrate angular velocities instead
                dt = (msg.header.stamp - self.last_imu.header.stamp).to_sec()
                translation = Vector3(
                )  # TODO: consider integrating linear acceleration
                av = msg.angular_velocity
                rotation = quaternion_from_euler(dt * av.x, dt * av.y,
                                                 dt * av.z)
                delta_transform = Transform(translation=translation,
                                            rotation=get_quaternion(rotation))

            # hand in the update
            self.callback(delta_transform)
            if self.do_plot:
                plotting.add_transform(self, delta_transform)

        self.last_imu = msg
Exemple #6
0
    def gps_callback(self, msg):
        '''handles arrival of NavSatFix messages'''
        if self.orig_ll is None:
            self.orig_ll = msg.latitude, msg.longitude

        # position difference
        x, y = latlon_to_dxdy(msg.latitude, msg.longitude, *self.orig_ll)
        z = msg.altitude
        position = Vector3(x, y, z)
        translation = get_vector3_subtraction(position, self.last_position)
        # construct a transform
        delta_transform = Transform(
            translation=translation,
            rotation=Quaternion(
                0, 0, 0, 1
            )  # The commonly-used unit quaternion that yields no rotation about the x/y/z axes is (0,0,0,1) [http://wiki.ros.org/tf2/Tutorials/Quaternions]
        )

        # hand in the update
        self.callback(delta_transform)
        if self.do_plot:
            plotting.add_transform(self, delta_transform)

        self.last_position = position