pollen-robotics/microduck_rlPublic

RL training environments for Microduck (mjlab)

AI summary: Reinforcement learning training environments using PPO and MuJoCo to generate policies for the Microduck bipedal robot.

Stars
2.4K
+15 today
Forks
512
Watchers
14
Open issues
9
Open PRs
34
Contributors
~8
Commits
1.2K
Branches
37

PythonApache-2.0Created Dec 6, 2025Last push 3d ago+90 stars this week+788 this month

Quick answers

What is microduck_rl?
Reinforcement learning training environments using PPO and MuJoCo to generate policies for the Microduck bipedal robot.
What does microduck_rl do?
Microduck RL provides a structured physics simulation environment to train control policies for the physical Microduck bipedal robot. It solves the complexity of robotic locomotion by leveraging MuJoCo Warp and Proximal Policy Optimization (PPO) to simulate thousands of parallel environments simultaneously. The repository contains specialized configurations to teach the robot how to maintain balance and walk at a consistent 50 Hz control frequency. After training converges, the resulting neural networks are exported as ONNX models. These lightweight models are then deployed directly onto the real-world hardware's runtime system.
Who is microduck_rl for?
Robotics engineers and machine learning researchers focusing on reinforcement learning for physical control systems. It requires a modern GPU for training and an understanding of policy optimization.
How do I get started with microduck_rl?
git clone https://github.com/pollen-robotics/microduck_rl && cd microduck_rl && uv run train Mjlab-Velocity-Flat-MicroDuck --env.scene.num-envs 4096
How popular is microduck_rl on GitHub?
pollen-robotics/microduck_rl has 2,354 stars and 512 forks on GitHub, and gained 90 stars in the last 7 days.
What license does microduck_rl use?
pollen-robotics/microduck_rl is released under the Apache-2.0 license.

Star history

since Aug 30, 2026
01K2KAug 2026Sep 2026Sep 2026Oct 2026
2.4K stars as of Oct 3, 2026. Measured daily since Aug 30, 2026; GitHub no longer exposes earlier star timestamps.

Contribution activity

