⚠️ Experimental — This project is under active development and may contain bugs or incomplete features. Use at your own risk.
REST + WebSocket API for controlling the Unitree G1 Basic humanoid robot, with AGiXT AI agent integration.
- Serial MITM Control: Intercepts and injects 40-byte controller packets via Raspberry Pi
- 7 State Transitions: Documented button combos for stand, sit, walk, emergency stop, etc.
- Velocity Control: Forward/backward, lateral, rotation with safety ramping
- Sequences: Pre-built and custom movement routines with save/load
- Safety Layer: Velocity clamping, acceleration ramping, watchdog auto-stop
- WebSocket: Real-time telemetry streaming at ~10Hz with bidirectional commands
- Dashboard: Web-based control panel with virtual joysticks and keyboard shortcuts
- Event Logging: Structured telemetry log with filtering
- AGiXT Integration: AI agent context and unified command endpoints
- Simulation Mode: Full API testing without hardware
┌──────────────┐ Wireless ┌──────────────┐ USB Serial ┌──────────────┐ UART ┌─────────┐
│ Controller │ ──────────►│ Receiver │ ────────────►│ Raspberry Pi │ ──────►│ G1 MCU │
└──────────────┘ └──────────────┘ │ (g1control) │ └─────────┘
└──────────────┘
│
HTTP / WebSocket
│
┌──────────────┐
│ AGiXT Agent │
└──────────────┘
The Raspberry Pi sits between the wireless receiver and the robot, reading controller packets and injecting its own 40-byte commands over serial.
# Install dependencies
pip install -r requirements.txt
# Edit config
cp config.yaml config.yaml.bak
nano config.yaml # Set simulation: false, serial ports
# Run
python3 api_server.py- API: http://localhost:8000
- Dashboard: http://localhost:8000/dashboard
- Docs: http://localhost:8000/docs
# Health check
curl http://localhost:8000/health
# Status
curl http://localhost:8000/api/v1/status
# Boot sequence
curl -X POST http://localhost:8000/api/v1/action/stand_up
curl -X POST http://localhost:8000/api/v1/action/start_control
curl -X POST http://localhost:8000/api/v1/action/toggle_walk
# Move forward for 3 seconds
curl -X POST http://localhost:8000/api/v1/move \
-H "Content-Type: application/json" \
-d '{"vx": 0.5, "duration": 3}'
# Stop
curl -X POST http://localhost:8000/api/v1/stop| Method | Path | Description |
|---|---|---|
| GET | /api/v1/status |
Robot mode, velocity, battery, connections |
| GET | /api/v1/actions |
List all available actions |
| Method | Path | Description |
|---|---|---|
| POST | /api/v1/move |
Velocity control (vx, vy, vyaw, duration) |
| POST | /api/v1/stop |
Stop all movement |
| POST | /api/v1/speed_mode |
Set walk/run mode |
| POST | /api/v1/action/{name} |
Execute a state transition action |
| Method | Path | Description |
|---|---|---|
| GET | /api/v1/sequences |
List all sequences |
| GET | /api/v1/sequences/{name} |
Get sequence definition |
| POST | /api/v1/sequences/{name}/run |
Run a named sequence |
| POST | /api/v1/sequences/{name}/save |
Save a custom sequence |
| DELETE | /api/v1/sequences/{name} |
Delete a user-saved sequence |
| POST | /api/v1/sequence |
Run an inline sequence |
| DELETE | /api/v1/sequence |
Cancel the running sequence |
| Method | Path | Description |
|---|---|---|
| GET | /api/v1/agent/context |
Full robot context for AI agents |
| POST | /api/v1/agent/command |
Unified agent command endpoint |
| Method | Path | Description |
|---|---|---|
| GET | /api/v1/safety |
Current safety configuration |
| GET | /api/v1/controller |
Raw controller state (debug) |
| POST | /api/v1/navigate |
Navigation placeholder (not yet implemented) |
| Method | Path | Description |
|---|---|---|
| GET | /api/v1/events |
Recent events (filterable) |
| GET | /api/v1/events/types |
List all event types |
| WS | /ws/telemetry |
Real-time state + bidirectional commands |
| Method | Path | Description |
|---|---|---|
| GET | /health |
Health check |
| GET | /dashboard |
Web control panel |
| GET | / |
API info |
All 7 actions correspond to documented controller button combos from the official Unitree G1 manual:
| Action | Button Combo | Description |
|---|---|---|
damping |
L1 + A | Enter damping/soft mode (motors off, robot falls) |
stand_up |
L1 + Up | Stand up from damping |
sit_down |
L1 + Left | Sit down (use before shutdown) |
start_control |
R1 + X | Enter operation control / walking mode |
toggle_walk |
Start | Toggle standing still ↔ walking |
emergency_stop |
L2 + B | Emergency stop — enters damping |
debug_mode |
L2 + R2 | Enter debug mode (stops motion program) |
The G1 must be brought up in order: damping → stand_up → start_control → toggle_walk → move commands.
| Axis | Range | Description |
|---|---|---|
vx |
±1.5 m/s | Forward / backward |
vy |
±1.0 m/s | Left / right |
vyaw |
±0.6 rad/s | Counter-clockwise / clockwise |
Safety features enforce these limits automatically with acceleration ramping and a watchdog that stops the robot if no command is received within 2 seconds.
40-byte packets with a 16-bit button bitmask and float joystick axes:
| Field | Offset | Size | Description |
|---|---|---|---|
head |
0 | 2 | Header bytes |
btn |
2 | 2 | Button bitmask (16-bit) |
lx |
4 | 4 | Left stick X (-1.0 to 1.0) |
rx |
8 | 4 | Right stick X |
ry |
12 | 4 | Right stick Y |
L2 |
16 | 4 | L2 trigger (0.0 to 1.0) |
ly |
20 | 4 | Left stick Y |
idle |
24 | 16 | Padding |
g1control/
├── api_server.py # FastAPI server (v0.3.0)
├── config.py # YAML + env var config loader
├── config.yaml # Default configuration
├── controller_protocol.py # 40-byte packet encode/decode
├── robot_controller.py # Virtual controller + keyboard input
├── serial_controller_reader.py # USB serial reader/monitor
├── read_controller.py # Simple serial monitor
├── sequence_library.py # Built-in + user sequence management
├── telemetry.py # Structured event logging
├── dashboard.html # Web control panel
├── g1control.service # systemd unit file
├── requirements.txt # Python dependencies
├── sequences/ # User-saved sequences (JSON)
└── docs/
├── CONTROLLER_RESEARCH.md # Protocol research notes
└── PI_ARCHITECTURE.md # Architecture documentation
The AGiXT extension for this robot is in the unitree_extensions repo. Copy unitree_g1.py into your AGiXT extensions directory and configure with G1_API_URL=http://<g1control-host>:8000.
- Serial only: The G1 Basic has no onboard secondary computer, so control is limited to what the controller can do (button combos + joystick axes)
- No gestures: Wave, bow, handshake, and other gesture actions require DDS and are not available via serial injection
- No camera/mic: The G1 Basic has no accessible camera or microphone through this interface
- go2control — Control server for the Unitree Go2 Pro robot dog
- unitree_extensions — AGiXT extensions for both robots
- AGiXT — AI agent framework
This project is experimental and we welcome contributions! If you find a bug or have a suggestion:
- Report issues on the GitHub Issues page
- Pull requests are always welcome — if you find an issue you can fix, we'd love the help
MIT — Use at your own risk. This is unofficial/experimental code.