示例#1
0
    def convert_ref_frame(arm_frame, ref_frame, ref_frame_obj=Landmark()):
        '''Transforms an arm frame to a new ref. frame.

        Args:
            arm_frame (ArmState)
            ref_frame (int): One of ArmState.*
            ref_frame_obj (Landmark): As in Landmark.msg

        Returns:
            ArmState: arm_frame (passed in), but modified.
        '''
        if ref_frame == ArmState.ROBOT_BASE:
            if arm_frame.refFrame == ArmState.ROBOT_BASE:
                # Transform from robot base to itself (nothing to do).
                rospy.logdebug(
                    'No reference frame transformations needed (both ' +
                    'absolute).')
            elif arm_frame.refFrame == ArmState.OBJECT:
                # Transform from object to robot base.
                abs_ee_pose = World.transform(
                    arm_frame.ee_pose,
                    arm_frame.refFrameLandmark.name,
                    'base_link'
                )
                arm_frame.ee_pose = abs_ee_pose
                arm_frame.refFrame = ArmState.ROBOT_BASE
                arm_frame.refFrameLandmark = Landmark()
            else:
                rospy.logerr(
                    'Unhandled reference frame conversion: ' +
                    str(arm_frame.refFrame) + ' to ' + str(ref_frame))
        elif ref_frame == ArmState.OBJECT:
            if arm_frame.refFrame == ArmState.ROBOT_BASE:
                # Transform from robot base to object.
                rel_ee_pose = World.transform(
                    arm_frame.ee_pose, 'base_link', ref_frame_obj.name)
                arm_frame.ee_pose = rel_ee_pose
                arm_frame.refFrame = ArmState.OBJECT
                arm_frame.refFrameLandmark = ref_frame_obj
            elif arm_frame.refFrame == ArmState.OBJECT:
                # Transform between the same object (nothign to do).
                if arm_frame.refFrameLandmark.name == ref_frame_obj.name:
                    rospy.logdebug(
                        'No reference frame transformations needed (same ' +
                        'object).')
                else:
                    # Transform between two different objects.
                    rel_ee_pose = World.transform(
                        arm_frame.ee_pose,
                        arm_frame.refFrameLandmark.name,
                        ref_frame_obj.name
                    )
                    arm_frame.ee_pose = rel_ee_pose
                    arm_frame.refFrame = ArmState.OBJECT
                    arm_frame.refFrameLandmark = ref_frame_obj
            else:
                rospy.logerr(
                    'Unhandled reference frame conversion: ' +
                    str(arm_frame.refFrame) + ' to ' + str(ref_frame))
        return arm_frame
示例#2
0
    def testConvertFromObjToAnotherObj(self):
        arm_state = ArmState()
        arm_state.ee_pose.position.x = 0.05
        arm_state.ee_pose.position.y = 0
        arm_state.ee_pose.position.z = 0
        arm_state.ee_pose.orientation.w = 1
        arm_state.refFrame = ArmState.OBJECT
        arm_state.refFrameLandmark.name = 'landmark1'
        arm_state.refFrameLandmark.pose.position.x = 0.15
        arm_state.refFrameLandmark.pose.position.y = 0
        arm_state.refFrameLandmark.pose.position.z = 0
        arm_state.refFrameLandmark.pose.orientation.w = 1

        landmark = Landmark()
        landmark.name = 'landmark2'
        landmark.pose.position.x = 0.2
        landmark.pose.position.y = 0.1
        landmark.pose.position.z = 0
        landmark.pose.orientation.w = 1

        rel_arm_state = world.convert_ref_frame(arm_state, ArmState.OBJECT,
                                                landmark)

        self.assertAlmostEqual(rel_arm_state.ee_pose.position.x, 0)
        self.assertAlmostEqual(rel_arm_state.ee_pose.position.y, -0.1)

        # Test copy behavior for passed-in landmark
        rel_arm_state.refFrameLandmark.name = 'modified'
        self.assertNotEqual(rel_arm_state.refFrameLandmark.name, landmark.name)