commits per day, last 52 weeks
OctNovDecJanFebMarAprMayJunJulAugSepMonWedFri2025-10-04: 0 commits2025-10-05: 0 commits2025-10-06: 0 commits2025-10-07: 0 commits2025-10-08: 0 commits2025-10-09: 0 commits2025-10-10: 0 commits2025-10-11: 0 commits2025-10-12: 0 commits2025-10-13: 0 commits2025-10-14: 0 commits2025-10-15: 0 commits2025-10-16: 0 commits2025-10-17: 0 commits2025-10-18: 0 commits2025-10-19: 0 commits2025-10-20: 0 commits2025-10-21: 0 commits2025-10-22: 0 commits2025-10-23: 0 commits2025-10-24: 0 commits2025-10-25: 0 commits2025-10-26: 0 commits2025-10-27: 0 commits2025-10-28: 0 commits2025-10-29: 0 commits2025-10-30: 0 commits2025-10-31: 0 commits2025-11-01: 0 commits2025-11-02: 0 commits2025-11-03: 0 commits2025-11-04: 0 commits2025-11-05: 0 commits2025-11-06: 0 commits2025-11-07: 0 commits2025-11-09: 0 commits2025-11-10: 0 commits2025-11-11: 0 commits2025-11-12: 0 commits2025-11-13: 0 commits2025-11-14: 0 commits2025-11-15: 0 commits2025-11-16: 0 commits2025-11-17: 0 commits2025-11-18: 0 commits2025-11-19: 0 commits2025-11-20: 0 commits2025-11-21: 0 commits2025-11-22: 0 commits2025-11-23: 0 commits2025-11-24: 0 commits2025-11-25: 0 commits2025-11-26: 0 commits2025-11-27: 0 commits2025-11-28: 0 commits2025-11-29: 0 commits2025-11-30: 0 commits2025-12-01: 0 commits2025-12-02: 0 commits2025-12-03: 0 commits2025-12-04: 0 commits2025-12-05: 0 commits2025-12-06: 3 commits2025-12-07: 0 commits2025-12-08: 0 commits2025-12-09: 0 commits2025-12-10: 0 commits2025-12-11: 0 commits2025-12-12: 0 commits2025-12-13: 0 commits2025-12-14: 0 commits2025-12-15: 0 commits2025-12-16: 0 commits2025-12-17: 0 commits2025-12-18: 0 commits2025-12-19: 0 commits2025-12-20: 0 commits2025-12-21: 0 commits2025-12-22: 0 commits2025-12-23: 0 commits2025-12-24: 0 commits2025-12-25: 0 commits2025-12-26: 0 commits2025-12-27: 0 commits2025-12-28: 0 commits2025-12-29: 0 commits2025-12-30: 0 commits2025-12-31: 0 commits2026-01-01: 0 commits2026-01-02: 0 commits2026-01-03: 0 commits2026-01-04: 0 commits2026-01-05: 0 commits2026-01-06: 0 commits2026-01-07: 0 commits2026-01-08: 0 commits2026-01-09: 0 commits2026-01-10: 0 commits2026-01-11: 0 commits2026-01-12: 0 commits2026-01-13: 0 commits2026-01-14: 0 commits2026-01-15: 2 commits2026-01-16: 3 commits2026-01-17: 13 commits2026-01-18: 12 commits2026-01-19: 16 commits2026-01-20: 13 commits2026-01-21: 25 commits2026-01-22: 11 commits2026-01-23: 0 commits2026-01-24: 0 commits2026-01-25: 0 commits2026-01-26: 14 commits2026-01-27: 12 commits2026-01-28: 40 commits2026-01-29: 23 commits2026-01-30: 0 commits2026-01-31: 0 commits2026-02-01: 0 commits2026-02-02: 18 commits2026-02-03: 1 commit2026-02-04: 13 commits2026-02-05: 0 commits2026-02-06: 7 commits2026-02-07: 13 commits2026-02-08: 4 commits2026-02-09: 28 commits2026-02-10: 29 commits2026-02-11: 4 commits2026-02-12: 19 commits2026-02-13: 13 commits2026-02-14: 28 commits2026-02-15: 22 commits2026-02-16: 5 commits2026-02-17: 0 commits2026-02-18: 0 commits2026-02-19: 1 commit2026-02-20: 0 commits2026-02-21: 0 commits2026-02-22: 0 commits2026-02-23: 3 commits2026-02-24: 2 commits2026-02-25: 7 commits2026-02-26: 15 commits2026-02-27: 1 commit2026-02-28: 1 commit2026-03-01: 0 commits2026-03-02: 2 commits2026-03-03: 7 commits2026-03-04: 9 commits2026-03-05: 8 commits2026-03-06: 5 commits2026-03-07: 4 commits2026-03-08: 6 commits2026-03-09: 0 commits2026-03-10: 0 commits2026-03-11: 20 commits2026-03-12: 31 commits2026-03-13: 7 commits2026-03-14: 0 commits2026-03-15: 14 commits2026-03-16: 19 commits2026-03-17: 25 commits2026-03-18: 12 commits2026-03-19: 3 commits2026-03-20: 0 commits2026-03-21: 0 commits2026-03-22: 0 commits2026-03-23: 20 commits2026-03-24: 17 commits2026-03-25: 19 commits2026-03-26: 18 commits2026-03-27: 6 commits2026-03-28: 0 commits2026-03-29: 0 commits2026-03-30: 16 commits2026-03-31: 1 commit2026-04-01: 2 commits2026-04-02: 6 commits2026-04-03: 7 commits2026-04-04: 4 commits2026-04-05: 3 commits2026-04-06: 0 commits2026-04-07: 9 commits2026-04-08: 4 commits2026-04-09: 0 commits2026-04-10: 0 commits2026-04-11: 2 commits2026-04-12: 7 commits2026-04-13: 7 commits2026-04-14: 0 commits2026-04-15: 0 commits2026-04-16: 0 commits2026-04-17: 0 commits2026-04-18: 0 commits2026-04-19: 0 commits2026-04-20: 0 commits2026-04-21: 0 commits2026-04-22: 5 commits2026-04-23: 0 commits2026-04-24: 0 commits2026-04-25: 0 commits2026-04-26: 0 commits2026-04-27: 0 commits2026-04-28: 0 commits2026-04-29: 0 commits2026-04-30: 0 commits2026-05-01: 0 commits2026-05-02: 0 commits2026-05-03: 0 commits2026-05-04: 0 commits2026-05-05: 0 commits2026-05-06: 0 commits2026-05-07: 0 commits2026-05-08: 0 commits2026-05-09: 0 commits2026-05-10: 0 commits2026-05-11: 9 commits2026-05-12: 27 commits2026-05-13: 15 commits2026-05-14: 16 commits2026-05-15: 13 commits2026-05-16: 0 commits2026-05-17: 0 commits2026-05-18: 21 commits2026-05-19: 12 commits2026-05-20: 6 commits2026-05-21: 2 commits2026-05-22: 0 commits2026-05-23: 0 commits2026-05-24: 0 commits2026-05-25: 0 commits2026-05-26: 0 commits2026-05-27: 5 commits2026-05-28: 0 commits2026-05-29: 0 commits2026-05-30: 0 commits2026-05-31: 0 commits2026-06-01: 0 commits2026-06-02: 0 commits2026-06-03: 0 commits2026-06-04: 0 commits2026-06-05: 0 commits2026-06-06: 0 commits2026-06-07: 0 commits2026-06-08: 0 commits2026-06-09: 0 commits2026-06-10: 0 commits2026-06-11: 0 commits2026-06-12: 0 commits2026-06-13: 0 commits2026-06-14: 0 commits2026-06-15: 0 commits2026-06-16: 0 commits2026-06-17: 0 commits2026-06-18: 0 commits2026-06-19: 0 commits2026-06-20: 0 commits2026-06-21: 0 commits2026-06-22: 0 commits2026-06-23: 0 commits2026-06-24: 2 commits2026-06-25: 2 commits2026-06-26: 0 commits2026-06-27: 0 commits2026-06-28: 13 commits2026-06-29: 10 commits2026-06-30: 11 commits2026-07-01: 9 commits2026-07-02: 5 commits2026-07-03: 0 commits2026-07-04: 0 commits2026-07-05: 0 commits2026-07-06: 8 commits2026-07-07: 3 commits2026-07-08: 6 commits2026-07-09: 5 commits2026-07-10: 0 commits2026-07-11: 0 commits2026-07-12: 0 commits2026-07-13: 0 commits2026-07-14: 0 commits2026-07-15: 7 commits2026-07-16: 4 commits2026-07-17: 9 commits2026-07-18: 0 commits2026-07-19: 0 commits2026-07-20: 5 commits2026-07-21: 8 commits2026-07-22: 6 commits2026-07-23: 16 commits2026-07-24: 39 commits2026-07-25: 0 commits2026-07-26: 0 commits2026-07-27: 21 commits2026-07-28: 16 commits2026-07-29: 3 commits2026-07-30: 0 commits2026-07-31: 0 commits2026-08-01: 0 commits2026-08-02: 0 commits2026-08-03: 0 commits2026-08-04: 22 commits2026-08-05: 5 commits2026-08-06: 2 commits2026-08-07: 0 commits2026-08-08: 0 commits2026-08-09: 0 commits2026-08-10: 3 commits2026-08-11: 5 commits2026-08-12: 4 commits2026-08-13: 3 commits2026-08-14: 0 commits2026-08-15: 0 commits2026-08-16: 0 commits2026-08-17: 0 commits2026-08-18: 1 commit2026-08-19: 1 commit2026-08-20: 4 commits2026-08-21: 2 commits2026-08-22: 0 commits2026-08-23: 0 commits2026-08-24: 0 commits2026-08-25: 12 commits2026-08-26: 12 commits2026-08-27: 3 commits2026-08-28: 0 commits2026-08-29: 0 commits2026-08-30: 8 commits2026-08-31: 4 commits2026-09-01: 3 commits2026-09-02: 9 commits2026-09-03: 0 commits2026-09-04: 0 commits2026-09-05: 0 commits2026-09-06: 2 commits2026-09-07: 1 commit2026-09-08: 1 commit2026-09-09: 2 commits2026-09-10: 6 commits2026-09-11: 0 commits2026-09-12: 0 commits2026-09-13: 4 commits2026-09-14: 2 commits2026-09-15: 0 commits2026-09-16: 0 commits2026-09-17: 0 commits2026-09-18: 0 commits2026-09-19: 0 commits2026-09-20: 0 commits2026-09-21: 0 commits2026-09-22: 0 commits2026-09-23: 0 commits2026-09-24: 0 commits2026-09-25: 0 commits2026-09-26: 0 commits2026-09-27: 0 commits2026-09-28: 0 commits2026-09-29: 0 commits2026-09-30: 0 commits2026-10-01: 0 commits2026-10-02: 0 commits2026-10-03: 0 commits
1,201 commits in the last yearLessMore

