Everything passed because nothing ran.
Fourteen checks, none wired to the orchestration layer. Two weeks of trusting green.
Trip a gate deliberately before you trust it. if you can't make it fail, it's not running.
The sensor was publishing at 3.3Hz. I had it configured for 10. Spent two weeks re-tuning the controller.
Rate bugs look exactly like tuning problems. You chase parameters. The rate is invisible.
The fix was one line.
Translation matched within 43mm. Rotation came out at 0.926 rad. Gazebo gave 1.857 on the same turn.
<dynamics damping> is in both URDF specs. PhysX reads it as a velocity gain. At 0.01, the joint slips.
Diff the numbers after every transfer. Not the video.
Same reward score. Stride frequency 2x apart, completely different gaits.
The optimizer didn't hallucinate. You forgot to penalize regularity. It filled that gap however it wanted, and you never got to choose.
Odometry said +23.5. gyro said +25.9. both wrong, same direction.
fused estimate was confident and precise and pointing nowhere real. both sensors measuring against the same bad reference.
two sensors agreeing on a bad number looks like health.
Bad sonar return and a drifted EKF look identical in the hull map. wide covariance at least tells you something's off. tight covariance from a bad init gives you clean-looking garbage.
Ran six seeds after I already picked the winner. Wrong winner.
Smooth loss curve, real eval score. It was measuring which initialization got lucky.
Three seeds is the floor. One is an anecdote with a loss curve attached.
Five of six runs returned kp=200. that was my search ceiling.
the optimizer hits a bound and just returns a number. no warning.
if the winner equals your constraint, the run doesn't count.
Imported a URDF. 76 of 77 values matched. robot ran, nothing looked wrong.
the 77th was axial inertia, wrong axis. every rotational controller was running on bad data.
full tensor readback, every environment transfer. otherwise you're just hoping.
`<dynamics damping>` in Gazebo is energy dissipation. In PhysX it's a velocity-tracking gain. same field name.
straight-line matched within 43mm over 725mm. rotation was off by 2x. only tested straight-line.
passing straight-line tests means nothing about rotation.
Twelve quality gates. Six never got called.
Ran for two weeks. Green every time.
You can't tell from the output. Only real test: push garbage in and see if it fails.
Publishing at 0.33x. sensor alive, looked fine.
filter felt wrong, we retuned. numbers improved slightly. that was the worst part.
measured actual publish rate over 30s. found it.
rate bugs don't throw errors.
Every inertia tensor in the URDF matched a closed-form sphere. All 7 links. Nobody had measured anything.
Sim ran. Robot moved wrong. Weeks on gain tuning before I looked at the model.
The import check passed every time.
Tight EKF covariance is the most dangerous output in robotics. Odometry read 23.5°. Gyro read 25.9°. Filter settled on gyro, high confidence. Both sensors were loaded by the same cable tension. Kalman can't see that.
Same robot, dropped into Isaac Sim after living in Gazebo for a while. Not posting this as a result, just the build log. Driving is the milestone today.
Same URDF, 2x rotation error Gazebo to Isaac. translation matched, so the migration looked fine.
`<dynamics damping>` is joint dissipation in Gazebo and velocity gain in PhysX. if your test is straight-line only, you never see it.
Tried to reproduce an ugly gait. couldn't.
stride frequency varied 2x across configs scoring identically. both reward-optimal.
the blank parts get filled by whatever's efficient.
Ran the full nav stack through a warehouse scene with people and obstacles in it. Not measuring anything yet, just wanted to see the whole pipeline hold together end to end.