Skip to content

feat(teleop): generic Feetech leader teleop module and coordinator port - #5177

Draft
KrishnaH96 wants to merge 5 commits into
mainfrom
krishna/feat/leader-teleop-module
Draft

KrishnaH96 wants to merge 5 commits into
mainfrom
krishna/feat/leader-teleop-module

Conversation

@KrishnaH96

Copy link
Copy Markdown
Contributor

Why

Leader-arm teleop (Feetech leaders driving a Damiao follower) exists only as the OpenArm Mini module on #4326, and a second copy was being written for dual OpenYAM. DIM-129 asks for one module where the robot is config. This PR is that shared module. OpenArm Mini and dual OpenYAM follow as two stacked PRs that add only a mapping table and a blueprint each.

What

New package dimos/teleop/leader/:

  • mapping.py: SideMapping per side = JointMapping(motor, joint, lower, upper, scale, offset) list + optional GripperMapping(motor, travel_radians). Target is scale * reading + offset, clamped.
  • module.py: LeaderTeleopModule reads each enabled side every 20 ms and publishes leader_joint_command (JointState, frame dimos/guarded-joint) and left_gripper_command / right_gripper_command (Float32, 1 = open). Jump guard, optional low-pass, reader="mock" for --simulation.
  • coordinator.py: LeaderCoordinator(DamiaoCoordinator) adds the leader_joint_command input. leader_task() is a trajectory task at priority 20 bound to that port with stream_bind, so the leader outranks a policy on the joints it publishes and releases them 0.4 s after it stops. leader_gripper_tasks() gives one gripper task per side.
  • feetech.py, calibration.py: serial reader with multi-turn wrap, per-side calibration JSON under STATE_DIR/teleop/leader/<side>/ (same format as the OpenArm Mini files), mock reader.
  • cli/: dimos hardware feetech-leader {calibrate, joint-tui, setup-motor-id}, moved from the OpenArm Mini branch and made robot-agnostic.

Wiring: leader-teleop extra (ftservo-python-sdk), registry entries, README note. dimos/control is untouched.

Not in this PR

  • Robot mappings, velocity limits and blueprints: PR2 (OpenArm Mini) and PR3 (dual OpenYAM).
  • Hardware runs: done in PR2 and PR3 with their blueprints.

How to test

uv sync --extra leader-teleop
uv run pytest dimos/teleop/leader dimos/cli/hardware
dimos hardware feetech-leader --help

With a leader arm on a serial port:

dimos hardware feetech-leader calibrate --side left --port-left /dev/ttyACM0
dimos hardware feetech-leader joint-tui --side left --port /dev/ttyACM0

Checks

  • pytest dimos/teleop/leader dimos/cli/hardware dimos/robot/test_all_blueprints_generation.py: 102 passed
  • pytest dimos/codebase_checks: 162 passed
  • ruff, ruff format, mypy, deptry: clean

Checklist

  • I have read and approved the CLA.

Add dimos/teleop/leader: a robot-agnostic leader teleop module whose
motor-to-joint mapping is config (SideMapping per side), a Feetech reader
with per-side calibration under STATE_DIR/teleop/leader, a mock reader for
--simulation, and LeaderCoordinator plus leader_task/leader_gripper_tasks
that bind the leader's targets to their own trajectory task at priority 20.

Mount the calibrate/joint-tui/setup-motor-id commands under
dimos hardware feetech-leader and add the leader-teleop extra for the SDK.

@github-actions github-actions Bot left a comment •

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

go2 replay realtime (arm64)

Details
Benchmark suite Current: 7969c63 Previous: 14c62ab Ratio
peak memory 1768.02 MB 1762.355 MB 1.00
peak threads 374 threads 385 threads 0.97
network (transport) 2728.406 MB 2731.013 MB 1.00
disk write 1.867 MB 1.605 MB 1.16
instructions 137.172 G 138.791 G 0.99

This comment was automatically generated by workflow using github-action-benchmark.

…r tasks

