Krishna/feat/openarm damiao - #3351
Conversation
There was a problem hiding this comment.
lgtm overall. however, there's some other changes needed to make sure everything is working with openarm:
- manipulation module will definitely fail because current srdf generation does not support dual arm setup (on intention). We need to define the srdf and feed manually
- how to support multiple gripper, but this can be a separate pr
And a general (safe) testing tip: don't write the command to robot (can just comment out the write function call) and just open visualization to make sure robot joint looks correct (read working), and once it's verified we can enable motor write
❌ 1 Tests Failed:
View the top 1 failed test(s) by shortest run time
To view more test analytics, go to the Test Analytics Dashboard |
…ody adapter Add OpenArmDamiaoAdapter: both v10 arms (2x DM8006, 2x DM4340, 3x DM4310, send ids 0x01..0x07) and both grippers (DM4310 at 0x08) as one whole-body device over two CAN buses (left=can1, right=can0), with gravity compensation from the bimanual URDF (14 joints, validated order left1..7 then right1..7). Rewrite the OpenArm hardware config on the OpenYAM pattern: one 16-joint WHOLE_BODY component, mock/real selection via global_config.simulation, hardware-measured MIT gains carried over from the legacy adapter, and per-side planning models gaining an explicit coordinator->URDF joint name mapping. Blueprints: coordinator-openarm, openarm-planner-coordinator, keyboard-teleop-openarm and keyboard-teleop-openarm-planner. The keyboard jogs the left arm while the right arm's twist task holds pose; a single servo task drives both grippers, enabled by a new KeyboardTeleopConfig.gripper_joint_names field. The e2e planning-groups test moves to openarm-planner-coordinator since the harness's --simulation flag now selects the in-memory adapter.
The hand-rolled Damiao CAN driver and manipulator-protocol adapter are fully replaced by OpenArmDamiaoAdapter on the whole-body path, which also wires the previously unimplemented grippers. Drop the legacy CAN bring-up scripts (superseded by 'dimos can setup') and the openarm manipulator registry entry.
DM8009 shoulders (DM8006 was a legacy typo), MotorSpecs as plain lists, keyboard teleop module restored to upstream with gripper bindings deferred to a follow-up PR, and dual-arm planning switched to a single bimanual robot model with left_manipulator and right_manipulator groups fed by a hand-written SRDF, since generated SRDFs cannot express cross-robot collision exclusions. Planner blueprint verified against the in-memory adapter in simulation.
b7c5e7f to
7be88df
Compare
Replace the stale v1.0 data package with URDFs generated from the official
OpenArm v2.0 preset pipeline (enactic/openarm_description @ 6c7b720f1ba,
default_bimanual plus per-side pinch gripper presets). Pinch gripper finger
joints are fixed in the generated models so each arm exposes exactly its
seven driven joints while keeping gripper geometry and mass; mesh URIs stay
package relative and ros2_control blocks are dropped. The package ships
v2.0 meshes, the three URDFs, and a PROVENANCE file, and shrinks from 70 MB
to 8 MB.
The v2.0 generator collapses link7, so planning tips move to
openarm_{side}_ee_base_link and the SRDF now disables the sibling finger
pair per hand. Joint naming is unchanged from v1.0, so the adapter topology
and gravity joint order carry over. Verified with pinocchio (14 and 7 DOF
models, finite gravity) and a planner blueprint run in simulation.
RoboPlan generated composite planning groups only for selections spanning two or more robots, so a bimanual robot modeled as one URDF with two planning groups could not plan both arms in a single request. Drop the robot-count restriction; the joint-disjointness requirement and the composite group cap still apply, and overlapping selections are already rejected at the selection layer. Verified in process on the OpenArm 2.0 bimanual model: left, right, and combined fourteen-joint plans all succeed.
Converted OBJ files were named by stem only, so a robot whose visual and collision meshes share a stem (OpenArm v2.0 uses visual/link3.dae and collision/link3.stl) had the collision conversion overwrite the visual one, and viewers rendered collision geometry in visual mode. Suffix the converted name with a hash of the source path and pin the behavior with tests.
Regenerate the v2.0 URDFs with emit_grasp_frame enabled and move the
planning group tip links from the ee flange to openarm_{side}_grasp_frame,
matching the OpenYAM gripper_tip convention. Model DOF, joint order, and
gravity behavior are unchanged; planning verified for left, right, and
combined requests.
The optimistic target ghost rebuilt its per-robot joint values from the current state for every selected group, so with two planning groups on one robot the group processed last discarded the other group's target and the ghost only ever showed one arm's goal. Seed the merge once per robot and overlay each group's target into the same values.
642e299 to
64efdee
Compare
The pinch gripper finger joints are fixed in the generated models and their collision meshes do not intersect at the fixed pose, so the manual exclusions were dead weight. Verified left, right, and combined plans still succeed without the file.
Gripper opening calibrates during activation, and reading it earlier raises, so a connected but not activated whole-body adapter failed the entire state read and read-only bring-up sessions (connect without enable) streamed nothing. Report placeholder gripper states until the adapter is active; arms stream immediately and real openings appear after activation. Found on OpenArm hardware during the read-only phase.
Damiao feedback only updates when the bus is ticked, which the write path does once per control cycle while the adapter is active. A connected but not activated adapter never ticked, so read-only sessions streamed the connect-time snapshot forever. Refresh from the read path whenever the adapter is inactive; the active path is unchanged and still ticks exactly once per cycle.
| joint_names=openarm_arm_joints(side), | ||
| priority=priority, | ||
| params={ | ||
| "model_path": OPENARM_LEFT_MODEL if side == "left" else OPENARM_RIGHT_MODEL, |
There was a problem hiding this comment.
I prefer no left/right model at all but I understand that this is for testing, I'll cleanup later once teleop works
| _teleop_hw = openarm_single_hardware() | ||
| # The keyboard publishes twists to one task by name; the right arm's task | ||
| # keeps holding its anchor pose. | ||
| KEYBOARD_EEF_TASK_NAME = "eef_twist_left_arm" |
There was a problem hiding this comment.
if you only wired left side here, why wiring both side eef task in control coordinator? should only wire one side as well
Greptile SummaryThis PR replaces OpenArm’s legacy per-arm CAN integration with the generic bimanual Damiao whole-body stack.
Confidence Score: 5/5The PR appears safe to merge based on the reviewed changes, with no unacknowledged actionable defects identified. The whole-body joint ordering, planner mapping, adapter topology, simulation selection, and blueprint registry changes are internally consistent, while the unavailable keyboard gripper behavior is explicitly documented as deferred. Important Files Changed
Flowchart%%{init: {'theme': 'neutral'}}%%
flowchart LR
Keyboard[Keyboard teleop] --> Coordinator[ControlCoordinator]
Planner[Bimanual planner] --> Coordinator
Coordinator --> Hardware[OpenArm whole-body component]
Hardware --> Adapter[OpenArmDamiaoAdapter]
Adapter --> LeftBus[Left CAN bus]
Adapter --> RightBus[Right CAN bus]
LeftBus --> LeftArm[Left arm and gripper]
RightBus --> RightArm[Right arm and gripper]
Adapter --> Gravity[Bimanual URDF gravity model]
Reviews (1): Last reviewed commit: "fix(manipulation): pump feedback from th..." | Re-trigger Greptile |
|
|
||
| ADAPTER_FACTORIES = { | ||
| "openarm": "dimos.hardware.manipulators.openarm.adapter:OpenArmAdapter", | ||
| "openarm_damiao": ("dimos.hardware.whole_body.openarm_damiao.adapter:OpenArmDamiaoAdapter"), |
There was a problem hiding this comment.
this should just be openarm as we removed in-house solution
Contribution path
Problem
OpenArm support predates the whole-body Damiao stack: a hand-rolled CAN driver plus a manipulator-protocol adapter, one instance per bus, grippers present on the bus but never wired, no sim/real switch, and robot-specific gravity compensation code.
Solution
Stacked on #3129. This ports OpenArm to the generic
DamiaoWholeBodyAdapter, mirroring the OpenYAM integration:OpenArmDamiaoAdapter: both v10 arms (2x DM8006, 2x DM4340, 3x DM4310, send ids 0x01..0x07) and both grippers (DM4310 at 0x08) as one whole-body device over two CAN buses (left=can1, right=can0), commanded in one synchronized tick. Gravity compensation uses the bimanual URDF fromopenarm_description(validated in pinocchio: 14 joints, order left1..7 then right1..7, finite torques).global_config.simulation, hardware-measured MIT gains carried over from the legacy adapter, and per-side planning models now declare an explicit coordinator-to-URDF joint name mapping.coordinator-openarm,openarm-planner-coordinator,keyboard-teleop-openarm, andkeyboard-teleop-openarm-planner. The keyboard jogs the left arm while the right arm's twist task holds pose. The[and]keys drive both grippers through a single servo task, enabled by a newKeyboardTeleopConfig.gripper_joint_namesfield.openarm-planner-coordinator, since the test harness passes--simulationand now gets the in-memory adapter automatically.How to Test
Automated validation:
Hardware validation
Validated on a physical bimanual OpenArm 2.0 (PEAK 2ch adapter, one 1 Mbps
classic CAN bus per arm).
correct. This phase caught and fixed two adapter bugs (gripper reads raise
before calibration; feedback only pumped by the write path).
arm, keyboard teleop per arm, and planned motion executed per arm and with
both arms in one plan.
AI assistance
Claude Code with Fable 5 assisted throughout: studying the #3129 adapter stack, implementing the adapter, config, blueprints, and tests, validating the bimanual gravity URDF in pinocchio, and writing the docs. The author directed the design decisions (bimanual-first scope, gain carryover from the legacy adapter, legacy driver removal) and reviewed the changes. Mock and unit test validation only; physical OpenArm motion will be tested and findings willl be updated here.
Checklist