Configure Complex Kinematic Chains

Many components have complex kinematic chains and require an additional set of intermediate reference frames to use Viam’s Motion service.

  • 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().

If you want to implement a component with a complex kinematic chain that is not already built into the RDK, you need to add a file to your driver that details the attachment of the intermediate reference frames on the component.

This file can be a .json file in the same format as Viam’s built-in arm drivers, or an .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.

This is an example .json configuration as used by Viam’s Universal Robots arm driver:

{
    "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
        }
    ]
}


Have questions, or want to meet other people working on robots? Join our Community Discord.