How to Integrate a New Manipulator Arm
This guide walks through integrating a new robot arm with DimOS, from writing the hardware adapter to creating blueprints for planning and control.Architecture Overview
DimOS uses a Protocol-based adapter pattern — no base class inheritance required. Your adapter wraps the vendor SDK and exposes a standard interface that the rest of the system consumes:
See also: dimos/hardware/manipulators/README.md for a quick reference.
Prerequisites
- Vendor SDK — The Python SDK for your robot arm (e.g.,
xarm-python-sdk,piper-sdk) - URDF/xacro — A robot description file (only needed if you want motion planning)
- Connection info — IP address, CAN port, serial device, etc.
Step 1: Create the Adapter
Create a new directory for your arm underdimos/hardware/manipulators/:
adapter.py — Full Skeleton
Below is a complete annotated adapter. Implement each method by wrapping your vendor SDK calls. All values crossing the adapter boundary must use SI units.| Quantity | SI Unit |
|---|---|
| Angles | radians |
| Angular velocity | rad/s |
| Torque | Nm |
| Position | meters |
| Force | Newtons |
skip
Key implementation notes
-
Unsupported features — Return
Nonefor reads andFalsefor writes. Never raise exceptions for optional features. - Velocity/effort feedback — If your SDK doesn’t provide these, return zeros. The coordinator handles this gracefully.
-
Lazy SDK import — If the vendor SDK is an optional dependency, you can import it inside
connect()instead of at module level (see Piper adapter for this pattern):
Step 2: Create Package Files
__init__.py
skip
__registry__.py
Create a lightweight manifest next to adapter.py:
skip
How auto-discovery works
TheAdapterRegistry in dimos/hardware/manipulators/registry.py automatically discovers your adapter metadata at import time:
- It iterates over all subpackages under
dimos/hardware/manipulators/ - For each subpackage, it imports
<subpackage>.__registry__ - It reads
ADAPTER_FACTORIESentries such as"yourarm": "dimos.hardware.manipulators.yourarm.adapter:YourArmAdapter"
adapter_registry.create("yourarm", ...), so unrelated adapter listing does not import your vendor SDK.
You can verify discovery works:
skip
Step 3: Create Your Robot Folder and Blueprints
Each robot in DimOS gets its own folder underdimos/robot/. This is where you define all blueprints for your arm — coordinator, planning, perception, etc. This follows the same pattern as Unitree robots (dimos/robot/unitree/).
3a. Create the robot directory
3b. Define your blueprints
Createdimos/robot/yourarm/blueprints.py with your coordinator and (optionally) planning blueprints:
skip
Blueprint field reference
| Field | Description |
|---|---|
hardware_id | Unique name for this hardware component. Used to route commands. |
adapter_type | Name registered with adapter_registry (e.g., "yourarm"). |
address | Connection info passed to adapter’s __init__ as address kwarg. |
joints | List of joint names. make_joints("arm", 6) creates ["arm_joint1", ..., "arm_joint6"]. |
auto_enable | If True, servos are enabled automatically when the coordinator starts. |
task.name | Name used by the ManipulationModule to invoke trajectory execution via RPC. |
task.type | Task type: "trajectory", "servo", "velocity", or "cartesian_ik". |
task.priority | Priority for per-joint arbitration. Higher number wins. |
Step 4: Add URDF and Planning Integration (Optional)
If you want motion planning (collision-free trajectories via Drake), you need a URDF and a planning blueprint. Add these to your robot’s ownblueprints.py.
4a. Add your URDF
Place your URDF/xacro files under LFS data so they can be resolved viaLfsPath. LfsPath is a Path subclass that lazily downloads LFS data on first access — this avoids downloading at import time when the blueprint module is loaded.
skip
4b. Create a robot model config helper
skip
4c. Create a planning blueprint
Add this to yourdimos/robot/yourarm/blueprints.py alongside the coordinator blueprint:
skip
Key config fields
| Field | Description |
|---|---|
model_path | Path to .urdf or .xacro file |
joint_names | Ordered controllable local model joint set (must match URDF); not itself a planning group |
planning_groups / srdf_path | Explicit planning groups or SRDF source; fallback can generate {robot_name}/manipulator for an unambiguous single chain |
package_paths | Maps package:// URIs to filesystem paths (for xacro) |
coordinator_task_name | Must match the TaskConfig.name in your coordinator blueprint |
collision_exclusion_pairs | List of (link_a, link_b) tuples for links that may legitimately touch (e.g., gripper fingers) |
{robot_name}/{local_joint_name} (for example, arm/joint1).
Keep hardware-native name translation inside the hardware adapter; manipulation
planning config uses local model joint names.
base_link, base_pose, and end_effector_link are compatibility fields used
by current placement and robot-scoped helper paths. New planning code should use
SRDF/planning-group chain base/tip links and encode robot placement in the model. See
Planning Groups.
Step 5: Register Blueprints
The blueprint registry indimos/robot/all_blueprints.py is auto-generated by scanning the codebase for blueprint declarations. After adding your blueprints:
- Run the generation test to update the registry:
- Now you can run your arm via CLI:
Step 6: Testing
Verify adapter registration
skip
Unit test with mock
You can test coordinator logic without hardware by usingunittest.mock:
skip
Integration test with coordinator
skip
Test the real adapter standalone
skip
Quick Reference Checklist
Files to create:-
dimos/hardware/manipulators/yourarm/__init__.py -
dimos/hardware/manipulators/yourarm/__registry__.py(maps adapter key to implementation path) -
dimos/hardware/manipulators/yourarm/adapter.py(implements Protocol) -
dimos/robot/yourarm/__init__.py -
dimos/robot/yourarm/blueprints.py(coordinator + planning blueprints)
-
pyproject.toml— Add vendor SDK to optional dependencies (if applicable)
-
adapter_registry.available()includes"yourarm" -
adapter_registry.create("yourarm", address="192.168.1.100", dof=6)returns your adapter -
pytest dimos/robot/test_all_blueprints_generation.pypasses (regeneratesall_blueprints.py) -
dimos run coordinator-yourarmstarts successfully
