Skip to content

Krishna/feat/openarm mini v2 - #3396

Draft
KrishnaH96 wants to merge 48 commits into
krishna/feat/openarm-damiaofrom
krishna/feat/openarm-mini-v2
Draft

Krishna/feat/openarm mini v2#3396
KrishnaH96 wants to merge 48 commits into
krishna/feat/openarm-damiaofrom
krishna/feat/openarm-mini-v2

Conversation

@KrishnaH96

Copy link
Copy Markdown
Contributor

Contribution path

  • Small, safe change that does not need a tracking issue
  • Linked issue or discussion: DIM-XXX / #XXX / URL

Problem

Solution

How to Test

AI assistance

Checklist

  • I have read and approved the CLA.

TomCC7 and others added 30 commits July 21, 2026 16:33
Select MIT mode and drain startup traffic before enabling Damiao motors. Send zero-torque OpenYAM frames for compliant encoder readback and expose Viser on all interfaces.
# Conflicts:
#	CONTEXT.md
#	dimos/cli/can.py
#	dimos/cli/dimos.py
#	dimos/cli/test_can.py
#	dimos/robot/manipulators/openyam/config.py
#	pyproject.toml
TomCC7 and others added 18 commits August 2, 2026 22:49
…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.
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.
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.
Ports dimos/teleop/openarm_mini from cc/feat/openarm-mini at 1563ff1,
including the multi-turn encoder wrap and the CLI tools. Adapted for the
whole-body OpenArm follower: default follower joint names come from
openarm_arm_joints, and the sender-side clamp limits mirror the OpenArm
v2.0 URDF instead of the v1.0 measured limits.
…llower

mini-teleop-openarm drives both arms from two leader ports; the left and
right variants drive one side while the other arm holds. Leader joint N
maps to follower joint N with no wrist reordering, matching the OpenArm
2.0 conventions on both ends.
Soft arm gains and grippers removed from the topology, the exact
configuration validated on both real arms during the leader teleop
ladder. Drop or promote this commit before opening the PR.
@codecov

codecov Bot commented Aug 8, 2026

Copy link
Copy Markdown

❌ 1 Tests Failed:

Tests completed Failed Passed Skipped
3547 1 3546 174
View the top 1 failed test(s) by shortest run time
dimos.hardware.whole_body.openarm_damiao.test_adapter::test_openarm_topology_connects_arms_and_grippers
Stack Traces | 0.221s run time
openarm_adapter = <dimos.hardware.whole_body.openarm_damiao.adapter.OpenArmDamiaoAdapter object at 0xffe1b0c645f0>

    def test_openarm_topology_connects_arms_and_grippers(
        openarm_adapter: OpenArmDamiaoAdapter,
    ) -> None:
        robot = openarm_adapter._build_robot()
    
>       assert robot.group_names() == ["left_arm", "right_arm", "left_gripper", "right_gripper"]
E       AssertionError: assert ['left_arm', 'right_arm'] == ['left_arm', ...ight_gripper']
E         
E         Right contains 2 more items, first extra item: #x1B[0m#x1B[33m'#x1B[39;49;00m#x1B[33mleft_gripper#x1B[39;49;00m#x1B[33m'#x1B[39;49;00m#x1B[90m#x1B[39;49;00m
E         
E         Full diff:
E         #x1B[0m#x1B[90m #x1B[39;49;00m [#x1B[90m#x1B[39;49;00m
E         #x1B[90m #x1B[39;49;00m     'left_arm',#x1B[90m#x1B[39;49;00m
E         #x1B[90m #x1B[39;49;00m     'right_arm',#x1B[90m#x1B[39;49;00m
E         #x1B[91m-     'left_gripper',#x1B[39;49;00m#x1B[90m#x1B[39;49;00m
E         #x1B[91m-     'right_gripper',#x1B[39;49;00m#x1B[90m#x1B[39;49;00m
E         #x1B[90m #x1B[39;49;00m ]#x1B[90m#x1B[39;49;00m

openarm_adapter = <dimos.hardware.whole_body.openarm_damiao.adapter.OpenArmDamiaoAdapter object at 0xffe1b0c645f0>
robot      = <can_motor_control.Robot object at 0xffe1b10dd330>

.../whole_body/openarm_damiao/test_adapter.py:51: AssertionError

To view more test analytics, go to the Test Analytics Dashboard
📋 Got 3 mins? Take this short survey to help us improve Test Analytics.

@TomCC7
TomCC7 force-pushed the krishna/feat/openarm-damiao branch from fc31ef3 to fda5f14 Compare August 11, 2026 03:00
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants