Instructions to use reachjalil/nottyduck-keeper with libraries, inference providers, notebooks, and local apps. Follow these links to get started.
- Libraries
- Microduck
How to use reachjalil/nottyduck-keeper with Microduck:
# Replace SLOT with the slot specified in the model card (walk, stand, sitstand, ground_pick, kick_left, kick_right, roulade). sudo robotctl policy load SLOT reachjalil/nottyduck-keeper
- Notebooks
- Google Colab
- Kaggle
NottyDuck keeper v1
A goalkeeper brain for the MicroDuck robot (a 25 cm bipedal robot with 14 servos), trained in simulation for NottyDuck Labs Test Chamber 02 · Keeper (https://nottyduck.com/labs/keeper). It is the chamber's default brain: open the page, fire a shot, and this keeper watches the ball and steps or dives across its line.
What it is:
- A simulation-trained policy, evaluated in simulation.
- Not validated on hardware. A real robot would need a ball tracker to supply its ball input.
Files
| File | What it is |
|---|---|
nottyduck-keeper-v1.onnx |
The policy, with the observation normalizer baked in. 61 inputs, 14 servo targets, 50 Hz, no action filter. Load it in the chamber's Compare step, or anywhere the MicroDuck 61D contract runs. |
checkpoint/model_900.pt |
The RSL-RL training checkpoint (actor, critic, normalizer, optimizer), saved with CPU tensors so it loads on any machine. Start fine-tuning from this. |
checkpoint/params/agent.yaml, env.yaml |
The exact runner and environment config of the run. |
recipe.json |
The chamber recipe it was trained by. |
training/events.out.tfevents.* |
TensorBoard curves for the run. |
Contract
- Input
obs, float [1, 61]: the standard MicroDuck proprioception (48) plus the 13D command block. The 6D body-command slot carries the ball's position and velocity in the trunk's yaw frame (body_command_term=keeper_ball_obs). The twist and head slots are zero. - Output
actions, float [1, 14]: joint offsets from the standing pose, one per servo. - The ONNX metadata records
task_id=Mjlab-Keeper-NottyDuck,observation_normalizer=baked,control_frequency_hz=50andaction_filter=none.
Training
- Task:
Mjlab-Keeper-NottyDuckin reachjalil/nottyduck,src/mjlab_microduck/tasks/nottyduck_keeper_env_cfg.py, at commit6f55745. - Simulator and algorithm: mjlab 1.3.0 (MuJoCo Warp) with the BAM XL330 actuator model, domain randomization, and observation noise and delays. PPO (rsl_rl).
- Recipe (
recipe.json): firm shots (0.9–1.8 m/s), corners spread (aimed up to ±24 cm across a 52 cm mouth), dives allowed, block, stay down, medium smoothness. - Run: 4096 environments × 900 PPO iterations (about 88 million environment steps), seed 1, on one NVIDIA RTX 4090, in about 35 minutes.
- Selection: it was picked from 8 parallel runs (2 recipes × 4 seeds).
Evaluation (browser chamber, 2026-10-16)
The chamber's Compare step fires 12 standard shots per round: ±7 cm and ±20 cm at 0.9, 1.4 and 1.9 m/s. Every round after the first nudges the launcher by a seeded ±3 cm, ±5 cm and ±4 %, and both brains face identical rounds.
| Brain | Saves | Goals let in | Went down |
|---|---|---|---|
| Stock stance (supplied walker, standing) | 0 / 48 | 48 | 0 / 48 |
| NottyDuck keeper v1 | 36 / 36 | 0 | 33 / 36 |
This was measured in browser MuJoCo, which uses the game's position servos, not training's BAM motor model. These are chamber measurements, not hardware evidence. The keeper usually goes to ground to make a save; the recipe allowed dives and did not reward getting back up.
Download, fine-tune and redeploy
Download the policy and checkpoint:
hf download reachjalil/nottyduck-keeper --local-dir nottyduck-keeperFine-tune from a NottyDuck checkout. Write your own recipe, for example to make it get back up after a dive:
mkdir -p logs/rsl_rl/nottyduck_keeper/from-hf cp nottyduck-keeper/checkpoint/model_900.pt logs/rsl_rl/nottyduck_keeper/from-hf/ echo '{"schemaVersion":1,"shotSpeed":"firm","shotSpread":"corners","landing":"dive","redirect":"block","recover":"rise","smoothness":"medium"}' > my-recipe.json NOTTYDUCK_KEEPER_RECIPE=my-recipe.json uv run train Mjlab-Keeper-NottyDuck \ --env.scene.num-envs 4096 --agent.max-iterations 400 \ --agent.resume True --agent.load-run from-hf --agent.load-checkpoint model_900.ptResuming continues from iteration 900, so the warm-up curriculum doesn't repeat.
--agent.max-iterations 400trains 400 more iterations (900 → 1300). On a CPU, try--env.scene.num-envs 64 --gpu-ids None --agent.max-iterations 5first; that only checks the setup.Export, which bakes the normalizer and records the contract:
NOTTYDUCK_KEEPER_RECIPE=my-recipe.json uv run scripts/export.py Mjlab-Keeper-NottyDuck \ --checkpoint-file logs/rsl_rl/nottyduck_keeper/<your run>/model_1299.pt --onnx-file my-keeper.onnxRedeploy:
- Open https://nottyduck.com/labs/keeper#compare, choose Load a keeper
brain, and pick
my-keeper.onnx. It runs on your device, nothing is uploaded, and Compare scores it against this keeper. - To make it the chamber's default, publish it here as a new commit and
update the pinned revision and sha256 in
apps/nottyduck-space/src/labs/houseKeeper.ts.
- Open https://nottyduck.com/labs/keeper#compare, choose Load a keeper
brain, and pick
License
Apache-2.0, the same as the NottyDuck repository. The MicroDuck robot model
and the supplied walking policy are Pollen Robotics' work, credited in the
repository's THIRD_PARTY_NOTICES.md.