예제 #1
0
    def __init__(self, manipulator, interface=None, base_link=None, end_effector_link=None, control_type='position',
                 gripper=None, bounding_box=None, use_orientation=True, hand='right', position='relative',
                 priority=None, verbose=False):
        """

        Args:
            manipulator (Manipulator): manipulator robot instance.
            interface (None, LeapMotionInterface): LeapMotion interface. If None, it will create one.
            base_link (int, str): base link id or name.
            end_effector_link (int, str): end effector link id or name.
            control_type (str): type of control to use, select between {'position', 'impedance'}.
            gripper (None, Gripper): gripper robot instance.
            bounding_box (None, np.array[float[2,3]]): bounding box limits.
            use_orientation (bool): if we should account for the orientation of the end-effector as well using the
              interface.
            hand (str): the hand that we will use to move the end-effector, select between {'right', 'left'}.
            position (str): if the position of the hand should be absolute or relative when moving the end-effector.
              If relative, by moving the hand from the center it will compute the distance from it and move the
              end-effector accordingly. Note that the orientation is always absolute here.
            priority (int): priority of the bridge.
            verbose (bool): If True, print information on the standard output.
        """
        # set manipulator
        self.manipulator = manipulator
        self.gripper = gripper
        self.base_link = -1 if base_link is None else base_link
        self.distal_link = manipulator.get_end_effector_ids(end_effector=0) if end_effector_link is None \
            else end_effector_link
        self.use_orientation = use_orientation
        self.hand_type = Hand.RIGHT if hand == 'right' else Hand.LEFT
        self.position_type = Position.RELATIVE if position == 'relative' else Position.ABSOLUTE
        self.grasp_strength = 5

        # if interface not defined, create one.
        if interface is None:
            interface = LeapMotionInterface(bounding_box=bounding_box, verbose=verbose)
        if not isinstance(interface, LeapMotionInterface):
            raise TypeError("Expecting the given 'interface' to be an instance of `LeapMotionInterface`, but got "
                            "instead: {}".format(type(interface)))

        # create controller
        model = RobotModelInterface(manipulator)
        x_des = self.manipulator.get_link_positions(link_ids=end_effector_link, wrt_link_id=base_link)
        if control_type == 'position':
            task = CartesianTask(model, distal_link=end_effector_link, base_link=base_link, desired_position=x_des,
                                 kp_position=50.)
            control_type = ControlType.POSITION
        elif control_type == 'impedance':
            task = CartesianImpedanceControlTask(model, distal_link=end_effector_link, base_link=base_link,
                                                 desired_position=x_des, kp_position=100, kd_linear=60)
            control_type = ControlType.IMPEDANCE
        else:
            raise NotImplementedError("Please select between {'position', 'impedance'} for the control_type.")

        self._task = task
        self._control_type = control_type
        self._solver = QPTaskSolver(task=task)

        # call superclass
        super(BridgeLeapMotionManipulator, self).__init__(interface, priority, verbose=verbose)
예제 #2
0
    def __init__(self, manipulator, interface, base_link=None, end_effector_link=None, control_type='position',
                 gripper=None, translation_scale=1., rotation_step=0.001, use_orientation=False,
                 priority=None, verbose=False):
        """
        Initialize the bridge between the Controller and a manipulator's end-effector.

        Args:
            manipulator (Manipulator): manipulator robot instance.
            interface (GameControllerInterface): Game controller interface.
            base_link (int, str): base link id or name. If None, it will be set to -1 (the base)
            end_effector_link (int, str): end effector link id or name. If None, it will take the first end-effector.
            control_type (str): type of control to use, select between {'position', 'impedance'}.
            gripper (None, Gripper): gripper robot instance.
            translation_scale (float): translation scale coefficient. It will multiply the value by translation offset
              by that value when moving the joysticks.
            rotation_step (float): rotation step value. As long as we keep pushing on the corresponding buttons, it
              will increment the angles by that step value.
            use_orientation (bool): if we should account for the orientation of the end-effector as well using the
              interface.
            priority (int): priority of the bridge.
            verbose (bool): If True, print information on the standard output.
        """
        # set manipulator
        self.manipulator = manipulator
        self.gripper = gripper
        self.base_link = -1 if base_link is None else base_link
        self.distal_link = manipulator.get_end_effector_ids(end_effector=0) if end_effector_link is None \
            else end_effector_link
        self.use_orientation = use_orientation
        self.grasp_strength = 0

        self.translation_scale = translation_scale
        self.rotation_step = rotation_step

        # check the game controller interface
        if not isinstance(interface, GameControllerInterface):
            raise TypeError("Expecting the given 'interface' to be an instance of `GameControllerInterface`, but got "
                            "instead: {}".format(type(interface)))

        # create controller
        model = RobotModelInterface(manipulator)
        x_des = self.manipulator.get_link_positions(link_ids=end_effector_link, wrt_link_id=base_link)
        if control_type == 'position':
            task = CartesianTask(model, distal_link=end_effector_link, base_link=base_link, desired_position=x_des,
                                 kp_position=50.)
            control_type = ControlType.POSITION
        elif control_type == 'impedance':
            task = CartesianImpedanceControlTask(model, distal_link=end_effector_link, base_link=base_link,
                                                 desired_position=x_des, kp_position=100, kd_linear=60)
            control_type = ControlType.IMPEDANCE
        else:
            raise NotImplementedError("Please select between {'position', 'impedance'} for the control_type.")

        self._task = task
        self._control_type = control_type
        self._solver = QPTaskSolver(task=task)

        # call superclass
        super(BridgeControllerManipulator, self).__init__(interface, priority, verbose=verbose)