Signals and awards

derived from tracked data
  • Very active

    1,201 commits in 52 weeks

  • Permissive license

    Apache-2.0

  • Continuous integration

    Automated checks passing

  • Repeat trending

    7 trending appearances

What microduck_rl does

Microduck RL provides a structured physics simulation environment to train control policies for the physical Microduck bipedal robot. It solves the complexity of robotic locomotion by leveraging MuJoCo Warp and Proximal Policy Optimization (PPO) to simulate thousands of parallel environments simultaneously. The repository contains specialized configurations to teach the robot how to maintain balance and walk at a consistent 50 Hz control frequency. After training converges, the resulting neural networks are exported as ONNX models. These lightweight models are then deployed directly onto the real-world hardware's runtime system.

Robotics engineers and machine learning researchers focusing on reinforcement learning for physical control systems. It requires a modern GPU for training and an understanding of policy optimization.

  • MuJoCo integration: Uses the mjlab framework to provide highly accurate, GPU-accelerated physics simulation.
  • PPO training: Implements Proximal Policy Optimization algorithms to discover stable walking gaits automatically.
  • Parallel environments: Scales training across thousands of simulated instances to drastically reduce convergence time.
  • ONNX export: Converts trained PyTorch policies into optimized ONNX graphs for low-latency hardware inference.
  • Targeted control frequency: Trains models specifically for the 50 Hz control loop required by the physical robot.
  • Hardware alignment: Ensures simulated kinematics closely match the physical characteristics of the 800g bipedal platform.

Where teams use it

Locomotion policy generation

Train a neural network from scratch to allow a bipedal robot to walk without manual trajectory planning.

Hardware deployment

Export the trained simulated policy as an ONNX model and run it directly on the physical Microduck robot.

Algorithm experimentation

Test modifications to reward functions or network architectures in simulation before risking physical hardware.

Gait visualization

Watch the simulated agent learn and evaluate its walking performance using the built-in policy viewer.

Getting started: git clone https://github.com/pollen-robotics/microduck_rl && cd microduck_rl && uv run train Mjlab-Velocity-Flat-MicroDuck --env.scene.num-envs 4096

README

develop branch

Microduck RL

image

RL training environments for Microduck — a ~800 g, ~25 cm tall bipedal robot — built on mjlab (MuJoCo Warp) with PPO. Policies are trained here at 50 Hz, exported to ONNX, and deployed on the real robot by the runtime in pollen-robotics/microduck.

interaction.mov

The repo encodes the full sim2real recipe: BAM actuator physics, domain randomization, backlash simulation, and the reward-design lessons that made it work (see AGENTS.md for the distilled playbook).

Quickstart

Requires a CUDA GPU (training runs through MuJoCo Warp) and uv.

On ARM boxes (DGX Spark / GB10, Jetson): uv sync pulls ~2 GB of CUDA wheels on first run and uv's default 30 s HTTP timeout can abort mid-download. Export UV_HTTP_TIMEOUT=600 for the first sync.

git clone https://github.com/pollen-robotics/microduck_rl
cd microduck_rl

# train the walking policy (uses your GPU; ~1-2 h for a usable gait at 4096 envs)
uv run train Mjlab-Velocity-Flat-MicroDuck --env.scene.num-envs 4096

# watch a trained policy in the viewer
uv run play Mjlab-Velocity-Flat-MicroDuck --wandb-run-path <entity/project/run_id>

# export to ONNX for deployment
uv run scripts/export.py Mjlab-Velocity-Flat-MicroDuck --wandb-run-path <...>
uv run publish --onnx output.onnx --repo <user>/microduck-<name> --kind episodic --duration-s 4.0   # share it (see "Publishing a policy")

# drive the exported policy in CPU MuJoCo with the keyboard
uv run scripts/infer_policy.py --walking output.onnx

Resume from a checkpoint:

uv run train Mjlab-Velocity-Flat-MicroDuck --env.scene.num-envs 4096 \
    --agent.run-name resume --agent.load-checkpoint model_29999.pt --agent.resume True

No GPU? Add --hf-jobs to any train command to run it on Hugging Face Jobs instead of locally (see scripts/hf/README.md).

Tasks

uv run list-envs prints the live registry. Flat/Rough variants exist where noted.

Task id Terrain Description
Mjlab-Velocity-{Flat,Rough}-MicroDuck flat/rough The main task: walking with velocity commands + head-pose commands
Mjlab-VelStand-{Flat,Rough}-MicroDuck flat/rough Walking + fall recovery in one policy
Mjlab-StandUp-{Flat,Rough}-MicroDuck flat/rough Stand up from face-down/face-up/sitting, then hold the stand + body-pose control
Mjlab-SitStand-{Flat,Rough}-MicroDuck flat/rough Commanded sit ↔ stand in one policy, gently, head commandable
Mjlab-GroundPick-{Flat,Rough}-MicroDuck flat/rough Crouch and touch the ground with the mouth tip, return to stand
Mjlab-BallKick-Flat-MicroDuck flat Kick a 70 mm / 15 g ball forward (actor is ball-blind)
Mjlab-Roulade-Flat-MicroDuck flat Forward roll over the head, land back on the feet
Mjlab-Velocity-Flat-MicroDuck-Rollers flat Roller-skate velocity tracking (passive wheels under the feet)
Mjlab-Velocity-Swizzle-MicroDuck flat Classic symmetric swizzle skating
Mjlab-RollerCrouch-Flat-MicroDuck flat Crouch while gliding on rollers
Mjlab-RollerSlope-Flat-MicroDuck slope Glide down slopes on rollers
Mjlab-RollerStandUp-Flat-MicroDuck flat Stand up from the ground onto the wheels
Mjlab-Spin-Flat-MicroDuck flat Fast spin in place on rollers

At deployment the runtime hot-swaps these policies (walk / recover / trick) behind a shared 61-dimensional observation contract, so any of them can take over the robot at any moment. scripts/infer_policy.py rehearses exactly that:

uv run scripts/infer_policy.py --walking walk.onnx --standing stand.onnx \
    --sitstand sitstand.onnx --roulade roulade.onnx --new-cmd-obs

Keyboard-driven (velocity commands, G ground pick, Y sit/stand, R roulade, K/L kicks); --debug, --save-csv, --record support sim2real comparisons. The servos are simulated with the same BAM M6 XL330 model the policies are trained against (voltage control + load-dependent friction, via bam.mujoco.MujocoController); --vin / --vin-drop-gain / --kp-fw pin the training DR ranges to one value, --no-bam falls back to the XML PD actuators.

Backlash variants

Every main task has a Backlash twin that trains on a model with ±1° of gear play (2° total) in series with each of the 14 servo joints: insert -Backlash before MicroDuck in the task id, e.g. Mjlab-Velocity-Flat-Backlash-MicroDuck.

