DFX_inspire_service/SETUP_G1.md
2026-08-04 16:09:17 +04:00

5.2 KiB
Raw Blame History

Inspire RH56 dual-hand bring-up on Unitree G1 (PC2)

Setup notes specific to this robot. Upstream README assumes a clean unitree_sdk2 install in /usr/local and hard-codes /dev/ttyUSB1+/dev/ttyUSB2; neither holds here, so we adjust as below.

Canonical (workstation): …/yslootahtech/Project/G1/DFX_inspire_service Deploy to PC2 unitree@192.168.123.164:~/DFX_inspire_service via rsync, then ./build.sh. (wifi 10.255.254.86 is flaky; the eth0 IP 192.168.123.164 is the reliable path.)

0. Easiest way to drive everything — manage.sh

./manage.sh                 # status: service + devices + adapters
./manage.sh start|stop|restart
./manage.sh open|close|box|menu     # fingers only
./manage.sh like|handshake|thumbup  # arm + hand (ARM MOVES)
./manage.sh arm "shake hand"        # built-in arm action; armlist to list
./manage.sh help

It keeps exactly one inspire_g1 running (duplicates corrupt the RS-485 bus) and auto-starts the service for gesture commands.

Architecture (unchanged from upstream)

hand_example/your app → DDS topic rt/inspire/cmd (MotorCmds_, 12 motors: 05 right, 611 left) → inspire_g1 → RS-485 (CH340 USB adapters, 115200 8N1, Inspire slave id 1) → hands. State flows back on rt/inspire/state. Finger order per hand: pinky, ring, middle, index, thumb-bend, thumb-rotation. q ∈ [0,1]: 0 = closed, 1 = open.

1. Build (no system changes)

unitree_sdk2 in /usr/local is stale (no go2 IDL). build.sh links against the newer ~/unitree_sdk2 source tree instead:

cd ~/DFX_inspire_service
./build.sh          # -> build/inspire_g1, inspire_h1, hand_example

2. Stable serial names + no-sudo access (one-time, needs sudo)

Both hand adapters are CH340s with identical USB serial, so we pin names by physical port and grant access via udev:

sudo cp ~/DFX_inspire_service/udev/99-inspire-hands.rules /etc/udev/rules.d/
sudo udevadm control --reload-rules && sudo udevadm trigger
ls -l /dev/inspire_right /dev/inspire_left    # both should now exist

inspire_g1.cpp opens /dev/inspire_right + /dev/inspire_left. Mapping (corrected after live test): right → USB port 1-2.2.1.1, left → 1-2.2.3.

3. Run + test

cd ~/DFX_inspire_service/build
./inspire_g1        # Terminal 1 (no sudo needed after the udev rule)
./hand_example      # Terminal 2 -> both hands open/close ~1 Hz

Stop with Ctrl+C in each. If a hand doesn't move: check 24 V power, RS-485 A/B polarity, and that the hand is at Inspire slave id 1.

Record / replay panel (dashboard)

The dashboard's Record / replay card runs g1_record_replay.py as a child process — the same script as the CLI, so a take made in the browser and one made from a terminal are the same file in DataG1/. It needs the recorder present on whatever host serves the dashboard:

# where g1_record_replay.py lives (searched: ../Manual_Recorder, ~/Manual_Recorder)
export RECORDER_DIR=~/Manual_Recorder
# an interpreter that can import unitree_sdk2py (on a workstation: the g1_env conda python)
export RECORDER_PY=python3
./manage.sh dashboard          # prints the resolved recorder path, or NOT FOUND

The panel starts a take, relays the in-take keys (o c [ ] ; ', f, and the saved shapes as keys 1-9), answers the recorder's preview/save prompts, and lists DataG1/ for replay, rename and delete. Two things it works around, both load-bearing:

  • Keys are paced ~150 ms apart. The recorder reads them with select() + buffered sys.stdin.read(1); a burst lands in Python's buffer, select() then reports nothing ready and every key after the first is stranded. Measured: 3 keys 10 ms apart → 2 arrived.
  • Stop sends SIGINT, and the dashboard repairs SIGINT first. A process backgrounded by a non-interactive shell inherits SIGINT = SIG_IGN, which survives exec — and manage.sh starts the dashboard exactly that way, so without the repair Stop would silently do nothing. The panel shows a warning if the repair did not hold. SIGINT (not SIGKILL) is what lets the recorder walk the arm home and release it.

Replay and preview move the arm and both require an explicit confirmation. Starting a take disarms force-follow, since the bridge and the recorder would otherwise both publish rt/inspire/cmd every frame.

If you move an adapter to a different USB socket

The udev KERNELS value changes. Re-discover and update the rule:

udevadm info -a -n /dev/ttyUSB0 | grep -m1 'KERNELS=="[0-9]'

Troubleshooting

  • /dev/inspire_* missing / no CH340 in lsusb → the hand USB-RS485 adapters are unplugged (or robot rebooted with them out). Re-plug them; udev recreates the names.
  • Fingers don't move (thumb might) → usually a latched actuator fault from running two inspire_g1 at once. inspire_g1 now runs ClearError + sets speed/force on startup; ./manage.sh restart re-applies it. If still stuck, power-cycle the hands (24 V).
  • Two inspire_g1 instances → they collide on the serial bus; ./manage.sh status flags it, restart fixes it. Kill with pkill -x inspire_g1 (never pkill -f).
  • rt/inspire/state reads all-zeros → cosmetic; CH340 adapters echo their TX so position read-back is unreliable. Does not affect commands sent to the hand.