hopper-blackout
Hopper (MuJoCo Hopper-v5) · solvedexploration 3 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
With probability 0.015 per 8 ms control step every measured channel freezes at its last value for 12 steps (96 ms), roughly 15 % of the time, while the plant moves on; the controller's own clock (time, step) and last_action keep running. A memoryless feedback law acts on stale state during a blackout, and the hop cycle (0.3-0.5 s) is short enough that a 96 ms freeze straddles touchdown or lift-off, so the design has to detect staleness (a repeated observation) and bridge it with an internal phase or a state estimate. Physics nominal; gate forward (3 m) on 0.9 of the seeds. Open: the hopper-forward oracle scores 0 under blackouts.
Gate. per-seed success is the `forward` rung of this benchmark's ladder ['alive', 'forward', 'brisk', 'fast'] (`--success-mode forward`), 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:hopper, scenario:blackout_v1, gate:forward_3m, exploration:new-mechanism, sensing:intermittent
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.
blackout_v1| criterion | graded | needed |
|---|---|---|
| base:forward | 1.000 | ≥ 0.900 |
The agent's final message
`/app/work/controller.py` passes. It reached 20 of 20 on seeds 0–19 and 60 of 60 on seeds 100–159 under `blackout_v1` with `--success-mode forward`. Every seed stayed alive for the full 1000 steps and finished at about 13.1 m. That clears the `brisk` rung but not `fast`. I only tested `blackout_v1` and the nominal plant, not the other scenarios. The controller works like this: - **Gait:** it stands for about 28 steps, then runs a periodic hop. A clock drives six-point joint-angle tables for hip, knee and ankle, and each joint follows its table with a PD law. One cycle is about 0.58 s. - **Pitch feedback:** it shifts the hip target by the torso pitch and pitch rate. It also adds an ankle term while the foot is on the ground. - **Blackouts:** a repeated observation (same height, pitch and thigh) marks a blackout. The plant is nominal and fully measured on the blackout's first step, so the controller re-simulates its own MuJoCo copy of the hopper using the executed commands. It then feeds the gait the simulated state, so a blackout changes nothing. - **Dependency:** the dead-reckoning imports `mujoco` and `hl_control.envs.hopper` inside `controller.py`. The grader runs in a fresh copy of the original environment, which should have both, but I haven't confirmed that. The knot values and gains came from random hill-climbing on the visible seeds. Earlier attempts without the simulator copy (holding the last action, or extrapolating from held rates) failed under blackouts. They f…
After a standing phase, a phase clock drives 6-knot cosine-interpolated joint-angle tables tracked by PD servos with pitch feedback added to the hip target and ankle, while a re-simulated plant model replaces the stale observations during blackouts.
Shown: public seed 0 (blackout_v1); this episode passes the forward rung. This episode: episode_steps 1000, x_final 13.1, min_height 1.09, max_abs_pitch 0.143, n_flights 14, total_reward 2641.
controller.py · agent transcript · trial hopper-blackout__ub7S8i7
blackout_v1| criterion | graded | needed |
|---|---|---|
| base:forward | 0.850 | ≥ 0.900 |
The agent's final message
The final controller is in place at `/app/work/controller.py` and passes the gate. **Result** | Check (blackout_v1, forward rung) | Rate | |---|---| | Official verifier, visible seeds 0-9 | 10/10 | | Tuning seeds 0-35 | 36/36 | | Tuner revalidation seeds 36-59 | 24/24 | | Fresh seeds 60-119 (my harness) | 55/60 | | Nominal plant standard_v0, seeds 0-7 | 8/8 | Passing episodes cover 5 to 7 m (about 0.8 m/s), well above the 3 m gate. The remaining failures are late pitch falls at cruising speed, so the expected held-out rate is roughly 92 to 96%. **Control law** (documented in the file's docstring): a slide-hop cycle. The leg folds slowly toward a crouch so the body slides forward over the planted foot, which is quasi-static and therefore blackout-tolerant. When the centre of mass, computed by planar forward kinematics, is a set distance ahead of the foot, a short knee thrust launches a hop; in flight a soft PD straightens the leg so the foot lands forward, and a stiff landing phase with an ankle toe-push brakes the body before the next slide. The hip holds torso pitch in stance. **Blackout handling** was the decisive part. Repeated observations are detected by exact equality; joint angles are dead-reckoned over at most 50 ms, pitch is not extrapolated, the hop trigger and contact-based transitions are suspended while blind, and the hip torque is zeroed. Stale hip torque was the dominant toppling mechanism in traces, and cutting it raised the rate from about 70% to over 90…
A phase-based state machine slides the body forward over a planted foot via ramped joint PD targets, triggers a knee thrust hop when the CoM passes the foot, flies to a landing posture, then lands with PD plus ankle balance, while detecting sensor blackouts and falling back to time-based transitions with dead-reckoned joints and no hip torque.
Shown: public seed 0 (blackout_v1); this episode passes the forward rung. This episode: episode_steps 1000, x_final 5.06, min_height 1.13, max_abs_pitch 0.0706, n_flights 12, total_reward 1633. No public seed among the first 24 reproduced the graded outcome; this is a typical episode. It was the first failing one of 24 public seeds tried.
controller.py · agent transcript · trial hopper-blackout__B6naX53
blackout_v1| criterion | graded | needed |
|---|---|---|
| base:forward | 0.200 | ≥ 0.900 |
The agent's final message
The controller in `/app/work/controller.py` does not meet the gate. It succeeds on about half of the seeds, and the gate needs 0.9. It is a sampling-based model-predictive controller, not a hand-tuned hop. Every few steps it simulates 128 perturbed 50-step torque plans on the MuJoCo hopper model. It applies the first command of the best one. The cost rewards alive time, a tall torso and a target forward speed of 0.6 m/s. Once about 3.3 m has been covered it switches the target speed to 0 so the hopper settles. For blackouts it detects a repeated `gym_obs` and steps an exact copy of the plant with the last command. The state estimate stays correct because the physics are nominal. `x` is dead-reckoned from `x_velocity`, since position isn't observed. **Results on `blackout_v1`:** - **Official verifier, seeds 0–1:** success rate 0.5. Seed 0 passed. Seed 1 reached 3.39 m, then fell at step 600. - **My own harness, seeds 0–7:** 4 of 8 stayed alive for 1000 steps and finished at 3.6–4.2 m. Seeds 0, 2, 3 and 6 passed. - **Failures:** seeds 5 and 7 fell early, at about 200–260 steps and under 2 m. Seeds 1 and 4 passed 3 m and then fell later. **Variants I tried, none better than about 50%:** - Larger sample count or a longer horizon. - Extra penalties on joint posture, pitch rate, torso height and vertical speed. - A faster target speed, and a non-zero stopping speed. **Other risks:** - **Speed:** an episode takes roughly 70–150 s of wall-clock on this loaded machine. The grader…
Every few steps it samples 128 noisy perturbations of a warm-started 50-step torque plan, rolls them out in a coarser-timestep MuJoCo model, scores speed tracking, height, pitch and fall penalties, and applies the first command of the best plan, while propagating the exact model forward when measurements are blacked out.
Shown: public seed 1 (blackout_v1); this episode fails the forward rung. This episode: episode_steps 600, x_final 3.39, min_height 0.678, max_abs_pitch 0.184, n_flights 16, total_reward 1022. It was the first failing one of 2 public seeds tried.
controller.py · agent transcript · trial hopper-blackout__gCb8mTF
blackout_v1The agent's final message
I didn't solve the task. The controller now in `/app/work/controller.py` meets the `forward` rung on only **1 of the 5 visible seeds (20%)**, far below the 0.9 gate. I stopped at 53 of the 60 minutes because another tuning round takes 5–7 minutes and wouldn't have closed that gap. **Official verifier result (`blackout_v1`, seeds 0–4, `--success-mode forward`):** | seed | steps survived | x (m) | passes? | |---|---|---|---| | 0 | 1000 | 3.09 | yes | | 1 | 525 | 1.92 | no | | 2 | 676 | 1.83 | no | | 3 | 995 | 2.91 | no (fell 5 steps from the end) | | 4 | 330 | 1.03 | no | Every failure is the torso pitching past ±0.2 rad. Height stays above 1.03 m on every seed, so it never collapses. **What the controller does:** - **Blackout handling:** it keeps its own copy of the Hopper physics model. A fresh measurement resets the copy to the measured state. When an observation repeats exactly, it treats that as a blackout and steps the copy forward with the command actually sent. - **Control:** each step it simulates 48 random variations of its current plan, 60 steps (0.48 s) ahead, on that copy. It scores them on holding 0.5 m/s, keeping the torso level and the leg in a sensible posture, and staying healthy. It sends the first command of the weighted best plan. The docstring explains each gain. **What I tried before this:** - **Hand-built hopping gaits:** these never got past the first hop. With the thigh at its 0 rad limit the hip can't correct a nose-up pitch, and pushing off with…
Each step the controller resets or propagates a private MuJoCo state estimate (propagating when the measurement is bit-identical to the previous one, i.e. a blackout), samples 48 noisy 60-step control sequences, rolls them out, scores them with speed, pitch, height, posture and effort costs plus a failure penalty, and applies the first action of the softmax-weighted average plan.
Shown: public seed 0 (blackout_v1); this episode passes the forward rung. This episode: episode_steps 1000, x_final 3, min_height 1.1, max_abs_pitch 0.155, n_flights 27, total_reward 1374. It was the first failing one of 1 public seeds tried.
controller.py · agent transcript · trial hopper-blackout__BAhs9hp