Search code examples
drake

How to make a gripper with two fingers (2DOF) have 1 DOF making one finger symmetric to the other


I am trying to add a model of a wsg-like gripper in Drake from an SDF file. The gripper has 2 joints:

  • a prismatic joint for the left finger
  • a prismatic joint for the right finger, that I want it to mimic the left finger behaviour with a multiplier of -1.

My goal is to make this model have 1 DOF:

  • one prismatic joint for both fingers. I want to make the fingers symmetric and have one DOF for both of them.

That is, when I add only this SDF model to my plant, I want plant.num_position() to return 1, and when I edit the joint value for the left finger, I want the right finger to be displaced by the same value times -1.

How do I do this in Drake?

Is it something I need to set up in the .sdf file or with additional programming and constraints?

I have tried to use the <mimic> tag in the sdf file, but when running plant.num_positions(), it still counts both finger joints.

These are the joints I have defined in my .sdf file:

<joint name="left_finger_sliding_joint" type="prismatic">
  <parent>body</parent>
  <child>left_finger</child>
  <axis>
    <xyz>-1 0 0</xyz>
    <!-- Drake attaches an actuator to all and only joints with a nonzero
         effort limit. -->
    <limit>
      <lower>-0.055</lower>
      <upper>0</upper>
      <effort>80</effort>
      <stiffness>15000</stiffness>
    </limit>
    <dynamics>
      <spring_reference>0</spring_reference>
      <spring_stiffness>0</spring_stiffness>
      <damping>0</damping>
      <friction>0</friction>
    </dynamics>
  </axis>
</joint>

<joint name="right_finger_sliding_joint" type="prismatic">
  <parent>body</parent>
  <child>right_finger</child>
  <axis>
    <xyz>1 0 0</xyz>
    <!-- Drake attaches an actuator to all and only joints with a nonzero
         effort limit. -->
    <limit>
      <lower>0</lower>
      <upper>0.055</upper>
      <effort>80</effort>
      <stiffness>15000</stiffness>
    </limit>
    <!-- Mimic the left finger sliding joint. This will make the right
         finger move in the opposite direction of the left finger. 
         This will reduce the dimensionality of the gripper's configuration -->
    <mimic joint="left_finger_sliding_joint">
      <multiplier>-1.</multiplier>
      <offset>0.</offset>
      <reference>0.</reference>
    </mimic>
    <dynamics>
      <spring_reference>0</spring_reference>
      <spring_stiffness>0</spring_stiffness>
      <damping>0</damping>
      <friction>0</friction>
    </dynamics>
  </axis>
</joint>

Another option I have considered is welding the right_finger joint to the main body, but this would not achieve the symmetry with the left_finger.


Solution

  • Using the <mimic> tag (in sdf, or we also support it in urdf) is the recommended approach, and should give you the dynamics that you want. But you are correct that it does not reduce the num_positions(). The implementation creates both joints but implements the mimic as a constraint which the dynamics engine enforces when you step the dynamics.

    You can use MultibodyPlant::GetPositionNames() and the similar accessors for velocities and actuators to help index in and find the subset of the positions that you need.