示例#3
0
    def __init__(self, name, pose, dimensions, db_id):
        """
        Constructs a WorldLandmark object.
        Use bounding_box() or cloud_box() instead.

        Args:
            name (str): Name of this landmark
            pose (Pose): Pose of the landmark, in base frame
            dimensions (Vector3): Size of bounding box
            db_id (str): The MongoDB id if this is a cloud box
        """
        self._name = name
        self._pose = pose
        self._dimensions = dimensions
        self._db_id = db_id

        if self.is_bounding_box():
            self.object = Landmark(type=Landmark.TABLE_TOP,
                                   name=name,
                                   pose=pose,
                                   dimensions=dimensions,
                                   db_id='')
        elif self.is_cloud_box():
            self.object = Landmark(type=Landmark.CLOUD_BOX,
                                   name=name,
                                   pose=pose,
                                   dimensions=dimensions,
                                   db_id=db_id)
        self.int_marker = None
        self.is_removed = False

        # TODO(jstn): Move this outside.
        self.menu_handler = MenuHandler()
        self.menu_handler.insert('Remove from scene', callback=self.remove)
示例#4
0
    def testConvertFromBaseToObj(self):
        arm_state = ArmState()
        arm_state.ee_pose.position.x = 0.2
        arm_state.ee_pose.position.y = 0
        arm_state.ee_pose.position.z = 0
        arm_state.ee_pose.orientation.w = 1
        arm_state.refFrame = ArmState.ROBOT_BASE
        landmark = Landmark()
        landmark.name = 'landmark1'
        landmark.pose.position.x = 0.15
        landmark.pose.position.y = 0
        landmark.pose.position.z = 0
        landmark.pose.orientation.w = 1

        rel_arm_state = world.convert_ref_frame(arm_state, ArmState.OBJECT,
                                                landmark)

        self.assertAlmostEqual(rel_arm_state.ee_pose.position.x, 0.05)
        self.assertEqual(rel_arm_state.refFrame, ArmState.OBJECT)
        self.assertEqual(rel_arm_state.refFrameLandmark.pose.position.x, 0.15)
示例#5
0
    def make_ref(self, parent):
        """Creates the reference frame for the side of an object.

        Args:
            parent (Marker)

        Returns:
            ref (Landmark)
        """
        ref = Landmark()
        ref.type = 1
        ref.pose.position.x = parent.pose.position.x
        ref.pose.position.y = parent.pose.position.y
        ref.pose.position.z = parent.pose.position.z
        ref.pose.orientation.x = parent.pose.orientation.x
        ref.pose.orientation.y = parent.pose.orientation.y
        ref.pose.orientation.z = parent.pose.orientation.z
        ref.pose.orientation.w = parent.pose.orientation.w
        ref.name = parent.ns + " Ref"
        ref.dimensions.x = parent.scale.x
        ref.dimensions.y = parent.scale.y
        ref.dimensions.z = parent.scale.z
        return ref
示例#6
0
    def _get_arm_states(self):
        '''Returns the current arms states as a list of two ArmStates.

        Returns:
            [ArmState]: A list (of length two, one for each arm) of
                ArmState objects. Right first, then left.
        '''
        # TODO(mbforbes): Perhaps this entire method should go in
        # the Arms class?
        abs_ee_poses = [
            Arms.get_ee_state(Side.RIGHT),  # (Pose)
            Arms.get_ee_state(Side.LEFT)
        ]  # (Pose)
        joint_poses = [
            Arms.get_joint_state(Side.RIGHT),  # ([float64])
            Arms.get_joint_state(Side.LEFT)
        ]  # ([float64])

        states = [None, None]
        rel_ee_poses = [None, None]

        for arm_index in [Side.RIGHT, Side.LEFT]:
            nearest_obj = self._world.get_nearest_object(
                abs_ee_poses[arm_index])
            if not self._world.has_objects() or nearest_obj is None:
                # Arm state is absolute (relative to robot's base_link).
                states[arm_index] = ArmState(
                    ArmState.ROBOT_BASE,  # refFrame (uint8)
                    abs_ee_poses[arm_index],  # ee_pose (Pose)
                    joint_poses[arm_index],  # joint_pose ([float64])
                    Landmark()  # refFrameLandmark (Landmark)
                )
            else:
                # Arm state is relative (to some object in the world).
                arm_frame = ArmState()
                arm_frame.ee_pose = abs_ee_poses[arm_index]
                arm_frame.refFrame = ArmState.ROBOT_BASE
                rel_arm_frame = world.convert_ref_frame(
                    arm_frame, ArmState.OBJECT, nearest_obj)
                rel_ee_poses[arm_index] = rel_arm_frame.ee_pose
                states[arm_index] = ArmState(
                    ArmState.OBJECT,  # refFrame (uint8)
                    rel_ee_poses[arm_index],  # ee_pose (Pose)
                    joint_poses[arm_index],  # joint_pose [float64]
                    nearest_obj  # refFrameLandmark (Landmark)
                )
        return states
