Configure complex kinematic chains

If you are developing a new modular resource to support a component with a complex kinematic chain (for example, a new robotic arm model), you need to add a file to your driver that details the attachment of the intermediate reference frames on the component.

The motion service uses these intermediate reference frames when calculating movements.

For example, an arm has a reference frame originating where the arm is attached to a surface, but it also has links and joints whose frames of reference matter when attempting to move the arm to a pose with MoveToPosition().

This file can be a JSON file like this xArm6 file, or a .URDF file.

Kinematic parameters

Viam supports two formats for supplying kinematic parameters to configure intermediate reference frames for a kinematic chain, defined as "kinematic_param_type":

  1. Spatial Vector Algebra (SVA): supplying reference frame information for each link and each joint.
  2. Denavit-Hartenberg (DH) parameters.

Of the two methods, we prefer Spatial Vector Algebra over Denavit-Hartenberg because it allows you to specify link frames arbitrarily, which DH parameters are unable to guarantee. Additionally, if you are making your own robot and defining new drivers, incorrect SVA parameters are easier to troubleshoot than incorrect DH parameters.

This is an example configuration that is used by the ur5e arm model:

{
  "name": "UR5e",
  "kinematic_param_type": "SVA",
  "links": [
    {
      "id": "base_link",
      "parent": "world",
      "translation": {
        "x": 0,
        "y": 0,
        "z": 162.5
      },
      "geometry": {
        "x": 120,
        "y": 120,
        "z": 260,
        "translation": {
          "x": 0,
          "y": 0,
          "z": 130
        }
      }
    },
    {
      "id": "shoulder_link",
      "parent": "shoulder_pan_joint",
      "translation": {
        "x": 0,
        "y": 0,
        "z": 0
      }
    },
    {
      "id": "upper_arm_link",
      "parent": "shoulder_lift_joint",
      "translation": {
        "x": -425,
        "y": 0,
        "z": 0
      },
      "geometry": {
        "x": 550,
        "y": 150,
        "z": 120,
        "translation": {
          "x": -215,
          "y": -130,
          "z": 0
        }
      }
    },
    {
      "id": "forearm_link",
      "parent": "elbow_joint",
      "translation": {
        "x": -392.2,
        "y": 0,
        "z": 0
      },
      "geometry": {
        "x": 480,
        "y": 120,
        "z": 100,
        "translation": {
          "x": -190,
          "y": 0,
          "z": 0
        }
      }
    },
    {
      "id": "wrist_1_link",
      "parent": "wrist_1_joint",
      "translation": {
        "x": 0,
        "y": -133.3,
        "z": 0
      },
      "geometry": {
        "x": 90,
        "y": 130,
        "z": 130,
        "translation": {
          "x": 0,
          "y": -110,
          "z": 0
        }
      }
    },
    {
      "id": "wrist_2_link",
      "parent": "wrist_2_joint",
      "translation": {
        "x": 0,
        "y": 0,
        "z": -99.7
      },
      "geometry": {
        "x": 80,
        "y": 150,
        "z": 100,
        "translation": {
          "x": 0,
          "y": 0,
          "z": -100
        }
      }
    },
    {
      "id": "ee_link",
      "parent": "wrist_3_joint",
      "translation": {
        "x": 0,
        "y": -99.6,
        "z": 0
      },
      "orientation": {
        "type": "ov_degrees",
        "value": {
          "x": 0,
          "y": -1,
          "z": 0,
          "th": 90
        }
      }
    }
  ],
  "joints": [
    {
      "id": "shoulder_pan_joint",
      "type": "revolute",
      "parent": "base_link",
      "axis": {
        "x": 0,
        "y": 0,
        "z": 1
      },
      "max": 360,
      "min": -360
    },
    {
      "id": "shoulder_lift_joint",
      "type": "revolute",
      "parent": "shoulder_link",
      "axis": {
        "x": 0,
        "y": -1,
        "z": 0
      },
      "max": 360,
      "min": -360
    },
    {
      "id": "elbow_joint",
      "type": "revolute",
      "parent": "upper_arm_link",
      "axis": {
        "x": 0,
        "y": -1,
        "z": 0
      },
      "max": 180,
      "min": -180
    },
    {
      "id": "wrist_1_joint",
      "type": "revolute",
      "parent": "forearm_link",
      "axis": {
        "x": 0,
        "y": -1,
        "z": 0
      },
      "max": 360,
      "min": -360
    },
    {
      "id": "wrist_2_joint",
      "type": "revolute",
      "parent": "wrist_1_link",
      "axis": {
        "x": 0,
        "y": 0,
        "z": -1
      },
      "max": 360,
      "min": -360
    },
    {
      "id": "wrist_3_joint",
      "type": "revolute",
      "parent": "wrist_2_link",
      "axis": {
        "x": 0,
        "y": -1,
        "z": 0
      },
      "max": 360,
      "min": -360
    }
  ]
}
{
  "name": "UR5e",
  "kinematic_param_type": "DH",
  "dhParams": [
    {
      "id": "base",
      "parent": "world",
      "a": 0,
      "d": 162.5,
      "alpha": 1.57079632679,
      "max": 360,
      "min": -360
    },
    {
      "id": "shoulder",
      "parent": "base",
      "a": -425,
      "d": 0,
      "alpha": 0,
      "max": 360,
      "min": -360
    },
    {
      "id": "elbow",
      "parent": "shoulder",
      "a": -392.2,
      "d": 0,
      "alpha": 0,
      "max": 180,
      "min": -180
    },
    {
      "id": "wrist_1",
      "parent": "elbow",
      "a": 0,
      "d": 133.3,
      "alpha": 1.57079632679,
      "max": 360,
      "min": -360
    },
    {
      "id": "wrist_2",
      "parent": "wrist_1",
      "a": 0,
      "d": 99.7,
      "alpha": -1.57079632679,
      "max": 360,
      "min": -360
    },
    {
      "id": "wrist_3",
      "parent": "wrist_2",
      "a": 0,
      "d": 99.6,
      "alpha": 0,
      "max": 360,
      "min": -360
    }
  ]
}