예제 #3
0
    def __init__(self,
                 model,
                 distal_link,
                 base_link=None,
                 desired_wrench=0.,
                 kp=1.,
                 weight=1.,
                 constraints=[]):
        """
        Initialize the task.

        Args:
            model (ModelInterface): model interface.
            distal_link (int, str): distal link id or name.
            base_link (int, str, None): base link id or name. If None, it will be the base root link.
            desired_wrench (float, np.array[float[6]]): desired wrench (force and torque) in the base link of reference
              frame.
            kp (float, np.array[float[6,6]]): proportional gain = compliance matrix.
            weight (float, np.array[float[6,6]]): weight scalar or matrix associated to the task.
            constraints (list[Constraint]): list of constraints associated with the task.
        """
        super(InteractionTask, self).__init__(model=model,
                                              weight=weight,
                                              constraints=constraints)

        # set variables
        self.distal_link = self.model.get_link_id(distal_link)
        self.base_link = self.model.get_link_id(
            base_link) if base_link is not None else base_link

        self.desired_wrench = desired_wrench
        self.wrench = None  # measured wrench
        self.kp = kp

        # create sub-task
        self._task = CartesianTask(model,
                                   distal_link=distal_link,
                                   base_link=base_link,
                                   weight=weight)
예제 #4
0
class InteractionTask(JointVelocityTask):
    r"""Interaction Task

    From the documentation of the framework of [1]: "the `InteractionTask` class implements an admittance based force
    control using the admittance law:

    .. math::

        dx = K_p (w_d - w) \\
        x_d = x + dx

    where :math:`w_d \in \mathbb{R}^6` is the desired wrench in some base_link frame, :math:`w` is the measured wrench
    transformed from the Force/Torque sensor frame to the base_link frame. The displacement :math:`dx` is integrated
    using the previous position :math:`x`, and a new desired position :math:`x_d` is computed. The references
    :math:`x_d` and :math:`dx` are then used inside a Cartesian task (see ``CartesianTask``).

    Warnings: the :math:`w_d` is the desired wrench that the robot has to exert on the environment, so the measured
    wrench :math:`w` is the wrench produced by the robot on the environment (and not the opposite)!"


    The implementation of this class is inspired by [1] (which is licensed under the LGPLv2).

    References:
        - [1] "OpenSoT: A whole-body control library for the compliant humanoid robot COMAN", Rocchi et al., 2015
    """
    def __init__(self,
                 model,
                 distal_link,
                 base_link=None,
                 desired_wrench=0.,
                 kp=1.,
                 weight=1.,
                 constraints=[]):
        """
        Initialize the task.

        Args:
            model (ModelInterface): model interface.
            distal_link (int, str): distal link id or name.
            base_link (int, str, None): base link id or name. If None, it will be the base root link.
            desired_wrench (float, np.array[float[6]]): desired wrench (force and torque) in the base link of reference
              frame.
            kp (float, np.array[float[6,6]]): proportional gain = compliance matrix.
            weight (float, np.array[float[6,6]]): weight scalar or matrix associated to the task.
            constraints (list[Constraint]): list of constraints associated with the task.
        """
        super(InteractionTask, self).__init__(model=model,
                                              weight=weight,
                                              constraints=constraints)

        # set variables
        self.distal_link = self.model.get_link_id(distal_link)
        self.base_link = self.model.get_link_id(
            base_link) if base_link is not None else base_link

        self.desired_wrench = desired_wrench
        self.wrench = None  # measured wrench
        self.kp = kp

        # create sub-task
        self._task = CartesianTask(model,
                                   distal_link=distal_link,
                                   base_link=base_link,
                                   weight=weight)

    ##############
    # Properties #
    ##############

    @property
    def desired_wrench(self):
        """Get the desired wrench."""
        return self._desired_wrench

    @desired_wrench.setter
    def desired_wrench(self, wrench):
        """Set the desired wrench."""
        if wrench is None:
            wrench = np.zeros(6)
        elif isinstance(wrench, (float, int)):
            wrench = wrench * np.ones(6)
        if not isinstance(wrench, (list, tuple, np.ndarray)):
            raise TypeError(
                "Expecting the given 'desired_wrench' to be a tuple/list of np.array, or a np.array, "
                "but got instead: {}".format(type(wrench)))
        self._desired_wrench = np.asarray(wrench).reshape(
            -1)  # (N*6,) or (N*3,)

    @property
    def wrench(self):
        """Get the current wrench."""
        return self._wrench

    @wrench.setter
    def wrench(self, wrench):
        """Set the current wrench expressed in the base link of reference frame."""
        if wrench is not None:
            if not isinstance(wrench, (list, tuple, np.ndarray)):
                raise TypeError(
                    "Expecting the given 'desired_wrench' to be a tuple/list of np.array, or a np.array, "
                    "but got instead: {}".format(type(wrench)))
            wrench = np.asarray(wrench).reshape(-1)  # (6,) or (3,)
        self._wrench = wrench

        # enable / disable the tasks based on if the wrench was provided or not
        if self._wrench is None:
            self.disable()
        else:
            self.enable()

    @property
    def kp(self):
        """Return the proportional gain / compliance matrix."""
        return self._kp

    @kp.setter
    def kp(self, kp):
        """Set the proportional gain / compliance matrix."""
        if kp is None:
            kp = 1.
        if not isinstance(kp, (float, int, np.ndarray)):
            raise TypeError(
                "Expecting the given compliance matrix gain kp to be an int, float, np.array, instead "
                "got: {}".format(type(kp)))
        if isinstance(kp, np.ndarray) and kp.shape != (6, 6):
            raise ValueError(
                "Expecting the given compliance matrix gain kp to be of shape {}, but instead "
                "got shape: {}".format((6, 6), kp.shape))
        self._kp = kp

    ###########
    # Methods #
    ###########

    def _update(self, x=None):
        """
        Update the task by computing the A matrix and b vector that will be used by the task solver.
        """
        x = self.model.get_pose(link=self.distal_link, wrt_link=self.base_link)
        dx = np.dot(self.kp, (self.desired_wrench - self.wrench))

        # update cartesian task
        self._task.set_desired_references(x_des=x, dx_des=dx)
        self._task.update()
        self._A = self._task.A
        self._b = self._task.b

        # set wrench to None
        self._wrench = None
    def __init__(self, manipulator, interface=None, base_link=None, end_effector_link=None, control_type='position',
                 gripper=None, translation_range=(-1, 1), rotation_range=(-1, 1), use_orientation=False,
                 priority=None, verbose=False):
        """
        Initialize the bridge between the SpaceMouse and a manipulator's end-effector.

        Args:
            manipulator (Manipulator): manipulator robot instance.
            interface (None, SpaceMouseInterface): SpaceMouse interface. If None, it will create one.
            base_link (int, str): base link id or name. If None, it will be set to -1 (the base)
            end_effector_link (int, str): end effector link id or name. If None, it will take the first end-effector.
            control_type (str): type of control to use, select between {'position', 'impedance'}.
            gripper (None, Gripper): gripper robot instance.
            translation_range (np.array[float[2]], np.array[float[2,3]], tuple[float[2]],
              tuple[np.array[float[3]][2]]): the lower and higher bounds for the (x, y, z). This is used to normalize
              the translation range to be between [-1, 1]. The frame (x,y,z) is defined with x pointing forward, y to
              the left, and z up.
            rotation_range (np.array[float[2]], np.array[float[2,3]], tuple[float[2]], tuple[np.array[3][2]]): the
              lower and higher bounds for the roll-pitch-yaw angles. This is used to normalize the rotation range to
              be between [-1, 1]. The frame (x,y,z) is defined with x pointing forward, y to the left, and z up.
            use_orientation (bool): if we should account for the orientation of the end-effector as well using the
              interface.
            priority (int): priority of the bridge.
            verbose (bool): If True, print information on the standard output.
        """
        # set manipulator
        self.manipulator = manipulator
        self.gripper = gripper
        self.base_link = -1 if base_link is None else base_link
        self.distal_link = manipulator.get_end_effector_ids(end_effector=0) if end_effector_link is None \
            else end_effector_link
        self.use_orientation = use_orientation
        self.grasp_strength = 0

        # if interface not defined, create one.
        if interface is None:
            interface = SpaceMouseInterface(verbose=verbose, translation_range=translation_range,
                                            rotation_range=rotation_range)
        if not isinstance(interface, SpaceMouseInterface):
            raise TypeError("Expecting the given 'interface' to be an instance of `SpaceMouseInterface`, but got "
                            "instead: {}".format(type(interface)))

        # create controller
        model = RobotModelInterface(manipulator)
        x_des = self.manipulator.get_link_positions(link_ids=end_effector_link, wrt_link_id=base_link)
        if control_type == 'position':
            task = CartesianTask(model, distal_link=end_effector_link, base_link=base_link, desired_position=x_des,
                                 kp_position=50.)
            control_type = ControlType.POSITION
        elif control_type == 'impedance':
            task = CartesianImpedanceControlTask(model, distal_link=end_effector_link, base_link=base_link,
                                                 desired_position=x_des, kp_position=100, kd_linear=60)
            control_type = ControlType.IMPEDANCE
        else:
            raise NotImplementedError("Please select between {'position', 'impedance'} for the control_type.")

        self._task = task
        self._control_type = control_type
        self._solver = QPTaskSolver(task=task)

        # call superclass
        super(BridgeSpaceMouseManipulator, self).__init__(interface, priority, verbose=verbose)