The backlash is modeled properly for sim2real: each servo gets an unactuated passive_<joint>_backlash hinge, and because the real encoder sits on the output side of the play, both the firmware PD emulation (BacklashEncoderBamActuator) and the joint_pos/joint_vel observations read through the backlash (qpos[servo] + qpos[backlash]). Observation and action dims are unchanged, so ONNX export and the runtime need no changes. See src/mjlab_microduck/tasks/backlash.py.

Actuator model

All tasks use the BAM M6 actuator model for the Dynamixel XL330 (voltage control law, back-EMF, Coulomb/Stribeck/load-dependent friction), with per-env domain randomization on battery voltage, voltage sag under load, command delay, and friction magnitude (FrictionDRBamActuator in src/mjlab_microduck/actuator/).

At this scale — tiny servos driving a ~800 g biped — actuator fidelity is most of the sim2real gap, which is why the actuator is modeled down to its voltage control law instead of an ideal PD.

Robot models

MJCF models live in src/mjlab_microduck/robot/microduck/ and are exported from Onshape with onshape-to-robot, one config_mjcf_*.json per model:

XML Used by
robot_walk.xml Velocity (stripped trunk/head contacts — falling is cheap)
robot_groundcontact.xml VelStand, StandUp, SitStand, GroundPick, BallKick, Roulade (curated collision set for the parts that touch the floor — body can physically lie on the ground; formerly robot_allcollisions.xml)
robot_groundcontact_rollers.xml Roller tasks (passive wheels)
robot_allcollisions.xml True full-collision model — every part has a collision geom. No task uses it yet
robot_*_backlash.xml Backlash task variants (generated by add_backlash.py)

scene*.xml files wrap the robots with a floor + keyframes (STAND/SIT/FOLD) for quick viewing and for infer_policy.py.

Project structure

src/mjlab_microduck/
├── robot/
│   ├── microduck/                    # MJCF exports, export configs, scenes, add_backlash.py
│   └── microduck_constants.py        # robot cfgs, HOME frame, BAM actuator cfg
├── actuator/friction_dr_bam.py       # BAM + friction DR + backlash encoder feedback
├── tasks/
│   ├── __init__.py                   # task registration (base + backlash variants)
│   ├── mdp.py                        # rewards, events, observations, custom classes
│   ├── backlash.py                   # make_backlash_variant() env-cfg wrapper
│   └── microduck_*_env_cfg.py        # one cfg module per task family
├── train_cli.py                      # `train` script (identical to mjlab's)
├── train_hook.py                     # intercepts `train ... --hf-jobs`
└── hf_jobs.py                        # Hugging Face Jobs submission

Conventions worth knowing:

  • The observation layout is shared across every policy (61-dim actor obs: 48 proprioception + commands [twist(3), head_pose(4), body_pose(6)]), which is what makes runtime policy hot-swapping possible. Envs that don't use a command slot zero-pad it rather than dropping it.
  • Unactuated joints are all named passive_* (roller wheels, backlash hinges); actuators, joint observations and pose rewards select servo joints with ^(?!passive_).*.
  • Domain-randomization toggles are ENABLE_* booleans at the top of each env cfg file.
  • Joint layout (14 servos): 0–4 left leg (hip_yaw, hip_roll, hip_pitch, knee, ankle), 5–8 neck/head (neck_pitch, head_pitch, head_yaw, head_roll), 9–13 right leg.
  • The exporter bakes the observation normalizer into the ONNX graph — always deploy ONNX produced by scripts/export.py, never a hand-converted checkpoint, or the policy sees unnormalized observations at runtime.

AGENTS.md documents the env-building workflow and the reward-design rules learned across the project (also aimed at AI coding agents working in this repo).

Publishing a policy

uv run publish puts a policy on the Hugging Face Hub in the shape the robot's daemon loads: one policy.onnx with the observation normalizer baked in, a manifest.json following schema 2 of the microduck policy manifest, and a README saying how to run it. Anyone with a microduck can then install it with one command, no daemon release needed.

# From a wandb run — exports through the one safe path, then uploads
uv run publish --task Mjlab-PoliteBow-Flat-MicroDuck \
    --wandb-run-path <entity/project/run_id> --checkpoint 3000 \
    --repo <user>/microduck-polite-bow --kind episodic --duration-s 4.0 \
    --description "Bows from a two-foot stand and comes back up."

# From an ONNX you already exported (validated, not re-exported)
uv run publish --onnx output.onnx --repo <user>/microduck-flamingo \
    --kind perpetual --unwind-s 1.5 --twist-help "[flag, side, 0]"

# A new gait for a slot
uv run publish --onnx output.onnx --repo <user>/microduck-my-walk --kind perpetual --slot walk

# See what would be uploaded without touching the Hub
uv run publish --onnx output.onnx --repo <user>/microduck-bow --kind episodic --duration-s 4.0 --dry-run

Then on a robot:

