arm-pickup-lag
Two-link arm · solved 14 of 14 agent attempts pass
more
Reference designs: PD/PID loops are unstable under the 30 ms of lag at the stiffness the payload needs, nominal computed torque droops under the payload, adaptive computed torque passes; the adaptation must converge within a 0.8 s move.
Gate. per-seed success is the `settles` rung of this benchmark's ladder ['safe', 'reaches', 'settles', 'tracks'] (`--success-mode settles`), not the evaluator's default flag; the task is solved when the success rate over the grader's held-out seeds is `>= 0.9`
Axes: plant:two_link_arm, scenario:lag_noise_v1, payload:unknown-pickup, actuator:lag20ms-delay10ms, gate:settles
Each video re-runs the attempt's final controller through the task's own evaluator on a public seed (never the grader's held-out ones). The table under each video is the official grade on the held-out seeds.
lag_noise_v1| criterion | graded | needed |
|---|---|---|
| base:settles | 1.000 | ≥ 0.900 |
The agent's final message
Done. The final controller at `/app/work/controller.py` passes `settles` (and the full ladder, including `tracks`) on all 151 seeds I tested — seeds 0–150 — comfortably above the 0.9 gate. **The control law** is a computed-torque servo with four pieces, each added to fix a specific observed failure: 1. **Inverse dynamics + joint-space servo.** The task-space reference is mapped through closed-form IK (elbow-up branch) and a damped Jacobian inverse; the desired acceleration `qdd_ref + KP·e + KD·ė` goes through the full model `M(q)q̈ + C + G + Fv·q̇`, which is exactly known except for the payload. The reference radius is clamped to ≥ 0.17 m so mid-move chords can never command the elbow into its mechanical stop. 2. **Delay predictor + lag inversion.** The actuator (10 ms pure delay + 20 ms first-order lag) is known exactly, so the controller models the applied torque, rolls the rigid-body model ~1 step forward, and servos on the predicted state; the commanded torque pre-compensates the lag (`u = y + LEAD·(τ_des − y)`). This was what cut the noise-driven jitter that kept violating the 0.1 m/s settle-speed limit, together with reduced gains during the dwell tail. 3. **Payload estimator.** The estimate is pinned to 0 before segment 2, jumps to a 0.6 kg prior at pickup (a task guarantee), then is read off the quasi-static gravity torque balance in a short window early in each dwell. 4. **Integrator discipline.** The subtle bugs were all interactions here: the integrator and estim…
A computed-torque controller predicts the arm state forward across the known command delay and actuator lag, tracks a min-jerk IK joint reference with PD plus feedforward through the full dynamics model with an estimated payload, and pre-compensates the lag with a lead before clipping to the torque limit.
Shown: public seed 0 (lag_noise_v1); this episode passes the settles rung. This episode: max_end_error 0.000441, max_settle_error 0.000523, hold_error_max 0.000306, track_rms 0.00722, track_peak 0.0243, saturation_ratio 0, coupling_peak_max 7.31, payload_mass 0.871, limit_violation 0, total_reward -3.69.
controller.py · trial arm-pickup-lag__dmWLvFN