Mobile base with arm
A mobile manipulator, a base with an arm on top, has two distinct kinds of motion: the base moves through the environment, and the arm moves within reach of the base. The frame system represents this correctly by parenting the arm to the base rather than to the world. Every arm-attached component (the gripper, a wrist camera) then inherits the base’s motion, while navigation sensors mounted directly on the base form a parallel subtree. This guide builds the full hierarchy: world to base to (arm to (gripper, wrist camera), navigation sensors).
Frame hierarchy
world
└── my-base
├── my-arm (mounted on base)
│ ├── my-gripper
│ └── wrist-camera
├── nav-camera (front-facing)
└── my-lidar
The hierarchy reflects what physically moves with what. The base’s parent is the world, so when the base drives, every frame below it shifts with it. The arm’s parent is the base, so arm motion moves the gripper and wrist camera but not the navigation sensors. This separation keeps the lidar’s reading about the floor consistent while the arm reaches for something.
Steps
1. Choose your world frame
For a mobile base, the world frame origin is typically the center of the base. All component positions are defined relative to this center point.
2. Add a frame to the base
In the Viam app, navigate to your machine and click the CONFIGURE tab. In the sidebar, click your base component to open its card. On the card, click Frame.
The Frame section opens a JSON editor (no form, parent dropdown, or geometry-type picker). Edit the JSON directly for each component below.
{
"parent": "world",
"translation": { "x": 0, "y": 0, "z": 0 },
"orientation": {
"type": "ov_degrees",
"value": { "x": 0, "y": 0, "z": 1, "th": 0 }
}
}
Click Save in the top-right of the page (or press ⌘/Ctrl+S).
3. Add a frame to the arm
In the sidebar, click your arm component to open its card. On the card, click Frame. The arm’s parent is the base, not the world frame.
Measure the offset from the center of the base to the arm’s mounting point. For an arm mounted 100 mm forward of center and 200 mm above the base center:
{
"parent": "my-base",
"translation": { "x": 0, "y": 100, "z": 200 },
"orientation": {
"type": "ov_degrees",
"value": { "x": 0, "y": 0, "z": 1, "th": 0 }
}
}
If the arm is mounted off-center to one side, include an x offset as well.
Click Save.
4. Add frames to the gripper and wrist camera
Both the gripper and wrist camera are children of the arm.
Gripper (attached directly to the end effector). In the sidebar, click your gripper component to open its card, then click Frame:
{
"parent": "my-arm",
"translation": { "x": 0, "y": 0, "z": 0 },
"orientation": {
"type": "ov_degrees",
"value": { "x": 0, "y": 0, "z": 1, "th": 0 }
}
}
If there is an adapter plate between the arm and gripper, set the z translation to the plate height.
Wrist camera (mounted on the arm, offset from the end effector). In the sidebar, click your wrist camera component to open its card, then click Frame:
{
"parent": "my-arm",
"translation": { "x": 0, "y": 30, "z": 60 },
"orientation": {
"type": "ov_degrees",
"value": { "x": 0, "y": 0, "z": 1, "th": 0 }
}
}
Adjust the translation values to match the camera’s actual mounting position relative to the arm’s end effector. If the camera is tilted, add a rotation. For example, tilted 30 degrees downward:
{
"orientation": {
"type": "ov_degrees",
"value": { "x": 1, "y": 0, "z": 0, "th": -30 }
}
}
Click Save after adding each frame.
5. Add frames to navigation sensors
Navigation sensors are children of the base, not the arm.
Front-facing navigation camera. In the sidebar, click your front camera to open its card, then click Frame:
{
"parent": "my-base",
"translation": { "x": 0, "y": 200, "z": 120 },
"orientation": {
"type": "ov_degrees",
"value": { "x": 0, "y": 0, "z": 1, "th": 0 }
}
}
LIDAR mounted on top of the base. In the sidebar, click your LIDAR component to open its card, then click Frame:
{
"parent": "my-base",
"translation": { "x": 0, "y": 0, "z": 150 },
"orientation": {
"type": "ov_degrees",
"value": { "x": 0, "y": 0, "z": 1, "th": 0 }
}
}
Adjust translation values to match your sensor mounting positions.
Click Save after adding each frame.
6. Visualize and verify
- Open the 3D SCENE tab.
- Confirm the tree structure: arm, gripper, and wrist camera under the base; navigation sensors as direct children of the base.
- Jog the arm from the CONTROL tab. The arm subtree should move; the base and navigation sensors should not. This is the single clearest test that the hierarchy is correct.
- Drive the base a short distance. Every frame should shift together.
- Measure a known physical offset (base center to lidar, for example) and compare to the translation values in your config.
7. Verify with TransformPose
Use TransformPose to verify the full chain of transforms.
For example, transform the wrist camera’s origin from the camera frame to the world frame.
The result should account for the base-to-arm offset, the arm’s current joint positions, and the arm-to-camera offset.
For details on the TransformPose API, see Frame system: TransformPose.
Troubleshooting
What’s next
Was this page helpful?
Glad to hear it! If you have any other feedback please let us know:
We're sorry about that. To help us improve, please tell us what we can do better:
Thank you!