Calibrate records a gripper trigger servo at the ID after the arm joints when
one answers, and the joint TUI reads whatever motors the calibration names.
leader_gripper_tasks now takes the robot's DamiaoGripper list so each task
carries the jaw's open_at instead of the gripper task default.
Blueprint parsing validates every module config before the command line
supplies the leader ports, so the side check only covers sides that are
already selected; sides() still refuses to connect with none.
A coordinator has one trajectory task and addresses it by name, so a second
instance for the leader is refused at start. leader_task now returns the
joint_trajectory task bound to the leader's port.
@codecov

codecov Bot commented Nov 10, 2026 •

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 89.89091% with 139 lines in your changes missing coverage. Please review.
✅ All tests successful. No failed tests found.

Files with missing lines Patch % Lines
dimos/teleop/leader/cli/setup_motor_id.py 67.88% 22 Missing and 13 partials ⚠️
dimos/teleop/leader/cli/calibrate.py 70.58% 25 Missing and 5 partials ⚠️
dimos/teleop/leader/feetech.py 73.68% 16 Missing and 9 partials ⚠️
dimos/teleop/leader/module.py 89.75% 14 Missing and 7 partials ⚠️
dimos/teleop/leader/cli/joint_tui.py 70.31% 18 Missing and 1 partial ⚠️
dimos/teleop/leader/mapping.py 93.13% 4 Missing and 3 partials ⚠️
dimos/teleop/leader/test_feetech.py 96.66% 1 Missing and 1 partial ⚠️
@@            Coverage Diff             @@
##             main    #5177      +/-   ##
==========================================
+ Coverage   83.73%   83.77%   +0.04%     
==========================================
  Files        1864     1884      +20     
  Lines      181729   183104    +1375     
  Branches    14967    15077     +110     
==========================================
+ Hits       152168   153400    +1232     
- Misses      25583    25687     +104     
- Partials     3978     4017      +39     
Components Coverage Δ
Tests 96.67% <99.66%> (+0.02%) ⬆️
Flag Coverage Δ
OS-macos-latest 78.03% <89.67%> (+0.08%) ⬆️
OS-ubuntu-24.04-arm 77.80% <89.45%> (+0.09%) ⬆️
OS-ubuntu-latest 78.16% <89.67%> (+0.08%) ⬆️
Py-3.10 78.16% <89.45%> (+0.08%) ⬆️
Py-3.11 78.14% <89.45%> (+0.08%) ⬆️
Py-3.12 78.15% <89.45%> (+0.08%) ⬆️
SelfHosted-Linux 40.72% <33.81%> (-0.06%) ⬇️
SelfHosted-macOS 40.44% <33.81%> (-0.06%) ⬇️

Flags with carried forward coverage won't be shown. Click here to find out more.

Files with missing lines Coverage Δ
dimos/cli/hardware/test_feetech_leader.py 100.00% <100.00%> (ø)
dimos/cli/hardware_cli.py 100.00% <100.00%> (ø)
dimos/robot/all_blueprints.py 100.00% <ø> (ø)
dimos/teleop/leader/calibration.py 100.00% <100.00%> (ø)
dimos/teleop/leader/cli/_errors.py 100.00% <100.00%> (ø)
dimos/teleop/leader/cli/app.py 100.00% <100.00%> (ø)
dimos/teleop/leader/cli/test_calibrate.py 100.00% <100.00%> (ø)
dimos/teleop/leader/cli/test_cli.py 100.00% <100.00%> (ø)
dimos/teleop/leader/cli/test_joint_tui.py 100.00% <100.00%> (ø)
dimos/teleop/leader/cli/test_setup_motor_id.py 100.00% <100.00%> (ø)
... and 12 more

... and 4 files with indirect coverage changes

🚀 New features to boost your workflow:
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

Sharing a Python process with cameras, Viser and the recorder cost the
100 Hz tick loop a quarter of its ticks on a Jetson, so the arm moved in
steps. With its own worker the coordinator publishes at a clean 100 Hz.

This branch has not been deployed

No deployments
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.

1 participant