Using Microban
July 6, 2026 · View on GitHub
This guide covers day-to-day operation once the robot has been set up (see the
Deployment Guide). You drive the robot from your computer with the
Makefile, which talks to the Pi over SSH. You can use the keyboard or a Bluetooth
gamepad to control it, and optionally run it
Important
Always run make shutdown before cutting power to the robot. This is not
automatic — powering off the Pi without a clean shutdown can corrupt the SD card.
Wait 10-15 s after the command before flipping the power switch off, to give the
Pi time to actually halt.
Makefile commands
Run these from the repository root on your computer. They target the host microban
by default; add HOST=microban-ext to operate over the secondary network (see the
Deployment Guide).
| Command | What it does |
|---|---|
make run | Sync the code and start the control loop on the robot (50 Hz). Stays attached to your terminal for live control. |
make stop | Stop the control loop and disable torque on all motors. |
make shutdown | Power off the Pi cleanly. |
make setup | Sync the code and (re)install dependencies on the robot (uv sync --frozen). Run after changing dependencies. |
make sync | Sync your local copy to the robot without touching dependencies. |
make imu | Stream the robot's IMU/gyro readings to your terminal. |
make voltage | Read the voltage of all motors. |
make voltage ID=<id> | Read the voltage of motor <id>. |
make sim | Run the MuJoCo simulation locally (no robot needed). |
make viewer | Open the MuJoCo viewer locally (no robot needed). |
Running the robot
- Place the robot on a stable surface, or hold it securely — on start it enables torque and ramps to its neutral pose.
make run— the control loop starts at 50 Hz and stays attached to your terminal. Some latency is expected due to the SSH connection.- Toggle moves and drive the robot (see below).
make stop(or pressq) to stop;make shutdownto power off.
Controlling with the keyboard
| Key | Action |
|---|---|
v | toggle the walk move |
h | toggle the head move |
s | toggle the squat move |
| arrows | vx (up/down), vtheta (left/right) |
x | reset velocity to zero |
i | toggle the IMU/gyro display |
q | stop the control loop |
Controlling with a gamepad
A Bluetooth Xbox controller can be used instead of the keyboard. The detailed explanation of the gamepad usage is in Gamepad Guide.
Using a gamepad allows to drive the robot through two different modes: with a terminal (SSH) or fully headless (no SSH, no terminal). The second mode is particularly useful for demonstration purposes, due to the fact that it allows to drive the robot without any computer connected to it.
Moves
Moves are toggled independently and run on top of the neutral pose:
- Walk (
v/ gamepad A) — a reinforcement-learning policy. Once active, the velocity command drives it:vx(forward/back),vy(lateral),vtheta(turn), set from the arrow keys or the gamepad sticks. - Head (
h) — oscillates the head. - Squat (
s) — squat motion computed with inverse kinematics.
Velocity command
Every input source emits a normalized command in [-1, 1] per axis; the scheduler
maps it to physical limits with scale_velocity(), so the behavior is identical for
keyboard, gamepad and sim. Defaults (in constants.py):
| Axis | Max |
|---|---|
vx (forward) | +0.7 |
vx (backward) | -0.5 |
vy (lateral) | ±0.3 |
vtheta (turning in place, vx = vy = 0) | ±3.0 |
vtheta (while translating) | ±1.5 |
Developing: adding your own moves
Each behavior is a subclass of Move (src/moves/move.py) with
a simple lifecycle driven by the scheduler:
preload()— optional, called once before the loop starts (load heavy resources).on_start(obs, command)— called each tick while starting; setself.state = MoveState.ACTIVEwhen ready (e.g. after ramping in).step(obs, command)— called each tick while active; write your target joint angles intocommand.target_angles.on_stop(obs, command)— called each tick while stopping; setself.state = MoveState.INACTIVEwhen done (e.g. after ramping back to neutral).
To add a move:
- Create a new file in src/moves/ with a class subclassing
Move. Use rotate_head.py (a simple oscillation) or squat.py (inverse kinematics with placo) as a template. - Register it in src/main.py: add it to the
movesdict passed to theScheduler, and add a trigger — a key inMOVE_KEYS(keyboard) and/or a button inGAMEPAD_BUTTON_MOVES(gamepad). - In
step(), read the robot state fromobs.robot_state(motor positions and velocities, IMU gyro, projected gravity) and write your targets intocommand.target_angles.
Training your own walk (or other RL) policies
The walk move runs an ONNX policy trained in simulation.
You can train your own walking — or other learned skills — and drop the resulting .onnx file into src/agents/ to use it on the robot. Check the repository MarcDcls/mjlab_microban for the training pipeline.
If you achieve some interesting results, don't hesitate to make a pull request to the repository as it is also a community-driven project!