示例#7
0
 def __init__(self, pose, index, dimensions, is_recognized):
     '''
     Args:
         pose (Pose): Position of bounding box
         index (int): For naming object in world (e.g. "thing 0")
         dimensions (Vector3): Size of bounding box
         is_recognized (bool): Result of object recognition.
     '''
     self.index = index
     self.assigned_name = None
     self.is_recognized = is_recognized
     self.object = Landmark(
         Landmark.TABLE_TOP, self.get_name(), pose, dimensions)
     self.menu_handler = MenuHandler()
     self.int_marker = None
     self.is_removed = False
     self.menu_handler.insert('Remove from scene', callback=self.remove)
示例#8
0
    def _set_ref(self, new_ref_name):
        '''Changes the reference frame of the action step to
        new_ref_name.

        Args:
            new_ref_name
        '''
        # Get the id of the new ref (an int).
        new_ref = World.get_ref_from_name(new_ref_name)
        if new_ref != ArmState.ROBOT_BASE:
            index = ActionStepMarker._ref_names.index(new_ref_name)
            new_ref_obj = ActionStepMarker._ref_object_list[index - 1]
        else:
            new_ref_obj = Landmark()

        if self.action_step.type == ActionStep.ARM_TARGET:
            # Handle "normal" steps (saved poses).
            t = self.action_step.armTarget
            if self.arm_index == Side.RIGHT:
                t.rArm = World.convert_ref_frame(t.rArm, new_ref, new_ref_obj)
            else:
                t.lArm = World.convert_ref_frame(t.lArm, new_ref, new_ref_obj)
        elif self.action_step.type == ActionStep.ARM_TRAJECTORY:
            # Handle trajectory steps.
            t = self.action_step.armTrajectory
            arm = t.rArm if self.arm_index == Side.RIGHT else t.lArm
            for i in range(len(arm)):
                arm_old = arm[i]
                arm_new = World.convert_ref_frame(arm_old, new_ref,
                                                  new_ref_obj)
                arm[i] = arm_new
            # Fix up reference frames.
            if self.arm_index == Side.RIGHT:
                t.rRefFrameLandmark = new_ref_obj
                t.rRefFrame = new_ref
            else:
                t.lRefFrameLandmark = new_ref_obj
                t.lRefFrame = new_ref
示例#9
0
    def _find_dominant_ref(self, arm_traj, frame_list):
        '''Finds the most dominant reference frame in a continuous
        trajectory.

        Args:
            arm_traj (ArmState[]): List of arm states that form the arm
                trajectory.
            frame_list ([Landmark]): List of Landmark (as defined by
                Landmark.msg), the current reference frames.

        Returns:
            (int, Landmark): Tuple of the dominant reference frame's
                number (as one of the constants available in ArmState to
                be set as ArmState.refFrame) and Landmark (as in
                Landmark.msg).
        '''
        # Cycle through all arm states and check their reference frames.
        # Whichever one is most frequent becomes the dominant one.
        robot_base = Landmark(name=BASE_LINK)
        ref_counts = Counter()
        for arm_state in arm_traj:
            # We only track objects that
            if arm_state.refFrame == ArmState.ROBOT_BASE:
                ref_counts[robot_base] += 1
            elif arm_state.refFrameLandmark in frame_list:
                ref_counts[arm_state.refFrameLandmark] += 1
            else:
                rospy.logwarn('Ignoring object with reference frame name ' +
                              arm_state.refFrameLandmark.name +
                              ' because the world does not have this object.')

        # Get most common obj.
        dominant_ref_obj = ref_counts.most_common(1)[0][0]

        # Find the frame number (int) and return with the object.
        return world.get_ref_from_name(dominant_ref_obj.name), dominant_ref_obj
