The simulated arm component emulates the SO-101 arm entirely in software, with no hardware required. It shares the same kinematics as the devrel:so101:arm model, so it is useful for developing and testing configs, motion plans, and the 3D scene viewer without a physical robot.
When commanded to a joint configuration, the simulated arm interpolates its joints toward the target over time at a configurable speed, like rdk's builtin simulated arm. It also serves 3D meshes for each link, so it renders as an SO-101 in the visualizer.
{}All attributes are optional, so the simulated arm works with an empty configuration.
The following attributes are available for the simulated arm component:
| Name | Type | Inclusion | Description |
|---|---|---|---|
speed_degs_per_sec |
float | Optional | How fast each joint travels toward its target, in degrees per second. Default is 90. |
motion |
string | Optional | Name of the motion service used to plan MoveToPosition requests. Default is "builtin". |
simulate_time |
bool | Optional | Whether a background goroutine advances the arm's position in real time. Default is true. (Tests set it to false to drive the simulated clock.) |
visualize_ee_frame |
bool | Optional | When true, serves a colored XYZ coordinate-frame marker at the end-effector for the 3D viewer. Default is false. |
use_urdf |
bool | Optional | When true, sources kinematics and collision geometry from the bundled assets/urdf/so101.urdf instead of the embedded so101.json, and requires VIAM_MODULE_ROOT (viam-server sets this). A drop-in swap — frame names, TCP, and kinematics are identical; only the collision geometry upgrades from primitive shapes to per-link meshes. Default false. |
mesh_decimation_ratios |
[]float | Optional | Per-mesh simplification ratios, one per arm link in document order (base, shoulder, upper_arm, lower_arm, wrist). Only values strictly inside (0, 1) decimate; lower is more aggressive. Used only with use_urdf. Defaults to 0.9 for all five. |
orientation_tolerance_deg |
float | Optional | Half-angle, in degrees, of the cone of acceptable end-effector approach directions around the goal orientation, used by MoveToPosition. Roll about that axis is NOT constrained. Range [0, 180]; 0/unset means 30. See Approach-axis orientation planning. |
position_tolerance_mm |
float | Optional | Per-axis positional leeway, in millimetres, of the MoveToPosition goal cloud. Default 1.0. See Approach-axis orientation planning. |
| Example configuration with attributes: |
{
"speed_degs_per_sec": 60
}Retrieve the configured joint speed:
{
"command": "get_motion_params"
}MoveToJointPositions,MoveThroughJointPositions, andGoToInputsinterpolate the joints toward each target over time; the calls block until the arm arrives.MoveToPositionplans through the motion service. As with thedevrel:so101:armmodel, it attaches an approach-axis cone (orientation_tolerance_deg/position_tolerance_mm) to the goal by default instead of ignoring orientation — see Approach-axis orientation planning above for the config attributes, theextraescape hatches, and the viam-server version requirement.JointPositions,EndPosition,Geometries, andIsMovingreport the simulated state.
The simulated gripper emulates the SO-101 gripper entirely in software, with no hardware required. It serves the gripper meshes (a static body plus a moving jaw/trigger) to the 3D scene viewer, with the moving part posed by the gripper's opening — useful for developing and previewing without a physical robot.
Open opens the gripper and Grab closes it, interpolating the jaw open/closed over time so it animates in the 3D viewer (like the simulated arm). Both block until the motion finishes, and IsMoving reports true while the jaw is travelling. A simulated gripper never grasps an object, so Grab always reports false.
{}All attributes are optional, so the simulated gripper works with an empty configuration.
| Name | Type | Inclusion | Description |
|---|---|---|---|
gripper_type |
string | Optional | Which gripper meshes to serve: follower (moving jaw, the default) or leader (thumb-loop handle + trigger). |
mesh_detail |
string | Optional | Gripper mesh resolution: low (decimated, the default) or high (full resolution). The mesh is also the motion-planning collision geometry, so low keeps planning fast; set high on a second gripper for a visual side-by-side. |
The simulated gripper reports the same TCP reference frame as the hardware gripper — see Reference frame (TCP).
Set a target opening percentage (0 = closed, 100 = open); the jaw interpolates toward it:
{
"command": "set_position",
"percentage": 50
}{
"command": "get_position"
}