Adventure x - #3138
Draft
Nabla7 wants to merge 57 commits into
Draft
Conversation
GalaxeaA1ZAdapter implements the ManipulatorAdapter protocol on top of the vendor a1z SDK (CAN bus, MIT PD + gravity comp at 250 Hz). POSITION (min-jerk planned moves) and SERVO_POSITION (streaming) control modes, latching soft e-stop, FK-based cartesian reads, G1Z gripper support (requires the vendor SDK's 'gripper' branch; meters API, 10 cm measured stroke), and teach-and-play recording exposed as adapter extensions. Startup is a verified zero-force sequence: motors enable at kp=0, every motor must report fresh in-limit feedback before hold gains engage at the measured pose - the vendor's stock start() position-holds a single 50 ms read and snaps the arm to zero if feedback is late (reproduced on hardware). Shutdown re-sends disable frames to all motors including the gripper, whose single vendor disable frame can be lost on a busy bus. Opt out with safe_start=False for vendor-stock behavior. Hardware-validated on a physical A1Z + G1Z.
…sport GsUsbMacBus is a python-can BusABC driving the bundled HHS USB-CANFD adapter over libusb - no SocketCAN, no Linux host. The adapter selects it automatically on macOS (transport="auto"); Linux keeps socketcan. Handles this device's quirks: TX endpoint discovered from descriptors (device uses 0x01, gs_usb lib assumes 0x02), no-op kernel-driver detach, TX echo filtering, RX queue flush on open (the device retains stale frames across sessions, which parse as garbage feedback), and up-to-5s discovery retry (the device drops off the USB bus briefly after a close). Validated on an M4 Pro against a live A1Z: 30 s sustained 250 Hz control loop (p99 cycle 5.2 ms, 0/7500 over the SDK's 12.5 ms watchdog limit), ~100% feedback from all 7 motors. Requires pyusb + gs_usb + libusb.
coordinator-galaxea-a1z runs the arm under the ControlCoordinator with a trajectory task. Hardware-certified end to end: coordinator boot, client-submitted multi-joint trajectories over LCM RPC, 0.07 rad return drift. Defaults to the stable arm-only configuration (SDK main branch). The vendor gripper branch ships a G1Z gravity model that mismatches at least some mountings - it pushes the arm during the zero-force startup window, and disabling gravity compensation as a workaround leaves the vendor's soft e-stop unable to catch the arm. Flip gripper=True after gravity/ zero-point calibration (vendor tools/set_zero.py).
…dware Wire the galaxea_a1z hardware adapter into the a1z planning model that landed on main (dimos/robot/manipulators/a1z): a planner+coordinator blueprint for ManipulationModule-driven motion and a keyboard teleop blueprint using the eef twist task. Both run the arm-only stable configuration (gripper=False, A1Z_Flange model) consistent with coordinator-galaxea-a1z; the mock-based a1z-* blueprints are untouched.
…available The A1Z ships with an HHS USB-CANFD adapter that the kernel gs_usb driver cannot actually drive: the adapter's VID/PID (a8fa:8598) is not in the driver's device table, and its bulk OUT endpoint is 0x01 where kernels before 6.x hardcode 0x02, so every transmit fails even if the driver is force-bound. On such machines (found on a JetPack 6 Jetson, kernel 5.15) the arm is unreachable over socketcan no matter what, even though the adapter is plugged in and healthy. Teach transport="auto" to handle this: keep socketcan whenever the channel exists and is up, so stock kernels that bind the adapter keep working exactly as before, and only otherwise fall back to the userspace gs_usb bus already used on macOS, with a log line saying so. A channel that merely exists is not enough to pick socketcan: an unrelated on-board CAN controller can expose can0 with nothing wired to it, which is exactly what the Jetson does. Verified on hardware: zero-force scan reads all 7 motors, the coordinator blueprint boots and holds pose, and the first-trajectory script passes with 0.066 rad settled drift.
Keep the gripper powered during hand-teaching and toggle it open/closed with a single g keypress, so the operator's hand stays out of the wrist camera footage. The legacy pinch-by-hand behavior remains available via --gripper-free-drive. Prompts now read single keypresses (cbreak) with a line-based fallback for non-tty stdin. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The HHS adapter is a Full-Speed USB device read one frame per libusb round-trip. Draining it synchronously from the SDK's 250 Hz control loop (~1 ms budget per cycle) cannot sustain the ~3500 frames/s the bus carries (7 motors' feedback plus TX echoes), so the device FIFO overflowed and feedback froze for 0.3-2.4 s at a time - poisoning teach recordings with stale-then-jump positions and tripping the SDK's stale-feedback watchdog during replay. A dedicated reader thread now drains USB continuously (libusb releases the GIL while blocked), filters TX echoes, and queues real frames; recv() becomes an instant pop that always meets the SDK's drain budget. Validated on hardware: teach recordings are freeze-free and replay runs without stale warnings.
Two changes so a hand-taught demonstration replays at 1.0x instead of being silently time-scaled to a crawl: - Smooth on the uniform resampled grid instead of the raw samples. The recorder's sample spacing is irregular (10-100 ms under load); differentiating linear interpolation across those gaps manufactured acceleration spikes an order of magnitude above the real motion (74 rad/s^2 measured vs ~14 real), which throttled the safety time-scaler and put velocity ripple into the streamed commands. Two moving-average passes give a continuous velocity profile. - Size the replay caps to measured reality: natural hand teaching peaks ~3.5 rad/s (old cap 1.5 rescaled every demo), staying under the SDK's 4.0 rad/s streaming cap and 7-20 rad/s watchdogs. The gripper is commanded through the SDK's own controller (measured ~0.28 m/s, ~9 m/s^2), so its caps now cover the SDK's own motion. Validated on hardware: a 33.5 s natural-speed episode preflights at 1.00x and replays smoothly at 0.5x and 1.0x.
Single-purpose keys with a persistent status line: SPACE starts and saves episodes, g toggles the gripper, d discards, q quits with a save/discard confirmation when an episode is in progress. Denoise the session by fixing root causes: publish the camera transform immediately at start (first-second frames also gain poses), rate-limit the recorder's poseless-message warning, drop in-flight recording callbacks during shutdown to avoid the closed-database error, and treat disabling an already-disconnected A1Z adapter as success. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Peers only form a transport link when they share the secret, so other machines on the network can't see or collide with this host's zenoh traffic. The password defaults to the machine id (derivable by any on-machine process, so local peers auto-share) and can be overridden with DIMOS_ZENOH_PASSWORD.
Contributor
|
Preview deployment for your docs. Learn more about Mintlify Previews.
💡 Tip: Enable Workflows to automatically generate PRs for you. |
| def _password_dictionary_file(user: str, password: str) -> str: | ||
| directory = CACHE_DIR / "zenoh_auth" | ||
| directory.mkdir(parents=True, exist_ok=True) | ||
| digest = hashlib.sha256(f"{user}:{password}".encode()).hexdigest()[:16] |
| directory.mkdir(parents=True, exist_ok=True) | ||
| digest = hashlib.sha256(f"{user}:{password}".encode()).hexdigest()[:16] | ||
| path = directory / f"{digest}.txt" | ||
| path.write_text(f"{user}:{password}\n") |
Contributor
|
Preview deployment for your docs. Learn more about Mintlify Previews.
💡 Tip: Enable Workflows to automatically generate PRs for you. |
❌ 3 Tests Failed:
View the top 3 failed test(s) by shortest run time
To view more test analytics, go to the Test Analytics Dashboard |
Collaborator
Author
|
@jeff-hykin can you explain a bit here the changes to core/zenoh that were made? |
…ure_x # Conflicts: # dimos/robot/cli/dimos.py # docs/docs.json
Brings the branch up to date with 66 commits of main. Two restructures on main drove most of the work: - dimos/learning/ became dimos/imitation/ (#3194). Git followed the rename for edited files, but not for the module paths inside them; the A1Z teach/replay code, the LeRobot policy module and their tests referenced dimos.learning.* and were rewritten. - dimos/robot/cli/ became dimos/cli/ (#3256). The A1Z teach CLI is rewired there; the Piper CLI this branch added is dropped because an identical copy already landed on main as dimos/robot/manipulators/piper/cli.py. Conflict resolutions of note: - memory2: main changed the record callback to take (recv_ts, msg) and tag samples with reception_ts. Kept that, plus this branch's rate-limited poseless warning and _closing guards, now also gated on main's poseless_streams config. - zenoh: kept main's _default_connect_endpoints and scouting, plus this branch's usrpwd auth; session_key covers both. - piper teleop: main removed RobotModelConfig.coordinator_task_name and made trajectory_task() derive the name from hardware_id. Dropped the explicit name= - trajectory_task_name("arm") is "traj_arm", identical to the old behavior - and the now-redundant test assertion. - docs: kept this branch's restructured manipulation index and ported main's API corrections into the new planning.md (planner_name became planner.backend; RoboPlan is now the default world and planner). - uv.lock regenerated from main's; all_blueprints.py regenerated. Fixed while running the suite: - test_blueprints: main deleted this file when it extracted the plan execution manager (#3183), dropping the xarm and planner-helper cases along with the blueprints they covered - xarm6_planner_only no longer exists and dual_xarm6_planner is now dual_xarm6_planner_coordinator. Kept only this branch's Piper teleop coverage rather than resurrecting tests main removed on purpose. Its _module_kwargs matched blueprint atoms on class identity, which stopped finding the coordinator once main introduced the _PiperTeleopCoordinator subclass; it now matches exactly first, then by subclass. - galaxea_a1z adapter: dropped two "# --- section ---" markers that dimos/codebase_checks/test_no_sections.py rejects. That check predates this branch, so it was already failing before the merge. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01GJRrxtKynzzJx43THcHsTn
Nabla7
marked this pull request as ready for review
July 31, 2026 06:17
Nabla7
requested review from
Dreamsorcerer,
leshy,
mustafab0,
paul-nechifor and
spomichter
as code owners
July 31, 2026 06:17
Member
|
Changing to draft, will split to smaller ones |
TomCC7
marked this pull request as draft
July 31, 2026 06:36
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Contribution path
Problem
Solution
How to Test
AI assistance
Checklist