A custom-designed 8-DOF quadruped (thigh and calf per leg, no hip motors) driven by 8 Unitree GO-M8010-6 motors and controlled from an onboard Jetson. The goal: train a walking policy entirely in simulation with reinforcement learning (PPO, MuJoCo + Gymnasium), then deploy it on the real robot and close the loop between sim and hardware until it walks forward reliably in both.
CAD → sim training → export → real deployment, with real-hardware findings feeding back into reward and sim tuning
Real (left) vs. simulation (right): the trained standing policy
A standard PPO setup, deliberately kept simple: the actor and critic see the exact same observation, nothing privileged or asymmetric between them. The only place privileged sim-only state (true torso height, tilt, velocity) gets used is reward computation, which trains both networks through the normal PPO loss. Difficulty (domain randomization, target walk height, learning-rate/entropy decay) is controlled by manual flags set at launch, not an automated curriculum.
Shared observation into a symmetric actor-critic; reward alone draws on privileged sim state
Real (left) vs. simulation (right): the trained walking policy
A gait that's rewarded for keeping the torso level ends up drifting backward as it walks, eventually tipping over onto its back. The fix: reward a deliberately forward-pitched torso instead of a level one, closer to how the robot naturally carries itself while moving, and it gives the policy a stable direction to lean into instead of hunting around level.
Pictured: simulated target behavior, currently being deployed to hardware
Mean episode reward over ~14.5M PPO training steps for one of the walk fine-tuning runs (`back_clearance_v1`), a fairly clean, steady climb, typical of a run once the reward shaping for that stage had settled.
rollout/ep_rew_mean over training, PPO
Most small quadrupeds direct-drive the calf from a motor mounted on the swinging thigh link. This robot instead mounts both the thigh and calf motors on the torso, and drives the calf joint through a timing belt routed through the thigh, keeping both motors' mass close to the body instead of out on the leg. The tradeoff: the calf's real-world angle is no longer just "thigh angle plus a hinge" the way a direct-drive design would be. Rotating the thigh alone doesn't move the calf at all; the belt cancels it out. The simulation has to account for that conversion explicitly so the trained policy and the real robot always agree on what a given calf command means.
Real (left) vs. simulation (right): hand-swinging a leg's thigh, the calf follows through the belt/pulley coupling in both
A simulated demo of the traditional design this robot avoids, built purely to illustrate the difference described above.
A direct-drive, coupled calf mechanism, simulated for comparison
Because of the belt decoupling mechanism, when the hip (thigh) rotates, the knee and feet counter-rotate. As a result, the physical range of motion the knee joint is allowed to move in shifts dynamically based on the thigh's rotation. Raw torque control can't represent that shifting coupling directly, so any torque-based scheme still has to separately track and correct for it. An impedance controller (a torque/position hybrid where a commanded target angle relies on virtual stiffness and damping to produce torque) is a real, viable way to handle this too, and was on the table. But it adds a second layer of tuning on top of the belt-coupling bookkeeping: choosing and validating stiffness and damping gains around a moving, coupled target, not just computing the target itself. Position control needed only the latter. Calculating the precise, coupled target angles and commanding them directly provided a simpler mental model and a much shorter path to a working controller. Working under a hard project deadline, that faster, more tractable path won out over the theoretically more capable but slower-to-get-right impedance approach.
Position control alone doesn't set how fast the robot moves; that comes from a separate per-motor cap on how quickly a commanded target angle is allowed to change, in degrees per second. Early in training this cap is left deliberately loose (1000 deg/s) so PPO has enough freedom to discover a working gait at all; a tighter cap that early had previously stopped a gait from being found in the first place. Once a gait is established, a curriculum tightens the cap over training, ramping it down to 250 deg/s, the same limit already enforced on the real robot's deployment node. Training against that same real-world limit closes a sim-to-real gap: the policy learns to work within the actual speed the hardware allows, rather than relying on motor speeds sim would permit but the real motors can't deliver.
Real (left) vs. simulation (right): the trained trotting policy
Real (left) vs. simulation (right)
Fine-tuning a walk policy from a strong existing checkpoint climbed steadily for the first ~3M steps, then reward crashed to less than half its peak before slowly, partially recovering, while the policy's own action noise (its exploration std) never stopped climbing for the entire run. Consistent with this project's own separate finding that fine-tuning an already-good checkpoint at too high a learning rate can push it toward instability instead of refining it.
A real walk fine-tuning run: reward (top) destabilizes mid-run and partially recovers, while action noise (bottom) never settles
Real (left) vs. simulation (right): the trained cantering policy
Each gait shown on this page came from its own reward-shaping pass: the same PPO setup, but a different sequence of small, targeted reward and termination changes to get from a generic locomotion objective to that specific gait's behavior. These are the real iterations, pulled from the training history, not a stylized summary.
Standing — target pose to a robust, all-four-feet stand
Walking — dragging knees to a fast, stable walk (walk_position_hf_v17)
Trotting — diagonal symmetry, ramped speed target (fv25_ramp_v1)
Galloping — same setup, no ramp: speed wins first (fv25_v1)
Cantering — antiphase reward, tuned until it sticks (antiphase_ramp_v2)
Robot assembly timelapse
Extended walk
Grass
Gravel
Rocks
Indoor floor
Walking (hf_v15)
Walking (hf_v17)
Cantering
Galloping
Trotting