Skip to content

SO-101 follower arm bring-up: joint states + safe joint control#50

Open
MJohnson459 wants to merge 1 commit into
mainfrom
worktree-arm-so101-bringup
Open

SO-101 follower arm bring-up: joint states + safe joint control#50
MJohnson459 wants to merge 1 commit into
mainfrom
worktree-arm-so101-bringup

Conversation

@MJohnson459

Copy link
Copy Markdown
Contributor

SO-101 follower arm bring-up: joint states + safe jog control.

Branch worktree-arm-so101-bringup, committed (not pushed). No leader arm assumed anywhere.

STACK DECISION (documented in mote_arm/README.md): direct Feetech control, NOT LeRobot. The arm servos are the same STS-class Feetech bus as the drive wheels, so this reuses the existing servo stack instead of pulling torch onto the deliberately-lean Pi env (the repo isolates all torch to off-board inference envs). Sole new dep: pure-Python feetech-servo-sdk (scservo_sdk) — the same SDK LeRobot uses, so a LeRobot path stays open. Episode-recording path = ROS rosbags (already used for map provenance).

WHAT LANDED — new mote_arm Python/ament package:

  • config.py: parses robot.yaml arm: section; encoder<->rad conversion + soft-limit clamping. ROS-free and unit-tested (15 tests) so the safety maths is verified without hardware.
  • bus.py: FeetechBus, thin scservo_sdk wrapper (lazy import → build/lint/test stay hardware-free); register map matches mote_hardware.
  • arm_driver node (pixi run arm): single bus owner. Publishes /joint_states for the arm, accepts soft-clamped goals on arm/goal, exposes arm/set_torque (SetBool). Starts LIMP, goes limp on shutdown — nothing moves without an explicit command.
  • jog CLI (pixi run arm-jog): interactive per-joint jog, a client of the driver (no bus contention), clamped both sides, torque-off on exit.
  • arm_check (pixi run arm-check): standalone enumeration/health + a ready-to-paste udev line + --save-home calibration snapshot.
    Supporting: robot.yaml arm: section (single source of truth; port/baud/IDs/soft-limits/home/invert), URDF arm links behind arm:=true (sim passes arm:=false), commented /dev/mote_arm udev rule, pixi tasks + feetech-servo-sdk dep + mote_arm in the test set. CLAUDE.md package docs updated.

VERIFIED: pixi run build, pixi run test (104 passed incl. 15 mote_arm), pixi run lint all green; xacro generates correctly with the arm on (real) and off (sim).

NOT verified on hardware — needs Michael at the bench (runbook: mote_arm/BENCH.md). Bench must resolve 3 open items the design already supports both ways: (1) does the arm share the wheel bus or have its own USB adapter (set arm.port accordingly), (2) real servo IDs, (3) udev serial. The robot.yaml soft limits / home / invert are conservative PLACEHOLDERS to calibrate at the bench.

GitHub #2 (camera doesn't fit with the arm attached) noted as an unresolved mechanical clash, not addressed here; mote_arm is not part of mission bringup and is run explicitly.

Bring the mounted SO-101 follower arm under software control: live joint
states, safe soft-limited joint commands, a jog CLI, and bench tools. There
is no leader arm and none is assumed anywhere.

Stack decision (documented in mote_arm/README.md): direct Feetech control,
not LeRobot. The arm servos are the same STS-class Feetech bus as the drive
wheels, so this reuses the servo approach rather than pulling torch onto the
lean Pi env (which the repo keeps torch off, isolating inference off-board).
The only new dep is the pure-Python feetech-servo-sdk (scservo_sdk).

New mote_arm package (Python/ament):
- config.py: parses robot.yaml `arm:`; encoder<->rad conversion + soft-limit
  clamping. ROS-free and unit-tested (15 tests) so the safety maths is
  verified without hardware.
- bus.py: FeetechBus, a thin scservo_sdk wrapper (lazy import so
  build/lint/test stay hardware-free); register map matches mote_hardware.
- arm_driver (node, `pixi run arm`): single bus owner. Publishes
  /joint_states for the arm, accepts soft-clamped goals on arm/goal, exposes
  arm/set_torque. Starts LIMP and goes limp on shutdown — nothing moves
  without an explicit command.
- jog (CLI, `pixi run arm-jog`): interactive per-joint jog; a client of the
  driver (no bus contention), clamped both sides, torque-off on exit.
- arm_check (`pixi run arm-check`): standalone enumeration/health + a
  ready-to-paste udev line + --save-home calibration snapshot.

Supporting changes:
- robot.yaml: `arm:` section (port, baud, IDs, per-joint soft limits, home,
  invert) — the single source of truth; limits are conservative placeholders
  to calibrate at the bench.
- mote.urdf.xacro: arm links/joints behind arm:=true (sim passes arm:=false)
  so robot_state_publisher animates the arm in TF from /joint_states.
- 99-mote.rules: commented /dev/mote_arm rule (pin by serial; arm_check
  prints the line).
- pixi.toml: feetech-servo-sdk dep; arm / arm-jog / arm-check tasks;
  mote_arm added to the test set.

Torque policy and calibration in mote_arm/README.md; human bench runbook in
mote_arm/BENCH.md. GitHub #2 (camera doesn't fit with the arm) noted as an
unresolved mechanical clash, not addressed here.

Verified: pixi run build, pixi run test (104 passed incl. 15 mote_arm),
pixi run lint all green; xacro generates with the arm on (real) and off (sim).

Co-Authored-By: Claude Opus 4.8 <[email protected]>
Claude-Session: https://claude.ai/code/session_01TQqUVutHYLPLToYtiP8BSj
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