soft-arm-reach
Soft continuum arm · solvedexploration 9 of 9 agent attempts pass
Exploration task. Built after the paper's sweep to test whether a task can force a mechanism outside the catalogue (docs/exploration_new_mechanisms.md, docs/soft_arm_spec.md). Not part of the benchmark tiers or of the paper's main counts; the soft arm is reported in the paper as a plant outside the sweep, the other tasks are not; all sessions ran under the paper's protocol.
more
Six tip targets per seed, each to be held within 10 mm for 2 s inside its 10 s window. A one-shot inverse of the nominal model drifts out under hysteresis and creep; the design has to keep correcting from the tip error alone. Gate fine on 0.9 of the seeds; the fast rung (every hold complete within 5 s) is open to a better design than the oracle, which reaches it on half the seeds.
Gate. per-seed success is the `fine` rung of this benchmark's ladder ['safe', 'coarse', 'fine', 'fast'] (`--success-mode fine`), 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:soft_arm, scenario:nominal_v0, gate:fine_10mm, exploration:soft-arm, material:unknown-per-seed
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.
nominal_v0| criterion | graded | needed |
|---|---|---|
| base:fine | 1.000 | ≥ 0.900 |
The agent's final message
The controller in `/app/work/controller.py` passes the `fine` rung on all 360 nominal seeds I ran (0–359). On every one of them, all six targets were held within 10 mm, and the worst best-2-second hold error on any target was 2.98 mm. The official evaluator on seeds 0–4 reports `solved=True` and passes every rung, including `fast`. The grader uses other seeds, so this is an estimate of its result, not a guarantee. The session took about 19 of the 60 minutes. **How it works** - **Starting command:** when a new target appears, the controller searches the nominal arm's static map for the commands that put the tip there. If two arm shapes reach the target about equally well, it picks the one closest to its current command, so the arm doesn't jump between the S and C shapes. - **Correction:** on each new camera frame, it turns the tip error into a command change using the map's local slope. The slope inverse is damped so it stays bounded below the mount, where the map is nearly singular. It adds that change to the command bit by bit, at gain KI = 1.0 per second. This absorbs this seed's unknown stiffness, chamber gains, hysteresis and creep. - **Pressure range:** below full command it matches `chamber_commands` with a 0.1 co-contraction bias. Beyond that it lowers the opposing chamber below the bias, so the full pressure difference is still available. **What the gain tests showed** - With KI = 1.5 one nominal seed failed (seed 25: low damping, oscillating 2–25 mm about the targe…
On each new target it sets the pressure-difference command to the inverse of the nominal static tip map, then on each fresh camera frame integrates the tip error through a damped Jacobian pseudo-inverse (with step clamp) to correct the command, which is mapped to four chamber pressures with co-contraction bias.
Shown: public seed 0 (nominal_v0); this episode passes the fine rung. This episode: hold_error_max 0.000312, targets_held_fine 6, targets_held_coarse 6, settle_time_max 4.28, final_error_max 0.00054, track_rms 0.0195, saturation_ratio 0, max_speed 0.74, stiffness_scale 1.08, payload_mass 0, total_reward -21.4.
controller.py · agent transcript · trial soft-arm-reach__yV8kn9Q
nominal_v0| criterion | graded | needed |
|---|---|---|
| base:fine | 0.975 | ≥ 0.900 |
The agent's final message
The final controller is in place at `/app/work/controller.py` and passes the fine rung on every nominal seed I tested. Session used 31 of the 60 minutes. **Results on `nominal_v0`, fine rung** | Seed set | Fine pass | |---|---| | 0-4 (official evaluator) | 5/5 | | 0-199 | 200/200 | | 200-299 | 100/100 | Hold errors on converged targets are 1 to 3 mm, and the fast rung is reached on about half the seeds. Sibling scenarios on seeds 10-39: hook 30/30, warmup 30/30, payload 29/30, weak chamber 25/30, circle 3/3 at fine. The weak chamber is the one case the model does not cover, since its gain is per segment rather than per chamber side. A per-side variant was tested and made nominal worse, so it was dropped. **Control law** (documented in the file's docstring): - **Feedforward** from the nominal static map inverse at the target, divided by an online-identified per-segment actuation gain, ramped over 0.8 s on each target change so the step does not ring the 1.25 Hz mode. - **Gain identification** by damped Gauss-Newton on the steady-state residual between the measured tip and the nominal map at the gain-scaled measured pressure difference. It runs only when the tip is quiet and away from saturation, has a weak prior toward 1, and each update is removed from the integrator so the command stays continuous. - **Slow task-space PI** on a low-passed tip error through the damped pseudo-inverse of the map Jacobian, with conditional anti-windup and a reset at target changes. - **Acti…
The controller inverts a precomputed nominal static tip map for feedforward (scaled by an identified gain g and ramped on target changes), adds a filtered task-space PI plus velocity damping through a damped Jacobian pseudo-inverse, and wraps the resulting chamber pressure commands in a fast inner pressure feedback loop.
Shown: public seed 0 (nominal_v0); this episode passes the fine rung. This episode: hold_error_max 0.00169, targets_held_fine 6, targets_held_coarse 6, settle_time_max 4.54, final_error_max 0.00241, track_rms 0.0246, saturation_ratio 0.000333, max_speed 0.352, stiffness_scale 1.08, payload_mass 0, total_reward -31.2.
controller.py · agent transcript · trial soft-arm-reach__3aa5GZX