58 lines
2.6 KiB
Markdown
58 lines
2.6 KiB
Markdown
# Dockerized Inspire hand service + dashboard
|
|
|
|
One self-contained image (aarch64) running `inspire_g1` + `hand_bridge` + the Flask
|
|
dashboard. Build ON the robot (it pulls `unitree_sdk2` + CycloneDDS from the host).
|
|
|
|
## Build (once, on the robot)
|
|
```bash
|
|
cd ~/DFX_inspire_service
|
|
./docker/build_image.sh # assembles context + docker build -> inspire-hand:latest
|
|
```
|
|
|
|
## Run
|
|
```bash
|
|
./docker/run.sh # or: docker compose -f docker/docker-compose.yml up -d
|
|
# dashboard -> http://<robot-ip>:8088
|
|
./docker/stop.sh
|
|
```
|
|
|
|
`run.sh` first stops any host-native `inspire_g1`/`hand_bridge` — running both the
|
|
container and the host service would put **two writers on the RS-485 bus** and
|
|
corrupt the hands.
|
|
|
|
## Why these flags
|
|
- `--network host` — CycloneDDS (rt/inspire/cmd) and the arm actions (rt/arm_sdk,
|
|
reaching the G1 motion controller on eth0) need the host network.
|
|
- `--privileged -v /dev:/dev` — the CH340 `ttyUSB*` adapters re-enumerate on the hub;
|
|
mounting `/dev` + privileged lets the in-container dynamic detection find them.
|
|
- `IFACE=eth0` — interface for arm actions (must be eth0). Fingers work on either.
|
|
|
|
## Record / replay in the image
|
|
The dashboard's Record/Replay card runs `g1_record_replay.py` as a child process, so the
|
|
image needs the script **and** a python that can import `unitree_sdk2py`. `build_image.sh`
|
|
pulls both into the context:
|
|
|
|
```bash
|
|
RECORDER_SRC=~/Manual_Recorder \
|
|
UNITREE_SDK2PY_DIR=~/unitree_sdk2_python \
|
|
./docker/build_image.sh
|
|
```
|
|
|
|
Neither is required — leave them out and the image still builds, with the panel reporting
|
|
*"recorder not found"*. `start.sh` prints which case you got.
|
|
|
|
- **That layer pip-installs (`cyclonedds`, `unitree_sdk2py`), so the robot needs network at
|
|
BUILD time.** Offline alternative: copy the robot's own python site-packages into the
|
|
image the same way `build_image.sh` copies the C libs.
|
|
- **Takes are a host volume** — `run.sh` mounts `$HAND_DATA_DIR/DataG1` to
|
|
`/opt/recorder/DataG1`, because `run.sh` starts with `docker rm -f` and would otherwise
|
|
destroy every recording ever made.
|
|
- **`arm_home.jsonl` is seeded on first start**, not baked into `DataG1/` — the bind-mount
|
|
would hide a baked copy, and without it every take skips its return-to-home. It is hidden
|
|
from the takes list and cannot be deleted from the panel: it is a home pose, not a take.
|
|
|
|
## Notes
|
|
- Sudo/udev not needed inside the container (privileged).
|
|
- Saved poses/combos persist via `-v $HAND_DATA_DIR:/opt/hand/data` + `HAND_DATA` (set by
|
|
`run.sh`). They used to live in the image and were wiped by every rebuild.
|