apt-a1 · validation · MuJoCo free-walk replay
Every claim so far was that these trajectories are periodic under a lumped
single-rigid-body model and inside the A1's measured actuator limits. Neither says a real
12-DOF articulated robot can follow them. This replays library trajectories on the full
MuJoCo A1, unrestrained on flat ground — which also makes it the free-walk baseline
CONTEXT.md §5 says is missing, since every hardware run so far was on a hoist.
The initial run failed everywhere, and the trace showed why: the body sank at close to free fall for 150 ms, then got catapulted to 0.56 m and flipped. Feeding the stored feedforward torque was pulling the robot into the ground.
a1.py computed joint torque as
τ = JTf with f the ground reaction force. That is the work
the ground does on the leg; the actuator torque is τ = −JTf.
The feasibility filter never noticed because it only ever reads |τ| ≤ 33.5 — but
the stored torques are exactly what a torque decoder would be trained on. Confirmed statically
too: a leg holding mg/4 returned −5.70 N·m at the knee where
extension needs +5.70.Success turned out to be trajectory-dependent, not speed-dependent alone — two draws at the same commanded speed can behave completely differently. So this is 24 randomly drawn feasible trajectories per speed bin, not a hand-picked example.
| Speed (m/s) | trot survives 6 cyc | bound | median z RMS | median travelled | τ saturated |
|---|---|---|---|---|---|
| 0.25 – 0.75 | 83% | 71% | 0.015 m | 121% | 4% |
| 0.75 – 1.25 | 38% | 62% | 0.016 m | 87% | 54% |
| 1.25 – 1.75 | 8% | 21% | 0.013 m | 88% | 79% |
| 1.75 – 2.05 | 4% | 29% | 0.026 m | 50% | 92% |
|τ| at the 33.5 N·m ceiling climbs 4% → 92% in lockstep with the survival
collapse. Note what this means for the feasibility filter: it currently checks that the
feedforward torque fits under 33.5, but at run time the PD term adds on top of it.
The filter needs to reserve headroom, not spend the whole budget.ff is stored feedforward torque alone, pd is position tracking on
the stored joint angles, ff+pd is both — which is what a real controller does, and
what APT-RL's decoder-plus-corrections structure amounts to. Gains are the deployed
Kp 40, Kd 1.0 from deploy/parkour_run.cpp:396.
CONTEXT.md §4 says
higher Kp trips PowerProtect earlier (kp20 needs L3, kp40 needs L5). Rerun
at the real Kp 40, results got better: slow trot went from saturating the torque
ceiling to peaking at 26.6 N·m with the same tracking. Stiff gains were fighting the
feedforward instead of letting it do the work.| Case | Mode | Cycles survived | z RMS (m) | pitch RMS (rad) | Travelled / planned (m) | peak |τ| |
|---|---|---|---|---|---|---|
| trot v=+0.50 | ff | 6.00 | 0.0874 | 0.1443 | 0.41 / 1.84 | 21.2 |
| trot v=+0.50 | pd | 6.00 | 0.0393 | 0.1592 | 0.24 / 1.84 | 22.5 |
| trot v=+0.50 | ff+pd | 6.00 | 0.0152 | 0.0826 | 1.92 / 1.84 | 26.6 |
| trot v=+1.20 | ff | 2.58 | 0.1401 | 0.0943 | 0.51 / 1.91 | 21.7 |
| trot v=+1.20 | pd | 1.42 | 0.0958 | 0.4950 | 0.43 / 1.05 | 33.5 |
| trot v=+1.20 | ff+pd | 1.68 | 0.0495 | 0.1551 | 1.10 / 1.24 | 33.5 |
| trot v=+1.90 | ff | 1.02 | 0.0797 | 0.1138 | 0.81 / 0.97 | 23.6 |
| trot v=+1.90 | pd | 1.37 | 0.0962 | 0.3290 | 0.68 / 1.31 | 33.5 |
| trot v=+1.90 | ff+pd | 1.53 | 0.0589 | 0.2951 | 1.14 / 1.46 | 33.5 |
| bound v=+0.50 | ff | 1.61 | 0.0547 | 0.5956 | 0.65 / 0.32 | 23.0 |
| bound v=+0.50 | pd | 6.00 | 0.0350 | 0.2096 | -0.21 / 1.22 | 33.5 |
| bound v=+0.50 | ff+pd | 4.32 | 0.0315 | 0.3847 | 0.95 / 0.88 | 32.7 |
| bound v=+1.20 | ff | 1.05 | 0.0559 | 0.1779 | 0.43 / 0.46 | 23.3 |
| bound v=+1.20 | pd | 2.79 | 0.0687 | 0.3974 | 0.88 / 1.25 | 33.5 |
| bound v=+1.20 | ff+pd | 2.29 | 0.0559 | 0.2935 | 1.18 / 1.02 | 33.5 |
ff+pd, 6 cycles, real timeCONTEXT.md §3's open question about porting torque decoders to our
position-control deploy stack: the torques are useful as a feedforward term, not on
their own.Every number here is one hand-written replay harness away from being wrong, and it caught two
of my own errors already. This is sim, on flat ground, with a model whose contact parameters were never calibrated
against the real robot. It says the library is trackable in principle at low speed; it says
nothing about sim2real, and CONTEXT.md §4's warnings — PowerProtect
tripping earlier at higher Kp, the 15 ms transport delay — all still apply. Peak torque hits
the 33.5 N·m ceiling in every pd and ff+pd run, which on hardware is
precisely the condition that trips PowerProtect level 1 about 7 s in.