sudo robotctl policy add polite-bow <user>/microduck-polite-bow   # episodic: length comes from the manifest
sudo robotctl policy add flamingo <user>/microduck-flamingo --hold 5   # held pose: you pick how long
sudo robotctl policy load walk <user>/microduck-my-walk                # gait: into the walk slot
robotctl robot do polite-bow

What --kind means, and what each needs:

  • episodic — runs for --duration-s and returns itself to a standing pose (kicks, roulade, a bow). Add --chain if holding the button should repeat it.
  • perpetual — runs until told otherwise. Two shapes:
    • a gait (a new walk or stand): add --slot walk (or stand) and nothing else; the owner installs it with robotctl policy load walk <repo>.
    • a held pose (the flamingo): give --unwind-s, how long the daemon drives the idle twist (--idle, zeros by default) before handing back to the gait, so the robot is not let go of on one foot. The owner runs it as a one-shot with policy add ... --hold <seconds>.

Before anything is uploaded, publish checks the graph is [1,61] -> [1,14] (a 51-D legacy policy is refused with a message), runs it on plausible inputs and refuses NaNs or a constant output, fills the training block from git and wandb (task, commit, branch, dirty flag, run, checkpoint), and refuses to overwrite an existing .onnx in the repo without --force. Repos are created private; --no-private for public, --tag v1 to tag the revision.

Only constant-command policies are publishable this way. Phase-driven moves (the ground pick) and the posture-flag sit↔stand are driven by the daemon itself and live in the official set, pollen-robotics/microduck-policies.

Tests

uv run --with pytest pytest tests/

CPU-only config-invariant and reward-function regression tests — they lock in joint-index mappings, reward sign conventions, and NaN guards.

Related projects

  • microduck — the Microduck project home, including the onboard runtime that runs the exported policies
  • mjlab — the training framework (MuJoCo Warp + rsl_rl)
  • BAM — better actuator models, by Rhoban

License

This project is licensed under the Apache 2.0 License. See the LICENSE file for details. 3D model files are licensed under Creative Commons BY-SA-NC.

View on GitHub

Recent activity

commits and pull requests

Code frequency

additions and deletions
+14.3K-14.3KWeek of 2025-11-30: +990 linesWeek of 2025-11-30: -99 linesWeek of 2025-12-07: +0 linesWeek of 2025-12-07: -0 linesWeek of 2025-12-14: +0 linesWeek of 2025-12-14: -0 linesWeek of 2025-12-21: +0 linesWeek of 2025-12-21: -0 linesWeek of 2025-12-28: +0 linesWeek of 2025-12-28: -0 linesWeek of 2026-01-04: +0 linesWeek of 2026-01-04: -0 linesWeek of 2026-01-11: +5,050 linesWeek of 2026-01-11: -747 linesWeek of 2026-01-18: +1,364 linesWeek of 2026-01-18: -900 linesWeek of 2026-01-25: +1,065 linesWeek of 2026-01-25: -698 linesWeek of 2026-02-01: +9,365 linesWeek of 2026-02-01: -4,753 linesWeek of 2026-02-08: +6,774 linesWeek of 2026-02-08: -1,225 linesWeek of 2026-02-15: +181 linesWeek of 2026-02-15: -218 linesWeek of 2026-02-22: +1,001 linesWeek of 2026-02-22: -3,338 linesWeek of 2026-03-01: +4,551 linesWeek of 2026-03-01: -2,171 linesWeek of 2026-03-08: +2,574 linesWeek of 2026-03-08: -1,521 linesWeek of 2026-03-15: +1,612 linesWeek of 2026-03-15: -869 linesWeek of 2026-03-22: +1,556 linesWeek of 2026-03-22: -1,100 linesWeek of 2026-03-29: +6,975 linesWeek of 2026-03-29: -5,157 linesWeek of 2026-04-05: +1,469 linesWeek of 2026-04-05: -1,414 linesWeek of 2026-04-12: +478 linesWeek of 2026-04-12: -53 linesWeek of 2026-04-19: +1,209 linesWeek of 2026-04-19: -141 linesWeek of 2026-04-26: +0 linesWeek of 2026-04-26: -0 linesWeek of 2026-05-03: +0 linesWeek of 2026-05-03: -0 linesWeek of 2026-05-10: +8,101 linesWeek of 2026-05-10: -6,346 linesWeek of 2026-05-17: +2,063 linesWeek of 2026-05-17: -743 linesWeek of 2026-05-24: +399 linesWeek of 2026-05-24: -32 linesWeek of 2026-05-31: +0 linesWeek of 2026-05-31: -0 linesWeek of 2026-06-07: +0 linesWeek of 2026-06-07: -0 linesWeek of 2026-06-14: +0 linesWeek of 2026-06-14: -0 linesWeek of 2026-06-21: +1,099 linesWeek of 2026-06-21: -3,148 linesWeek of 2026-06-28: +3,361 linesWeek of 2026-06-28: -3,091 linesWeek of 2026-07-05: +2,687 linesWeek of 2026-07-05: -1,306 linesWeek of 2026-07-12: +2,392 linesWeek of 2026-07-12: -436 linesWeek of 2026-07-19: +6,768 linesWeek of 2026-07-19: -948 linesWeek of 2026-07-26: +3,934 linesWeek of 2026-07-26: -1,663 linesWeek of 2026-08-02: +6,736 linesWeek of 2026-08-02: -163 linesWeek of 2026-08-09: +4,989 linesWeek of 2026-08-09: -474 linesWeek of 2026-08-16: +1,076 linesWeek of 2026-08-16: -66 linesWeek of 2026-08-23: +8,111 linesWeek of 2026-08-23: -14,297 linesWeek of 2026-08-30: +6,720 linesWeek of 2026-08-30: -3,397 linesWeek of 2026-09-06: +2,112 linesWeek of 2026-09-06: -181 linesWeek of 2026-09-13: +1,057 linesWeek of 2026-09-13: -248 linesWeek of 2026-09-20: +0 linesWeek of 2026-09-20: -0 linesWeek of 2026-09-27: +0 linesWeek of 2026-09-27: -0 linesNov 30, 2025Sep 27, 2026
+107.8K lines added, -60.9K removed over the last year.

