One set of legs, ten different robots
I'm building a walking robot that I can take apart and reconfigure. There are six identical leg modules and a body plate with eight places to attach them. Four legs makes a quadruped; six makes a hexapod; other arrangements give me different body shapes to test. The goal is for the robot to detect which legs are attached and use the same learned controller across all those configurations.
I started the semester planning to make a vacuum testbed, but switched to this project in week 4. It fits the class and gives me hardware I can use in my research afterward.
Why this robot
Some recent work suggests that a controller trained on a larger variety of simulated robot bodies can generalize better to new ones. That's exciting, but the physical validation so far has been limited. I want to find out whether the same trend holds when you test on more real robots. The catch is that most robots aren't easy to rebuild, and modular research platforms can be expensive. So I'm trying to make one that's relatively cheap and quick to reconfigure. If the hardware works, I'd like to run the experiment between December and February and aim for an IROS 2027 submission.
More broadly, this is the question I want to work on: how do we make controllers that can adapt when the robot's body changes?
What gets made, and in which week
The robot brings together most of the things we cover in class: 2D and 3D design, machining, 3D printing, circuit design, firmware, sensors and system integration. Here's how I'm planning to tackle the pieces across the semester.
| Subsystem | Week | What |
|---|---|---|
| Leg module | 4, 11 | Printed hip bracket, thigh with the servo pocketed inside, shin. A closed cable channel runs down the thigh, which is the part you cannot machine. Three STS3215 servos per leg: hip abduction, hip flexion, knee |
| Body board | 5, 6 | XIAO RP2040, IMU, half-duplex servo bus driver, 8 port-sense channels through an analog mux, 12 V in and a 5 V buck. Designed in week 5, milled and stuffed in week 6 |
| Body plate | 7 | Machined plate with 8 ports around the edge. Port positions are a variable in the experiment, so they are dimensioned precisely and live in the generator |
| Self-description | 8 | Each leg carries an ID resistor. The board reads it, pings the servos, and the same generator that makes training bodies makes the robot's own model |
| Servo control | 9 | 50 Hz bus loop: one sync-write of all targets, one read-back of position and current. Plus a hand-tuned tripod gait as the baseline that needs no learning |
| Feet | 10 | Cast silicone hemispheres, replaceable. Foot compliance is a known sim-to-real variable, so I measure one and put the number in the simulation |
| Experiment runner | 12 | Laptop program: read the self-description, load the matching policy, run trials, log everything. Live dashboard of the body diagram and joint states |
| Integration | 13, 14 | Tether, strain relief, emergency stop, first runs of a learned policy. Demo: someone in the audience picks a body, I plug it together, it walks |
The platform
| Part | Choice | Why |
|---|---|---|
| Actuator | Feetech STS3215, 12 V version (ST-3215-C018) | 30 kg·cm stall, 10 kg·cm rated, 12-bit magnetic encoder, reports position, current, voltage and temperature over one daisy-chained TTL bus |
| Leg | 3 joints, printed PLA/PETG links. Thigh 80 mm, shin 90 mm default; 70 and 110 mm shins as test variants | different shins make different bodies for free |
| Connector | one 4-pin latching connector per leg: 12 V, GND, DATA, ID | plug a leg in anywhere; the ID pin tells the board which variant it is |
| Body | plate with 8 ports; 6 modules built, so up to 6 legs at once | quadrupeds, hexapods, pentapods, asymmetric bodies, all from one plate |
| Compute | policy on a laptop at 50 Hz, over a USB tether to the body board | keeps the semester feasible; onboard compute is a later upgrade |
| Power | 12 V bench supply, 20 A, through the tether | 18 servos at 0.6 A walking is about 11 A; stall spikes higher |
| Target mass | quadruped about 2.1 kg, hexapod about 2.8 kg | with two feet down, each knee needs about 8 kg·cm: under the rated torque, with the stall figure as margin. Walking only; no jumping |
The simulation, already running
I'm developing the simulation in parallel with the hardware rather than waiting for the robot to be finished. I started that part in week 4 using MuJoCo MJX and JAX. For now it runs on my laptop CPU; the same code should be able to run on a GPU for larger training runs.
One awkward part of MJX is that environments in a batch need to share a model structure. I'm getting around that by using a six-legged base model for every robot and changing its parameters. For example, a missing leg becomes almost massless, sits tucked inside the body and has its actuator disabled. That lets one batch contain many different configurations. The controller also gets a compact description of the body: which ports have legs, where those legs are and their link lengths. Eventually I'd like the physical robot to generate that description itself.
generator.py module graph + parameters -> MJCF; the 10-body test set; random body sampler
env.py MJX environment, one batched model, a different body per environment
train.py PPO (brax) over a population of bodies; the 1 / 10 / 100 / 1000-body sweep
evaluate.py run a checkpoint on all 10 test bodies -> the simulation side of the scaling curve
pip install mujoco mujoco-mjx brax # GPU: pip install -U "jax[cuda12]"
python3 generator.py # the 10 test bodies stand under PD control
python3 train.py --smoke # CPU pipeline check, a few minutes
python3 train.py --mode scaling --n_bodies 10 --steps 100_000_000 --tag n10
python3 train.py --mode scaling --n_bodies 1000 --steps 100_000_000 --tag n1000
python3 evaluate.py runs/n1000.pkl # writes n1000_eval.json
The pipeline currently runs end to end on CPU: I've done a small 256-step training test and evaluated the policy on a tripod configuration. Proper training is the next step and will need a GPU. The actuator dynamics, foot friction and communication delays are still placeholders. I'll replace them with measurements as I build and test the hardware.
The experiment the robot is for
The experiment is to train four controllers, each exposed to a different number of simulated bodies: 1, 10, 100 and roughly 1,000. Then I'll test each controller, without fine-tuning, on the ten physical configurations shown above. I want to compare success rate and velocity error in simulation and on hardware. Does performance keep improving as training diversity increases, or does the real-world curve level off? Either outcome would tell me something useful about transferring controllers across morphologies.
I'm keeping the measurement setup fairly simple. An overhead webcam will track an AprilTag on the robot to estimate velocity, and I'll use servo current and voltage to estimate electrical energy use. I'll count a 30-second run as successful if the robot neither falls nor stalls. With five trials per condition, the main comparison comes to 200 runs. I'm budgeting about two days for testing and swapping configurations.
What could go wrong
| Risk | Know by | Then |
|---|---|---|
| No GPU for training | now | ask the lab or a cloud credit program |
| Servo bus too slow for 18 servos at 50 Hz | Nov 10 | two buses on two UARTs, or run the policy at 30 Hz |
| Hexapod cannot walk 2 m with a hand-tuned gait | Nov 10 | the mechanism is the problem; cut to four legs and fix it first |
| Sim-to-real gap too big for any learned policy | Dec 8 | fewer bodies; the paper becomes the gap analysis |
| No learned policy walks by the final | Dec 15 | platform plus simulation result go to a workshop; the real-world curve waits for a journal version |
Parts and ordering
| Item | Qty | By |
|---|---|---|
| STS3215 12 V servos, first batch (prototype leg + identification rig) | 4 | Oct 6 |
| STS3215 12 V servos, the rest (6 legs × 3 + 4 spares) | 18 | Oct 20 |
| Off-the-shelf bus adapter, to talk to servos before my board exists | 1 | Oct 6 |
| IMU breakout (BNO085 class) | 1 | Oct 13 |
| Latching 4-pin connectors | 20 | Oct 13 |
| 12 V 20 A supply (check the lab first) | 1 | Oct 27 |
| Webcam + printed AprilTags | 1 | Oct 27 |
| Rubber mat, play sand | Nov 10 | |
| Filament, silicone, plate stock (shop stock) |
Final orders close on December 4, so I need to order anything for the January experiments, including spares, before then.
Files
| generator.py | body generator: port map + parameters to MJCF, the 10-body test set |
| env.py | batched multi-body MJX environment |
| train.py, evaluate.py | PPO training sweep and the test-set evaluation |
| compat.py, README.md | JAX version shim; how to run everything |