Repository navigation
Conversation
- XArmConnection: a connection module over the xArm SDK. Servo targets on position_command, joint speeds on velocity_command (each with a duration, so the arm stops by itself), readings at about 100 Hz with real speeds and torques. Start fails on a wrong arm type or firmware below 1.9.0; an arm already in error starts but takes no command until clear_errors(). A position target further than jump_limit_s at the URDF top speed is refused. The xArm Gripper is its URDF drive_joint in radians. - xarm_model(arm, gripper, robot=...): one URDF builder for the connection module, the coordinator and make_xarm_model_config. - movable_joints() leaves out mimic joints, so the gripper's five followers are not driven. - xarm7-keyboard-teleop / xarm6-keyboard-teleop: keyboard eef twist through XArmTwistCoordinator and XArmConnection, arm only. The IP is given at run time with --xarmconnection.ip or XARMCONNECTION__IP.
…imOS When xArm Studio or the arm's stop button stops it (mode 0, state 4, no error), every motion command returns code 9 and the arm stayed dead until clear_errors() or a restart. On code 9 with no error or warning, the mode and set_state(0) are set again (motors left as they are), at most once a second, and the command retried once. While the arm still answers code 9, motion commands are dropped for 0.5 s (and halt skips its zero-speed call) so slow refused SDK calls do not stall the commands behind them. Errors and warnings still wait for clear_errors().
The eef_twist task in xarm7/xarm6-keyboard-teleop had timeout 0.0, so if keyboard messages stopped mid-jog the coordinator kept integrating the last twist and the arm kept moving.
When get_joint_states kept failing, the last good reading was used forever for the jump guard and to fill joints left out of a position command, so a target far from where the arm really is could pass. Joint targets are now refused once the latest reading is older than ten read periods (0.1 s). Speeds do not use the reading and are unchanged.
The arm refuses to clear a warning (code 1) while an error is still set, so after an e-stop clear_errors() failed on its first call.
connection.py imported xarm.wrapper at the top, and the CI test venv has no xArm SDK (it is in the control extra, not the tests group). Every blueprint that imports xarm/blueprints/teleop.py failed to load: the new keyboard teleop blueprints, the older keyboard-teleop-* ones, and teleop-webxr-a1z, learning-collect-webxr-piper and demo-pico-body-tracking through teleop/webxr/blueprints.py. The SDK is now imported in _open_sdk(), called from connect(), as the G1 wholebody connection does for unitree_sdk2py. The tests fake _open_sdk() instead of XArmAPI.
test_every_registered_blueprint_is_annotated fails on every registered blueprint missing from annotations.yaml. Both take the arm's IP as --xarmconnection.ip and run on a real arm only.
…ors() A stop from xArm Studio or the arm's stop button no longer lasts only until the next command: the module refuses every command until clear_errors() makes the arm ready again.
…e coordinator
- The gripper task drives a joint of a robot behind a connection module:
with no adapter hardware, its position limits come from the
coordinator's model, the same ones the coordinator enforces. The task
registry passes the model to a factory that takes a `model` argument.
- `open_at` ("upper" or "lower") says which end of the joint is open, so
set_normalized(1.0) opens a gripper like the xArm Gripper's drive_joint
(0 rad open, 0.85 rad closed). The default keeps adapter grippers as they
were.
- xarm7-keyboard-teleop / xarm6-keyboard-teleop: XArmConnection with the
xArm Gripper, the coordinator's model with it, and an `arm_gripper` task
on arm/drive_joint fed by the keyboard's `[` and `]`.
…op Manipulation app - Replaces xarm7-keyboard-teleop / xarm6-keyboard-teleop: no pygame window. The app's jog arrives on ee_twist_command and its gripper opening on right_gripper_command; the arm's joints go out on coordinator_joint_state. - The eef_twist task stops the end 0.3 s after the last twist, since the app sends twists only while a jog is held. - XArmTwistCoordinator takes right_gripper_command; the arm_gripper task is bound to it. - A UrdfManager serves the arm's URDF (joints named arm/joint1..., as the coordinator names them) on render_file_request / file_info and puts its joints on tf, so the Controller's 3D view draws the arm moving. - xarm_model is given the gripper by keyword.
They replace xarm6/7-keyboard-teleop, so the annotations follow the new names and say the commands come from the Desktop Manipulation app.
There was a problem hiding this comment.
go2 replay realtime (arm64)
Details
| Benchmark suite | Current: ec41253 | Previous: a8ca5ff | Ratio |
|---|---|---|---|
peak memory |
1740.473 MB |
1752.543 MB |
0.99 |
peak threads |
368 threads |
371 threads |
0.99 |
network (transport) |
2731.051 MB |
2725.828 MB |
1.00 |
disk write |
1.473 MB |
1.652 MB |
0.89 |
instructions |
138.13 G |
136.444 G |
1.01 |
This comment was automatically generated by workflow using github-action-benchmark.
Codecov Report❌ Patch coverage is @@ Coverage Diff @@
## mustafa/feat/xarm-gripper #4960 +/- ##
=============================================================
- Coverage 81.58% 81.35% -0.24%
=============================================================
Files 1772 1791 +19
Lines 176296 177501 +1205
Branches 15350 15418 +68
=============================================================
+ Hits 143836 144409 +573
- Misses 28771 29406 +635
+ Partials 3689 3686 -3
Flags with carried forward coverage won't be shown. Click here to find out more.
... and 9 files with indirect coverage changes 🚀 New features to boost your workflow:
|
Build directly on main with standard connection ports, dedicated control blueprints and the minimal Metal adapter/model configuration. Keep learning and policy changes out of this branch. Reuse model-backed gripper support from #4939 (27d3753) and the Metal driver/configuration from #4900. Lock only the required can-motor-control update to 0.0.11.
66cd59d to
668933d
Compare
[High impact] The PR changes how several robot families reach and control physical hardware. Fix the model transform order before merging; it prevents G1 teleop from loading its arm model. FindingsSummaryReplaces YAM, OpenArm, and Metal adapters with direct connection modules and an explicit mock connection for simulation.
Reviews (1) · Last reviewed commit: "Merge refreshed xArm stack into Damiao r..." · Reviewed by Greptile |
| return RobotModel( | ||
| _source_path=self._source_path, _base_model=self, _renamed_joints=tuple(names.items()) | ||
| ) |
There was a problem hiding this comment.
with_renamed_joints() now loads and renames the base model before later joint transforms run. Existing callers still use the original names. G1_TELEOP_ARM_MODEL, for example, renames the waist joints and then passes their URDF names to with_fixed_joints(). Loading it now raises ValueError: Joint not found, breaking G1 teleop setup. The existing attachment test also replaces limits using a name that has already been renamed.
Preserve the previous transform order, or migrate these callers and cover both chains.
| `OpenYamConnection()` and `DualOpenYamConnection()` default to sources `yam` and | ||
| `dual_openyam` when used directly. Use `.models(source=...)` for a matching | ||
| coordinator/planner model when composing a custom stack. |
There was a problem hiding this comment.
Documented model method is missing
The custom-stack instructions recommend .models(source=...), but neither connection provides a models() method. Following this example raises AttributeError. Document planning_model(source=...) for the planner and control_model(source=...) for the coordinator instead.
| `OpenYamConnection()` and `DualOpenYamConnection()` default to sources `yam` and | |
| `dual_openyam` when used directly. Use `.models(source=...)` for a matching | |
| coordinator/planner model when composing a custom stack. | |
| `OpenYamConnection()` and `DualOpenYamConnection()` default to sources `yam` and | |
| `dual_openyam` when used directly. Use `.planning_model(source=...)` for the planner | |
| and `.control_model(source=...)` for the coordinator when composing a custom stack. |
Note: If this suggestion doesn't match your team's coding style, reply to this and let me know. I'll remember it for next time!
Stack: main → #4938 → #4939 → #4960. Each layer is based on the refreshed preceding branch; shared gripper code and tests stay in #4939.
YAM, dual YAM, OpenArm, single Metal, and dual Metal use direct connection modules for CAN ownership, measured state, and position commands. The legacy Damiao adapters, registry entries, hardware factories, and Metal adapter coordinators are removed. Damiao-specific implementation and tests live in
dimos/robot/manipulators/damiao/.Native CAN selectors are required strings. Missing, None, blank, or duplicate selectors fail configuration validation. Explicit
--simulationcomposes a separate MockJointConnection; native connections never fall back to mock hardware.Vendor declarations use plain lists/dictionaries and the SDK's native Robot builder. Connections directly hold the robot and arm/gripper views, with no session wrapper types. SDK configuration owns gripper direction and exposes 0=closed, 1=open. Startup completes calibration, feedback validation, subscriptions, and reader setup before readiness or state streaming. Shutdown, rollback, feedback faults, and deadman holds retain regression coverage.
Metal reuses main #4865's pinned geometry, fixed-attachment API, planning groups, and configurable mount transforms. The single- and dual-arm entry names are preserved. Both arms reuse the same Metal profiles, motor addresses, gains, and gripper settings. Default bench transforms remain examples; the actual mounting geometry is configurable.
RobotModel loaded views add logical gripper joints and namespace joint names without synthetic URDF paths or generated model files. Deepcopy preserves lazy source handles without checking out robot assets. Serialization formats are unchanged. The existing Quest collection caller uses the deployed
arm/joint names; the learning pipeline is unchanged.The retired-adapter Codecov exclusions cover only the five removed directories; thresholds are unchanged. Supersedes #4959.
Validation
Try it
See Metal setup and mount geometry and the connection test runbook.
gh pr checkout 4960 uv run dimos --simulation run dual-makermods-metal-planner-coordinator --daemon uv run dimos shell # Stop after exiting the shell: uv run dimos stopNative single Metal requires
--can-port; dual Metal requires distinct--left-can-portand--right-can-port. Physical startup enables motors and calibrates gripper endpoints, causing jaw motion.