Commits per week

last 52 weeks
1250Week of 2025-10-04: 0 commitsWeek of 2025-10-11: 0 commitsWeek of 2025-10-18: 0 commitsWeek of 2025-10-25: 0 commitsWeek of 2025-11-01: 0 commitsWeek of 2025-11-09: 0 commitsWeek of 2025-11-16: 0 commitsWeek of 2025-11-23: 0 commitsWeek of 2025-11-30: 3 commitsWeek of 2025-12-07: 0 commitsWeek of 2025-12-14: 0 commitsWeek of 2025-12-21: 0 commitsWeek of 2025-12-28: 0 commitsWeek of 2026-01-04: 0 commitsWeek of 2026-01-11: 18 commitsWeek of 2026-01-18: 77 commitsWeek of 2026-01-25: 89 commitsWeek of 2026-02-01: 52 commitsWeek of 2026-02-08: 125 commitsWeek of 2026-02-15: 28 commitsWeek of 2026-02-22: 29 commitsWeek of 2026-03-01: 35 commitsWeek of 2026-03-08: 64 commitsWeek of 2026-03-15: 73 commitsWeek of 2026-03-22: 80 commitsWeek of 2026-03-29: 36 commitsWeek of 2026-04-05: 18 commitsWeek of 2026-04-12: 14 commitsWeek of 2026-04-19: 5 commitsWeek of 2026-04-26: 0 commitsWeek of 2026-05-03: 0 commitsWeek of 2026-05-10: 80 commitsWeek of 2026-05-17: 41 commitsWeek of 2026-05-24: 5 commitsWeek of 2026-05-31: 0 commitsWeek of 2026-06-07: 0 commitsWeek of 2026-06-14: 0 commitsWeek of 2026-06-21: 4 commitsWeek of 2026-06-28: 48 commitsWeek of 2026-07-05: 22 commitsWeek of 2026-07-12: 20 commitsWeek of 2026-07-19: 74 commitsWeek of 2026-07-26: 40 commitsWeek of 2026-08-02: 29 commitsWeek of 2026-08-09: 15 commitsWeek of 2026-08-16: 8 commitsWeek of 2026-08-23: 27 commitsWeek of 2026-08-30: 24 commitsWeek of 2026-09-06: 12 commitsWeek of 2026-09-13: 6 commitsWeek of 2026-09-20: 0 commitsWeek of 2026-09-27: 0 commitsOct 4, 2025Sep 27, 2026
1.2K commits in the last 52 weeks.

When work happens