예제 #6
0
    def __init__(self,
                 manipulator,
                 interface=None,
                 base_link=None,
                 end_effector_link=None,
                 control_type='position',
                 gripper=None,
                 translation_step=0.001,
                 rotation_step=0.001,
                 use_orientation=False,
                 priority=None,
                 verbose=False):
        """
        Initialize the bridge between the mouse+keyboard interface and a manipulator's end-effector.

        Args:
            manipulator (Manipulator): manipulator robot instance.
            interface (None, SpaceMouseInterface): SpaceMouse interface. If None, it will create one.
            base_link (int, str): base link id or name. If None, it will be set to -1 (the base)
            end_effector_link (int, str): end effector link id or name. If None, it will take the first end-effector.
            control_type (str): type of control to use, select between {'position', 'impedance'}.
            gripper (None, Gripper): gripper robot instance.
            translation_step (float): translation step value. As long as we keep pushing on the corresponding buttons,
              it will increment the positions by that step value.
            rotation_step (float): rotation step value. As long as we keep pushing on the corresponding buttons, it
              will increment the angles by that step value.
            use_orientation (bool): if we should account for the orientation of the end-effector as well using the
              interface.
            priority (int): priority of the bridge.
            verbose (bool): If True, print information on the standard output.
        """
        # set manipulator
        self.manipulator = manipulator
        self.gripper = gripper
        self.base_link = -1 if base_link is None else base_link
        self.distal_link = manipulator.get_end_effector_ids(end_effector=0) if end_effector_link is None \
            else end_effector_link
        self.use_orientation = use_orientation
        self.grasp_strength = 0

        self.translation_step = translation_step
        self.rotation_step = rotation_step

        # if interface not defined, create one.
        if not isinstance(interface, MouseKeyboardInterface):
            interface = MouseKeyboardInterface(self.simulator)

        # create controller
        model = RobotModelInterface(manipulator)
        x_des = self.manipulator.get_link_positions(link_ids=end_effector_link,
                                                    wrt_link_id=base_link)
        if control_type == 'position':
            task = CartesianTask(model,
                                 distal_link=end_effector_link,
                                 base_link=base_link,
                                 desired_position=x_des,
                                 kp_position=50.)
            control_type = ControlType.POSITION
        elif control_type == 'impedance':
            task = CartesianImpedanceControlTask(model,
                                                 distal_link=end_effector_link,
                                                 base_link=base_link,
                                                 desired_position=x_des,
                                                 kp_position=100,
                                                 kd_linear=60)
            control_type = ControlType.IMPEDANCE
        else:
            raise NotImplementedError(
                "Please select between {'position', 'impedance'} for the control_type."
            )

        self._task = task
        self._control_type = control_type
        self._solver = QPTaskSolver(task=task)

        # call superclass
        super(BridgeMouseKeyboardManipulator, self).__init__(interface,
                                                             priority,
                                                             verbose=verbose)