# Arm + Hand record / replay The teach/replay scripts now capture and replay the **Inspire hand** alongside the G1 arm. Backward compatible: old recordings (no hand track) replay arm-only. ## What changed - **`g1_teach_v4_stable.py`** — while recording the arm, it also subscribes to `rt/inspire/cmd` and saves the commanded finger pose as `"h": [12]` per frame (0–5 right, 6–11 left). Meta gains `"hand": true`. On by default; `--no-hand` disables. - **`g1_replay_v4_stable.py`** — auto-detects the `h` track and publishes it to `rt/inspire/cmd` every frame, so the hand follows the arm (incl. move-to-start, pause-hold, and home-return). The hand *state* read-back is unreliable on the current adapters, so we record the **commanded** hand pose (`rt/inspire/cmd`) — i.e. whatever you drive the hand to during teaching (via the dashboard) is what gets captured. ## Prerequisites - Env with `unitree_sdk2py`: **`conda activate g1_env`** (also works: teleop, g1ik, …). - Workstation ethernet to the G1 (`enp3s0`, 192.168.123.x) — same DDS domain as the robot. - **`inspire_g1` running on the robot** (the Docker container) so it receives `rt/inspire/cmd` and drives the physical hand. Same domain reaches it over the eth link. ## Record (teach) ```bash conda activate g1_env cd ~/Robotics_workspace/yslootahtech/G1/G1_Lootah/Manual_Recorder python3 g1_teach_v4_stable.py enp3s0 --output wave_hi --seconds 20 ``` - First 3 s: arms locked. Then arms go limp — **move the arm by hand**. - **Default (`--hand-source keys`, terminal focused):** `o`=open · `c`=close (fist) · `b`=box · `t`=thumbs-up — each key drives the hand and is recorded. Reliable. - **`--hand-source push` (push-to-teach):** after a 2 s force-baseline calibration, **press a finger to move it** (via the force sensor, since fingers can't be pushed directly). Two behaviours: - `--push-mode hold` (default): press-and-**HOLD** → the finger closes *gradually* (harder press = faster, `--close-rate`); release → **holds at that level**, so you get any partial close. Press again to open it back. - `--push-mode toggle`: a press flips the finger full open↔close. Keyboard while recording: `o`/`c` = open/close **both** hands · `[` `]` = open/close **right** · `;` `'` = open/close **left**. Sensitivity: `--push-thresh 50` default (auto-raised per finger to its resting noise); lower it (e.g. `30`) for a lighter press. - `--hand-source cmd`: command the hand from the dashboard http://:8088. - `--hand-source follow`: low-force by-hand — **does NOT work on the RH56** (see below). - Arm-only: add `--no-hand`. > **The RH56 fingers ARE back-drivable when RELEASED** (corrected 2026-07-30). Sending > `q=-1` turns the motor OFF (0xFFFF) → the fingers go loose and you can pose them by > hand, and the position sensor follows. (An earlier note here wrongly said > non-backdrivable — that test used a low *grip force*, which still COMMANDS/holds a > position, not a release.) So the simplest record-by-hand is **release + record the > actual position** — see `hand_record.py`, which does exactly that. The `keys` / `push` > / `follow` teach modes were built before this was understood; `keys` still works fine, > but posing by hand (release) is the natural way. > > ⚠️ The two hands are on a **flaky USB hub** that intermittently drops one or both > adapters (a dropped hand reads flat 0 / can't be driven). For reliable recording, > reseat the USB-RS485 adapters or plug them **direct into the Jetson**. ### Recording fingers by physically moving them (default `--hand-source state`) `rt/inspire/state` read-back now **works** (the frame-header fix — this hand replies `90 EB`). In the default `state` source the recorder **releases the fingers** (sends `-1` each frame so the motors go free) and logs the **actual** finger degrees, so you can bend the fingers by hand and it captures the real motion. Sources: - `--hand-source state` (default) — release + record actual positions (move fingers by hand). - `--hand-source keys` — drive with the keyboard (`o`/`c`/`b`/`t`) and record that. - `--hand-source cmd` — record whatever the dashboard commands. > Note: **both** hands track (open≈1.0 → close≈0), verified 2026-07-29. If a hand reads > a flat `0`, restart the hand service (`./manage.sh restart` / re-run the container); > if it persists on only one hand, check that hand's RS-485 adapter. ## Preview before saving After the arms return home (and before the save prompt) the teach asks: `▶️ Replay this recording to preview before saving? [y/n]`. Answering `y` replays the just-recorded arm **and** hand in real time (arms + fingers move), returns to home, and asks again — so you can watch it as many times as you like, then choose save `y/n`. ## Replay (arm + hand together) ```bash conda activate g1_env python3 g1_replay_v4_stable.py enp3s0 --input wave_hi.jsonl ``` - Detects the hand track automatically and drives the hand with the arm. - Keys: `x` pause · `z` resume · `q` quit. `--speed 0.5` for slow-mo. ## File format ``` {"meta":{"hz":60.0,"motors":29,"hand":true,"hand_motors":12}} {"t":0.0,"q":[..29..],"h":[..12..]} ... ```