示例#10
0
    def _execute_action(self, __=None, preregistered_landmarks=[]):
        '''Starts the execution of the current action.

        This saves the action before starting it.

        Args:
            __ (Landmark): unused, default: None
            preregistered_landmarks: A list of Landmarks.
                Landmarks in this list are expected to be custom landmarks
                with a name. We will skip searching for these landmarks.
                Other landmarks that are part of the action that are not
                pre-registered must be searched for using
                custom_landmark_finder.

        Returns:
            [str, int]: a speech response and a GazeGoal.* constant
        '''
        # We must *have* a current action.
        if self.session.n_actions <= 0:
            return [RobotSpeech.ERROR_NO_SKILLS, GazeGoal.SHAKE]

        # We must have also recorded steps (/poses/frames) in it.
        if self.session.n_frames() < 1:
            return [
                RobotSpeech.EXECUTION_ERROR_NOPOSES + ' ' +
                str(self.session.current_action_id), GazeGoal.SHAKE
            ]

        # Save current action to disk (rosbag)
        # TODO(jstn): Not sure if this works or is necessary anymore.
        self.session.save_current_action()
        current_action = self.session.get_current_action()
        rospy.loginfo('Executing action {}'.format(current_action.name))
        self._world.clear_all_objects()

        # Check if we need to find tabletop objects in this action.
        if current_action.is_tabletop_object_required():
            # Find tabletop objects
            if self._world.update_object_pose():
                self._world.update()
            else:
                # An object is required, but we didn't get it.
                return [RobotSpeech.OBJECT_NOT_DETECTED, GazeGoal.SHAKE]

        custom_landmarks = current_action.custom_landmarks()
        rospy.loginfo('Custom landmarks: {}'.format(', '.join(
            [l.name for l in custom_landmarks])))
        prereg_str = ', '.join([
            '{} ({})'.format(l.name, l.db_id) for l in preregistered_landmarks
        ])
        rospy.loginfo('Pre-registered landmarks: {}'.format(prereg_str))
        if len(custom_landmarks) > 0:
            preregistered = {}
            for landmark in preregistered_landmarks:
                preregistered[landmark.name] = landmark
            registered_landmarks = {}  # Maps db_ids to Landmarks
            for landmark in custom_landmarks:
                # Just in case custom_landmarks() returns duplicates
                if landmark.name in registered_landmarks:
                    continue
                if landmark.name in preregistered:
                    registered_landmarks[landmark.name] = preregistered[
                        landmark.name]
                    continue

                # Move head to look at where the custom landmark was at
                # demonstration time -- we assume that it is roughly in the
                # same location at run time.
                # Assumes that the landmark pose is given in the base frame.
                #Response.force_look_at_point(landmark.pose.position)
                if not Response.gaze_client.wait_for_result(
                        rospy.Duration(10)):
                    rospy.logwarn('Took longer than 10 seconds to look down.')
                rospy.sleep(2)
                rospy.loginfo('Searching for landmark: {}, ID: {}'.format(
                    landmark.name, landmark.db_id))
                matches = self._custom_landmark_finder.find(
                    None, landmark.name)
                if matches is None or len(matches) == 0:
                    rospy.logwarn('Could not find landmark: {}'.format(
                        landmark.name))
                    return [RobotSpeech.OBJECT_NOT_DETECTED, GazeGoal.SHAKE]
                rospy.logwarn('Picking best of {} matches'.format(
                    len(matches)))
                best_match = None
                for match in matches:
                    if best_match is None or match.error < best_match.error:
                        best_match = match
                registered_landmark = Landmark(type=Landmark.CLOUD_BOX,
                                               name=landmark.name,
                                               pose=best_match.pose,
                                               dimensions=landmark.dimensions,
                                               db_id=landmark.db_id)
                registered_landmarks[landmark.db_id] = registered_landmark
            for db_id, landmark in registered_landmarks.items():
                world_landmark = WorldLandmark(landmark.name, landmark.pose,
                                               landmark.dimensions,
                                               landmark.db_id)
                self._world.add_landmark(world_landmark)

        if current_action.is_tabletop_object_required(
        ) or len(custom_landmarks) > 0:
            current_action.update_objects(self._world.get_frame_list())

        self.arms.start_execution(current_action, EXECUTION_Z_OFFSET)

        # Reply: starting execution.
        return [
            RobotSpeech.START_EXECUTION + ' ' +
            str(self.session.current_action_id), None
        ]
