Paper experiments: protocols and reproduction status#
These scripts evaluate experiments associated with the GATO paper. Runnable does not mean numerically reproduced. Keep published results, historical datasets and fresh evaluations of the current code distinct. A correctness receipt is not a timing report.
Current-code numbers: docs/figure-refresh-2026-10-01.md.
Setup and modes#
Use the project .venv; ./tools/install.sh --examples supplies simulation AND
plotting dependencies (--test alone does not include matplotlib). Build with
JOBS=2 ./tools/build.sh --profile receipt, or select only the needed modules.
Scripts resolve inputs independently of cwd; run the commands below from the repo root.
# No GPU or result writes: preview the focused checkpoint.
examples/benchmarks/run_merge_checkpoint.sh --dry-run
# Render trusted saved data; does not evaluate the current solver.
.venv/bin/python examples/paper-figures/reproduce_fig4_hparam.py --replot
# Small correctness smoke, NOT paper numbers (uses GPU).
.venv/bin/python examples/paper-figures/make_all.py --only fig4,fig5 --quick
Fig-3 assembles saved CSVs by default. Timing lanes need
--run-gatoor--run-btand an exclusive quiet window; MPCGPU cells are imported from that repository’s own timing run with--mpcgpu-timing-dir.Fig-4/5/7 regenerate on the GPU by default.
--replotloads existing data;--quickis a plumbing smoke, not a statistical reproduction.Pickles are trusted local artifacts; never load arbitrary downloaded pickles.
Generated pools/plots need not exist in a fresh clone. Fig-4 has a bundled fallback; other replot commands require their inputs first.
Figure scope#
Script |
Modules |
Meaning and current limitation |
|---|---|---|
|
iiwa14 N64 (left); N8/16/32/64/128 (heatmap); |
Matched three-solver fig8 benchmark on an identical problem; ratios are not the paper’s (different robot, harness, timing boundary) |
|
iiwa14 N64 |
Normalized merit vs SQP iteration; recovered grid differs from paper text |
|
indy7 N64 |
Fixed-pacing disturbance rejection; does not reproduce latency-induced degradation |
|
iiwa14 N16 |
Pick-place success vs batch size on two task settings (stop: 15→100 %; pass-through: 26→97 %), refreshed Oct 3 |
Fig-6 is a simulation snapshot, not a numerical regression target. Fig-8 / Table-II require physical hardware; preserve them as published results unless new hardware experiments are performed.
Fig-3: matched comparison, different robot#
The current harness uses iiwa14; the published scalability figure used Indy7.
benchmarks/iiwa_fig8_shared.py defines the common trajectory, EE frame, costs
and budget (SQP=1, PCG cap 200 / relative tolerance 1e-4, rho=0.01). Every lane
takes --robot {iiwa14,indy7} (iiwa14 default, names unchanged). The Indy7 lane
runs the SAME fig8 (A = 0.15 m, period 6 s, center = EE at INDY7_START_CONFIGS["ready"])
for GATO and the CPU solver only — MPCGPU has no Indy7 build or goal file, so the
Indy7 goal is synthesized from the formula — and writes *_indy7 CSVs and figures
(sweep_fig8_gato_indy7.csv, fig3_fair_scalability_indy7.png, …).
GATO:
../benchmarks/sweep_batch_iiwa_fig8.py(N and batch sweeps).CPU:
../benchmarks/baselines/track_iiwa_fig8_bt.py, multi-threaded C++ QDLDL-based CPU solver (OSQP with QDLDL,pysqpcpu) built bybuild_cpu_baseline.shin its separate pinned environment.MPCGPU: that repository’s
tools/timing.pyfigure-eight plan (same costs and budget), imported with--mpcgpu-timing-dir; it has no batch axis, so the displayed baseline is sequential B × single-solve.
The assembler consumes ../benchmarks/data/sweep_fig8_{gato,bt,mpcgpu}[_indy7].csv.
Pre-July-30 data used the wrong terminal frame and the June point-to-point data a
different task; neither is a baseline for these sweeps.
The GATO sweep records internal solver duration, not Python or controller
latency; the paper timed around wrappers. Match boundaries before quoting
speedups. The sweep’s warm-start seed is explicit (--initial-guess zero-tail,
the historical choice; hold for a controlled comparison — the two differ by
up to 7%, see the refresh document). Each CSV has a .runs.jsonl companion and a
hashed frozen reference .npy; never mix seeds. --check-only verifies
raw/controller bitwise parity without timing.
For paired internal-solver and Python-controller call durations, reserve a quiet
window and run examples/benchmarks/run_timing_handoff.sh --suite boundaries
with GATO_QUIET_WINDOW=1. Its --dry-run is safe without a window. This lane
uses N64, B1/8/128, three repeats per arm, a frozen reference and the same
zero-tail seed. The .call-boundaries.json beside each CSV retains paired raw
samples after ten warmups. The outer boundary is MPCController.step, including
its wrapper work, but excluding reference construction, sensing, simulation and
actuator I/O. It is not a complete robot-control deadline measurement.
Fig-4: choose and name the grid#
Defaults evaluate 50 random targets × 24 Q/R combinations, matching the
recovered dataset. The paper text describes 100 runs × 81 cost choices.
--num-targets changes the target count, not the missing cost-grid definition.
Document the chosen grid before refreshing the figure; do not claim exact
paper reproduction without reconciling that difference.
Fig-5: quality and latency are different experiments#
The script uses pace_by_solve_time=False. Its force sweep and 50 N trajectories
measure control quality at fixed simulation pacing, useful even on a shared GPU.
They do not model additional actuation delay from larger batches. The paper’s
latency-induced degradation needs a separately specified delay/pacing experiment
on a quiet box. Replotting historical data is not a refresh; data predating the
July force/frame fixes is unsuitable for current validation.
Fig-7 / Table I: refreshed October 3, 2026 (corrected simulator, identified-weight batch)#
Simulator correction (September 27): the old initialization wrote an axis-angle vector
into quaternion xyz with w=0 and placed robot velocities at wrong offsets in the augmented
state. Corrected runs use Pinocchio manifold integration and are labeled
unit-quaternion-pendulum-v2. Historical pools (and the paper) are not comparable.
Two task settings (October 3): --task stop (default) tests arm arrival with a dwell,
not payload placement — the EE reference ramps to each goal over 1.5 s (minimum jerk) and the success gates
must hold 100 ms — run with the paper’s exploration sampler: 15 / 100 / 99 / 98 % at
B = 1 / 8 / 32 / 128 on 100 seeded scenarios. --task pass-through uses step references
and an instantaneous gate in the corrected simulator, with the identified-weight sampler
(IdentifiedWrenchSampler, --estimator wid): 26 / 83 / 97 / 95 %. Batching is the lever in
both; the batch is filled differently because a swinging load must not be chased when the arm
has to stop, while knowing the load pays when flying through. The paper’s ForceEstimator
never identifies a 15 kg payload (vertical estimate ≈ −17 N against 147 N) — on the
pass-through task it gives 6 / 62 / 84 / 82 %. --success-plot renders
fig7_success_vs_batch.png; numbers, diagnosis and the secondary rows are in
docs/figure-refresh-2026-10-01.md. --estimator, --goal-ramp, --settle-time,
--qd-cost, --pend-mass override a preset; tag every variant apart.
For shared-box GPU correctness, check_pickplace.py --scenarios 1,2 --out <new-dir> [--estimator fe|wid] replays seeded cases with fixed pacing, checks finite/deterministic
traces and records goal gates; it retains no latency measurements. Pools are fixed-paced
and deterministic, so they need no quiet window (they do disturb anyone else’s timing).
These are exploratory results: the seed-0 pool was reused during tuning, the stop pool records a dirty source tree, and neither task enforces actuator limits or payload settling. Never overwrite an old pool: tag every protocol change.
Held-out Fig-7 correctness validation#
fig7_validation_protocol.json freezes 100 separate seed-20261004 scenarios,
four batch sizes and three arms: stop/FE, pass-through/identified-weight, and
stop/FE with a torque penalty plus a hard simulator torque clamp. No tuning is
allowed on this holdout. All arms record actual applied torque, joint-position
and velocity violations, and payload swing; an arm-arrival success is not a
payload-placement or safe-robotics claim. The clamp enforces torque only, not
position or velocity constraints.
From a clean, committed checkout with the current iiwa14 N16 module built:
.venv/bin/python examples/paper-figures/validate_fig7.py docs/open-tasks/fig7-heldout
.venv/bin/python examples/paper-figures/summarize_fig7_validation.py docs/open-tasks/fig7-heldout
This is fixed-pacing correctness work, not timing. Coordinate GPU sharing first.
--limit 1 runs a partial smoke; rerun without that option to finish the same pool.
Create STOP in the output directory to pause between episodes; remove it to
resume with the same command, source commit, protocol and binary. Completed
episodes are not overwritten. Changing any identity requires a new directory.
Only a complete 1,200-episode pool supports the full protocol summary.
Merge checkpoint versus research refresh#
The focused runner samples Fig-3 at
N64 / B=1,8,128 with three process repeats and the Fig-7 stop task at B128 /
ten seeded scenarios: a regression sample, not a refresh. Compiler measurements
and autotuning are opt-in legs of ../benchmarks/run_timing_handoff.sh. Still
open for a research refresh: Fig-4’s exact cost grid and Fig-5’s latency
experiment. ../benchmarks/run_timing_night.sh is the legacy broad run (sibling
repository work, full Fig-7); do not launch it blindly on a shared machine.
Provenance and interpretation#
The paper used an RTX 4090 / CUDA 12.6 setup. Different hardware, compilers, models and budgets can change absolute times AND relative speedups. Re-run all compared lanes with matched accuracy before making a new performance claim.
Retain source/submodule SHAs, binary/configuration provenance, hardware/toolchain,
seeds, pacing, sample counts, metric definitions and exact commands. Record
missing provenance rather than mixing pools. _common.load_data prefers a
regenerated local pickle over its bundled fallback and prints the selected
source: check that output. Archaeology is a dated
record of recovered data, not the current reproduction verdict.