Software platform for the Waveshare WAVEGO 12-DOF quadruped (Standard BASIC, no Raspberry Pi), built on four pillars:
- Motion/control stack — gait, IK/FK and telemetry, ported faithfully from the open (MIT) Waveshare firmware.
- Teach-in programming — record, name, replay and git-version poses, trajectories and timed move sequences as human-editable YAML routines.
- Gamepad teleoperation — low-latency Xbox controller driving with a hard-wired software E-stop.
- Digital twin — URDF/MJCF simulation; twin and real robot are driven through the same Robot API.
Safety is part of the architecture: every command passes a supervisor with E-stop latch, connection watchdog and workspace limits. See ARCHITECTURE.md, ROADMAP.md and ASSUMPTIONS.md.
Requires Python ≥ 3.12 and uv.
uv sync --all-groups --all-extras
# what can the current backend do?
uv run robodog info --backend mock
# play a command-timeline routine against the in-process mock robot
uv run robodog play routines/patrol-demo.yaml --backend mock
# play a keyframed leg-space motion routine
uv run robodog play routines/bow.yaml --backend mock
# play a drive sequence: named moves with durations, repeated
uv run robodog play routines/patrol-loop.yaml --backend mock
# validate a routine file without running it
uv run robodog validate routines/bow.yaml
# map what you would say onto a behaviour call (needs an LLM endpoint, no robot)
uv run robodog intent "Komm zu mir"
# render the robot as a 3D stick figure (needs the `viz` extra)
uv run robodog viz --pose stand --out stand.pnguv run robodog info --backend sim
uv run robodog play routines/patrol-wifi.yaml --backend sim --viewerThe twin's legs are a serial stand-in for the real five-bar linkage, but their foot positions match the ported firmware kinematics exactly — so gait geometry and stability transfer, while absolute servo loads do not yet (ASSUMPTIONS E4). Its state is measured from physics, not estimated.
uv run robodog teach wave --backend sim --viewerOpens a local web UI in the browser: drag the feet in side/top views,
mirror left/right, capture keyframes, preview the motion in physics, save — and
out comes an ordinary routine file under routines/. Ghost markers
show where physics actually put each foot, and every pose passes the safety
supervisor while you teach it. A scriptable console is available via --repl.
Full guide: docs/teach-in.md.
--viewer paces playback to wall time (the simulation is otherwise some thirty
times faster than real time) and keeps the window open when the routine ends,
until you close it. Without the viewer, an 8-second routine finishes in about a
quarter of a second — handy for tests, useless for watching.
The same UI has a second tab that needs no pose capability at all: build a
sequence of standard moves with durations — 10 s forward, 2 s left, 5 s
backward — set the pause inserted between moves, repeat it a number of times or
loop it until stopped, and run it. A drive pad underneath sends the same
moves one at a time, for driving the robot by hand between runs. Stop is on the
page, on the Escape key, and on the page's own heartbeat (close the tab and
whatever moves stops). Saving produces a kind: sequence routine that
robodog play replays unchanged:
uv run robodog teach patrol --backend sim # author against the twin
uv run robodog teach patrol --backend http # ... or on the real robot
uv run robodog play routines/patrol-loop.yaml --backend httpThe same teach UI grows a command box and a Camera tab with detection boxes on it. Type plain words; a language model maps them to one named behaviour with parameters, once, before anything moves, and a deterministic loop then runs it through the safety supervisor. The model never drives.
uv run robodog teach patrol --backend http --vision # the real thing
uv run robodog teach demo --backend mock \
--vision-source ~/frames --detector yolo # ... or with no robot at allThe host reads the robot's MJPEG stream once and re-serves it, because with
no PSRAM the firmware has a single frame buffer and a browser watching the robot
directly would blind the detector (ASSUMPTIONS F4/G3). YOLO lives behind the
optional vision extra; the behaviour, the page and the model all work without
it. Full guide: docs/vision.md.
Join the robot's access point (SSID WAVESHARE Robot, password 1234567890),
then:
uv run robodog info --backend http # connectivity + capability check
uv run robodog bringup # guided bring-up, writes a report
uv run robodog play routines/patrol-wifi.yaml --backend http
# author and run move sequences in the browser, on the robot
uv run robodog teach patrol --backend http
# with our own firmware flashed, poses reach the robot too; the backend
# detects which firmware is on it, and --firmware overrules the probe
uv run robodog info --backend http --firmware robodog
# and then a keyframed motion routine plays on the real robot
uv run robodog play routines/bow.yaml --backend http
# measure a leg's real roll range (rehearse with --backend mock first)
uv run robodog calibrate-roll --legs front_left
# measure where each servo's zero really is, into a versioned table
uv run robodog calibrate-servos --legs front_left
uv run robodog calibrate-servos --showPut the robot on a stand first. The stock firmware has no link watchdog: if Wi-Fi drops mid-command it keeps walking and no stop can reach it. Full procedure and the reasoning: docs/bringup.md.
Development:
uv run pytest
uv run ruff check .
uv run ruff format .
uv run mypyM0 (offline foundations), M1 (Wi-Fi bring-up, run on the real robot on 2026-08-11) and the core of M2 (MuJoCo digital twin) are done, as are the first two thirds of M4 (our firmware fork: on-device watchdog, pose commands and camera tuning, all measured on the robot 2026-08-22). M8 (vision-guided behaviours) is built and covered headlessly, but has not met a robot yet. Still open: M3 sim-to-real calibration, and the rest of M4. See ROADMAP.md and ASSUMPTIONS.md.
One open hardware issue: our robot walks skewed because its repaired hind-right leg deviates from the firmware's link geometry (ASSUMPTIONS F1/F3).
| Document | What it answers |
|---|---|
| ARCHITECTURE.md | How it fits together: one Robot API, the backend/capability model, the safety design, repository layout |
| ROADMAP.md | Milestones M0-M7, each with its acceptance criteria |
| ASSUMPTIONS.md | Every unverified claim about the hardware and firmware, with its source and current status |
| docs/bringup.md | Guided first contact with the real robot, and why each step is in that order |
| docs/teach-in.md | Authoring routines: web UI, scriptable console, the routine file format |
| docs/vision.md | Vision-guided behaviours: the one-viewer camera, what the behaviour does, why the model does not drive |
| docs/localization.md | The IMU: what it corrects and why it is batched, and the honest case for stop-and-shoot visual odometry |
| docs/calibration.md | Servo zero calibration: the reference, the procedure, what the numbers do and do not say |
| docs/firmware.md | Flashing the ESP32: the pristine baseline, then the fork with the link watchdog |
| docs/research/ | Phase-0 source research on the WAVEGO and WAVEGO Pro, with citations |
| CONTRIBUTING.md | Development setup and the project's non-negotiable rules |
Why so much prose about assumptions: the robot has no servo position feedback and the stock firmware returns no telemetry at all. Everything this software believes about the machine is either read out of the vendor firmware source or verified by watching the robot move. ASSUMPTIONS.md is the ledger of which is which, and entries are updated rather than deleted — a guess that turned out wrong is worth keeping.
Issues and pull requests are welcome, particularly from anyone running the same hardware — much of ASSUMPTIONS.md currently rests on a sample size of one robot. See CONTRIBUTING.md.
MIT. Contains a pinned reference copy of the MIT-licensed Waveshare WAVEGO firmware under vendor/wavego-firmware/, Copyright (c) 2022 waveshare — read-only, never modified.