示例#11
0
def convert_ref_frame(arm_state, ref_frame, ref_frame_obj=Landmark()):
    """Transforms an arm frame to a new ref. frame.

    Args:
        arm_state (ArmState): The arm state to transform
        ref_frame (int): One of ArmState.*, the desired reference frame to
            transform into.
        ref_frame_obj (Landmark): The landmark to transform relative to.

    Returns:
        ArmState: A copy of arm_state, but transformed.
    """
    output_state = copy.deepcopy(arm_state)
    ref_frame_obj_copy = copy.deepcopy(ref_frame_obj)
    if ref_frame == ArmState.ROBOT_BASE:
        if arm_state.refFrame == ArmState.ROBOT_BASE:
            pass  # Nothing to do
        elif arm_state.refFrame == ArmState.OBJECT:
            # Transform from object to robot base.
            ee_in_obj = get_matrix_from_pose(arm_state.ee_pose)
            obj_pose = arm_state.refFrameLandmark.pose  # In base frame
            obj_to_base = get_matrix_from_pose(obj_pose)
            abs_ee_pose = get_pose_from_transform(
                np.dot(obj_to_base, ee_in_obj))
            output_state.ee_pose = abs_ee_pose
            output_state.refFrame = ArmState.ROBOT_BASE
            output_state.refFrameLandmark = Landmark()
        else:
            rospy.logerr(
                'Unhandled reference frame conversion: {} to {}'.format(
                    arm_state.refFrame, ref_frame))
    elif ref_frame == ArmState.OBJECT:
        if arm_state.refFrame == ArmState.ROBOT_BASE:
            # Transform from robot base to provided object.
            arm_in_base = get_matrix_from_pose(arm_state.ee_pose)
            base_to_obj = np.linalg.inv(
                get_matrix_from_pose(ref_frame_obj.pose))
            rel_ee_pose = get_pose_from_transform(
                np.dot(base_to_obj, arm_in_base))
            output_state.ee_pose = rel_ee_pose
            output_state.refFrame = ArmState.OBJECT
            output_state.refFrameLandmark = ref_frame_obj_copy
        elif arm_state.refFrame == ArmState.OBJECT:
            if arm_state.refFrameLandmark.name == ref_frame_obj.name:
                pass  # Nothing to do
            else:
                # Transform from arm state's object to provided object.
                ee_in_source_obj = get_matrix_from_pose(arm_state.ee_pose)
                source_obj_to_base = get_matrix_from_pose(
                    arm_state.refFrameLandmark.pose)
                base_to_target_obj = np.linalg.inv(
                    get_matrix_from_pose(ref_frame_obj.pose))
                rel_ee_pose = get_pose_from_transform(
                    np.dot(np.dot(base_to_target_obj, source_obj_to_base),
                           ee_in_source_obj))
                output_state.ee_pose = rel_ee_pose
                output_state.refFrame = ArmState.OBJECT
                output_state.refFrameLandmark = ref_frame_obj_copy
        else:
            rospy.logerr(
                'Unhandled reference frame conversion: {} to {}'.format(
                    arm_state.refFrame, ref_frame))
    return output_state