Kinematics | Reference

Kinematics

A kinematics file describes your arm’s physical structure (link lengths, joint axes, joint limits) so the motion planner can solve the inverse kinematics problem: given a target pose, find joint angles that reach it.

Most arms handle this automatically

Most arm modules in the Viam registry include a kinematics file. For standard commercial arms like the UR5e, xArm6, or Viam Arm, the module handles kinematics automatically; you do not need to provide or configure a kinematics file. Read this page if you are building a custom arm, using a module without a built-in kinematics file, or verifying that a kinematics model matches your physical arm.

Concepts

Forward and inverse kinematics

Forward kinematics computes the end effector’s pose from the current joint angles. Walk the chain from base to end, applying each joint’s rotation and each link’s length; the result is deterministic. GetEndPosition runs forward kinematics internally.

Inverse kinematics answers the reverse question: given a target position and orientation for the end effector, what joint angles will get the arm there? This is harder because there may be zero, one, or many solutions. The arm might be able to reach the same point with the elbow up or elbow down, or it might not be able to reach the point at all. Viam’s motion planner uses inverse kinematics internally when you call Move.

Links and joints

A robot arm is modeled as a chain of rigid bodies (links) connected by joints:

Joint limits

Every joint has limits that define its range of motion:

Joint limits prevent the motion planner from computing solutions that would require the arm to bend past its physical limits.

Kinematics file formats

Viam supports two kinematics file formats at the API level:

Format Description When to use
SVA (Spatial Vector Algebra) Viam’s native JSON format When writing a Viam kinematics file directly.
URDF XML format used by ROS and many manufacturers When the manufacturer ships a URDF and you want to reuse it.

GetKinematics returns one of these two formats. Viam’s SVA schema also accepts Denavit-Hartenberg parameters inline, as a convenience when you are converting a textbook DH table; DH is not a third API-level format.

Most registry arm modules use SVA internally. You rarely need to write a kinematics file from scratch unless you are building a custom arm.

Tool center point (TCP)

The tool center point is the reference point on the end effector. By default, it is at the last link’s origin. If you attach a gripper or tool, you may need to define an offset so the TCP reflects the actual point of interaction (for example, the tip of a gripper or the center of a suction cup). This offset is configured through the frame system, not the kinematics file.

Steps

1. Check if your arm has a built-in kinematics file

Most arm modules in the Viam registry ship with a kinematics file built into the module. The module loads and applies the kinematics automatically when viam-server starts.

Verify this by calling GetKinematics:

from viam.components.arm import Arm

arm = Arm.from_robot(machine, "my-arm")
kinematics = await arm.get_kinematics()
print(f"Kinematics format: {kinematics[0]}")
# kinematics[1] contains the raw kinematics data
myArm, err := arm.FromProvider(machine, "my-arm")
if err != nil {
    logger.Fatal(err)
}

model, err := myArm.Kinematics(ctx)
if err != nil {
    logger.Fatal(err)
}
fmt.Printf("Arm model: %s with %d DoF\n", model.Name(), len(model.DoF()))

If this call succeeds and returns data, your arm module has kinematics built in. Proceed to step 4 to read joint and end effector data.

If the call fails or returns empty data, the module does not include kinematics. You will need to provide a kinematics file (steps 2-3).

2. Understand the SVA kinematics format

The SVA format describes the arm as a sequence of links and joints in JSON. Here is a simplified example for a two-joint arm:

{
  "name": "MyArm",
  "kinematic_param_type": "SVA",
  "links": [
    {
      "id": "base_link",
      "parent": "world",
      "translation": { "x": 0, "y": 0, "z": 162.5 },
      "geometry": {
        "type": "box",
        "x": 120,
        "y": 120,
        "z": 260,
        "translation": { "x": 0, "y": 0, "z": 130 }
      }
    },
    {
      "id": "upper_arm_link",
      "parent": "shoulder_pan_joint",
      "translation": { "x": 0, "y": 0, "z": 245.0 }
    }
  ],
  "joints": [
    {
      "id": "shoulder_pan_joint",
      "type": "revolute",
      "parent": "base_link",
      "axis": { "x": 0, "y": 0, "z": 1 },
      "min": -360,
      "max": 360
    },
    {
      "id": "shoulder_lift_joint",
      "type": "revolute",
      "parent": "upper_arm_link",
      "axis": { "x": 0, "y": 1, "z": 0 },
      "min": -360,
      "max": 360
    }
  ]
}

Each field:

3. Import a URDF file

If your arm manufacturer provides a URDF file, you can reference it in your arm module’s configuration. URDF (Unified Robot Description Format) is an XML format that describes links, joints, visual meshes, and collision geometry.

A typical URDF structure:

<robot name="my_arm">
  <link name="base_link">
    <visual>
      <geometry><cylinder length="0.1" radius="0.05"/></geometry>
    </visual>
    <collision>
      <geometry><cylinder length="0.1" radius="0.05"/></geometry>
    </collision>
  </link>
  <joint name="shoulder_pan" type="revolute">
    <parent link="base_link"/>
    <child link="upper_arm"/>
    <axis xyz="0 0 1"/>
    <limit lower="-3.14" upper="3.14" velocity="1.0"/>
  </joint>
</robot>

To use a URDF file with your arm module, place the file in a location accessible to viam-server and reference it in the module’s configuration. The exact configuration depends on the module. Consult the module’s documentation for the specific attribute name.

4. Verify kinematics in the 3D SCENE tab

The Viam app can render a 3D visualization of your arm based on its kinematic model:

  1. Navigate to your machine in the Viam app.
  2. Click the 3D SCENE tab.
  3. The arm should appear as a 3D model with joints and links.

Verify the visualization by comparing it to the physical arm:

  1. Move a joint using the CONTROL tab.
  2. Switch to the 3D SCENE tab and confirm the visualization updated.
  3. Check that the joint rotated in the correct direction and by the correct amount.
  4. Repeat for each joint.

If the visualization does not match the physical arm, the kinematics file may have incorrect link lengths, joint axes, or joint limits.

For reading joint positions and controlling the arm directly, see Add an arm and the Arm API reference.

Troubleshooting

GetKinematics returns an error or empty data
Joint limits are too restrictive
3D SCENE tab does not match the physical arm

What’s next