07Operating the robot
One server, one wire contract, every client. The same launcher pattern runs the simulator on a laptop and the real robot on the Jetson; iOS, Vision Pro, and the browser connect identically to either — they cannot tell which is live.
Launch — simulator (laptop)
cd server && ./run.sh # full sim stack + web studio on :8097
./run.sh --test # open-field sandbox scene + native viewer
./run.sh --no-tui # plain scrolling output instead of the cockpit
In an interactive terminal the launcher becomes a retro cockpit TUI: live joints with deviation tracks, the robot rendered from the actual model, camera and lidar panels, log tails. It is also a teleop client:
| Key | Action |
|---|---|
| ↑↓←→ | drive the base (hold to move; release stops) |
| a / d | rotate left / right |
| w / s | lift up / down |
| Enter / r | re-anchor the teleop clutch / reset the sim |
| l / h / q | log panel / help / quit everything |
Launch — real robot (Jetson)
./server/real_run.sh # HAL + SLAM + Nav2 + app server (+ cockpit TUI)
./server/real_run.sh --no-slam # motors + cameras only
./server/real_run.sh --only-hands # bench a single subsystem (also --only-base, --only-cameras)
./server/real_run.sh -h # every flag
- The robot auto-starts this at boot via systemd. A manual run takes over cleanly (the service instance stands by until you exit).
- A module with no hardware plugged in stays idle — it never crashes the bring-up. The status watchdog prints per-bus liveness every 10 s.
- Ctrl-C (or q in the cockpit) stops everything and returns the robot to the auto-started stack.
Clients
| Client | How |
|---|---|
| Browser console | http://<host>:8080/console — video + keyboard drive, zero install |
| Control studios | real: http://<host>:8094 · sim: :8097 — full control GUI, visualizer, monitor |
| iPhone app | auto-discovers the robot on the same Wi-Fi (Bonjour), or add the host IP |
| Vision Pro | whole-body teleop: your hands drive the arms/hands, stereo video in immersive space |
| Remote | a relay tunnel (rathole + Caddy on any VPS) exposes the same contract over the internet; LAN/Tailscale is always the low-latency path |
Whole-body teleop flow: put both hands in view until tracking is solid, then
anchor the clutch (headset recenter, or Enter in the cockpit).
The arms stay limp until you explicitly enable torque from a client —
launching never energizes anything.
The safety model
Every safeguard below is real and lives in the code:
| Layer | Behavior |
|---|---|
| E-stop | any client sends estop → the bridge zeros all commands and latches stopped; a hardware e-stop de-energizes actuators independently of the host |
| Deadman | no fresh command in 0.3 s → drive zeros; lost Teensy heartbeat → controllers disable in ~150 ms |
| Tip-over | a ZMP model bounds base speed/accel from the measured CoM — the envelope tightens as the lift rises |
| Self-collision | a CBF-QP keeps the arms out of each other and the body |
| Arbitration | a single-driver lock: two operators can't fight; discrete commands outrank streams |
| Tracking loss | lost hand tracking holds pose — it never extrapolates |
| One gate | every base twist from every client passes safe_base_step() in controller/; no code path bypasses it |
Before any energized session: know where your hardware e-stop is, confirm the
software e-stop from the client you are using, and keep the first sessions in
an open area at reduced speed caps.