weekday and hour
SunMonTueWedThuFriSat036912151821Sun 0:00 — 0 commitsSun 1:00 — 0 commitsSun 2:00 — 0 commitsSun 3:00 — 0 commitsSun 4:00 — 0 commitsSun 5:00 — 0 commitsSun 6:00 — 0 commitsSun 7:00 — 0 commitsSun 8:00 — 0 commitsSun 9:00 — 0 commitsSun 10:00 — 0 commitsSun 11:00 — 6 commitsSun 12:00 — 16 commitsSun 13:00 — 9 commitsSun 14:00 — 8 commitsSun 15:00 — 9 commitsSun 16:00 — 11 commitsSun 17:00 — 11 commitsSun 18:00 — 10 commitsSun 19:00 — 4 commitsSun 20:00 — 6 commitsSun 21:00 — 2 commitsSun 22:00 — 3 commitsSun 23:00 — 0 commitsMon 0:00 — 0 commitsMon 1:00 — 0 commitsMon 2:00 — 0 commitsMon 3:00 — 0 commitsMon 4:00 — 0 commitsMon 5:00 — 0 commitsMon 6:00 — 0 commitsMon 7:00 — 0 commitsMon 8:00 — 0 commitsMon 9:00 — 0 commitsMon 10:00 — 14 commitsMon 11:00 — 20 commitsMon 12:00 — 20 commitsMon 13:00 — 22 commitsMon 14:00 — 31 commitsMon 15:00 — 39 commitsMon 16:00 — 29 commitsMon 17:00 — 30 commitsMon 18:00 — 13 commitsMon 19:00 — 11 commitsMon 20:00 — 0 commitsMon 21:00 — 2 commitsMon 22:00 — 1 commitsMon 23:00 — 0 commitsTue 0:00 — 0 commitsTue 1:00 — 0 commitsTue 2:00 — 0 commitsTue 3:00 — 0 commitsTue 4:00 — 0 commitsTue 5:00 — 0 commitsTue 6:00 — 0 commitsTue 7:00 — 0 commitsTue 8:00 — 0 commitsTue 9:00 — 6 commitsTue 10:00 — 27 commitsTue 11:00 — 20 commitsTue 12:00 — 31 commitsTue 13:00 — 24 commitsTue 14:00 — 34 commitsTue 15:00 — 25 commitsTue 16:00 — 36 commitsTue 17:00 — 23 commitsTue 18:00 — 8 commitsTue 19:00 — 0 commitsTue 20:00 — 0 commitsTue 21:00 — 1 commitsTue 22:00 — 2 commitsTue 23:00 — 0 commitsWed 0:00 — 0 commitsWed 1:00 — 0 commitsWed 2:00 — 0 commitsWed 3:00 — 0 commitsWed 4:00 — 0 commitsWed 5:00 — 0 commitsWed 6:00 — 0 commitsWed 7:00 — 0 commitsWed 8:00 — 0 commitsWed 9:00 — 7 commitsWed 10:00 — 11 commitsWed 11:00 — 27 commitsWed 12:00 — 25 commitsWed 13:00 — 24 commitsWed 14:00 — 31 commitsWed 15:00 — 22 commitsWed 16:00 — 35 commitsWed 17:00 — 41 commitsWed 18:00 — 17 commitsWed 19:00 — 0 commitsWed 20:00 — 4 commitsWed 21:00 — 2 commitsWed 22:00 — 6 commitsWed 23:00 — 0 commitsThu 0:00 — 1 commitsThu 1:00 — 0 commitsThu 2:00 — 0 commitsThu 3:00 — 0 commitsThu 4:00 — 0 commitsThu 5:00 — 1 commitsThu 6:00 — 0 commitsThu 7:00 — 0 commitsThu 8:00 — 1 commitsThu 9:00 — 3 commitsThu 10:00 — 15 commitsThu 11:00 — 31 commitsThu 12:00 — 27 commitsThu 13:00 — 16 commitsThu 14:00 — 25 commitsThu 15:00 — 21 commitsThu 16:00 — 23 commitsThu 17:00 — 14 commitsThu 18:00 — 11 commitsThu 19:00 — 5 commitsThu 20:00 — 1 commitsThu 21:00 — 9 commitsThu 22:00 — 1 commitsThu 23:00 — 0 commitsFri 0:00 — 0 commitsFri 1:00 — 0 commitsFri 2:00 — 0 commitsFri 3:00 — 0 commitsFri 4:00 — 0 commitsFri 5:00 — 0 commitsFri 6:00 — 0 commitsFri 7:00 — 0 commitsFri 8:00 — 0 commitsFri 9:00 — 1 commitsFri 10:00 — 10 commitsFri 11:00 — 16 commitsFri 12:00 — 17 commitsFri 13:00 — 6 commitsFri 14:00 — 11 commitsFri 15:00 — 13 commitsFri 16:00 — 14 commitsFri 17:00 — 13 commitsFri 18:00 — 2 commitsFri 19:00 — 3 commitsFri 20:00 — 3 commitsFri 21:00 — 1 commitsFri 22:00 — 2 commitsFri 23:00 — 0 commitsSat 0:00 — 0 commitsSat 1:00 — 0 commitsSat 2:00 — 0 commitsSat 3:00 — 0 commitsSat 4:00 — 0 commitsSat 5:00 — 0 commitsSat 6:00 — 0 commitsSat 7:00 — 0 commitsSat 8:00 — 0 commitsSat 9:00 — 0 commitsSat 10:00 — 1 commitsSat 11:00 — 11 commitsSat 12:00 — 7 commitsSat 13:00 — 4 commitsSat 14:00 — 6 commitsSat 15:00 — 6 commitsSat 16:00 — 0 commitsSat 17:00 — 3 commitsSat 18:00 — 5 commitsSat 19:00 — 7 commitsSat 20:00 — 7 commitsSat 21:00 — 7 commitsSat 22:00 — 4 commitsSat 23:00 — 0 commits
Commit volume by weekday and hour (UTC). Larger dots mean more commits.
DateListRankStars gained
Sep 29, 2026monthly#12+2,276
Sep 28, 2026monthly#12+2,276
Sep 8, 2026weekly#7+1,122
Sep 7, 2026weekly#7+1,122
Sep 1, 2026daily#14+384
Aug 31, 2026daily#14+384
Aug 30, 2026daily#10+147