Customizing Microduck: How to Hack, Train, and Build on Pollen Robotics' Open-Source Biped
Open Source Projects 8 min read

Customizing Microduck: How to Hack, Train, and Build on Pollen Robotics' Open-Source Biped

From 15 Dynamixel servos to a headless Rust daemon architecture and on-device RL policies, here is how the open-source community can customize, train, and expand Microduck.

M
med Developer and robotics enthusiast tracking the open source humanoid robot ecosystem.
On this page

Small bipedal robots have long lived in an uncomfortable gap between fragile educational hobby toys and prohibitively expensive research rigs. For the past two years, the open-source community around Antoine Pirrone’s Open Duck Mini (the 3D-printable biped inspired by Disney’s BDX droid) pushed what was possible on a tight budget.

Now, through a collaboration with Pollen Robotics, that community project has evolved into Microduck: a ~25 cm tall, ~800 g bipedal robot with an industrial-grade, fully open-source software stack (Apache 2.0).

With fifteen Dynamixel XL330 smart bus servos, an onboard Time-of-Flight (ToF) sensor, real-time reinforcement learning locomotion, and a clean Rust-based daemon architecture, Microduck represents a modern reference platform for agile bipedal pets.

Here is an architectural deep dive into how Microduck works under the hood and how the open-source community can customize, train, and extend it.


1. The Hardware Architecture: Lean and Accessible

Microduck balances cost, weight, and low-latency motor communication:

  • Compute: A Radxa Zero 3 SBC (Rockchip RK3566, quad-core Cortex-A55) running Armbian, with a 0.8 TOPS INT8 NPU sitting mostly idle for on-device perception work.
  • Actuators: 15× Dynamixel XL330 smart bus servos on a single shared UART running Dynamixel Protocol 2.0 at 1 Mbps.
  • Sensory Suite:
    • A head-mounted Time-of-Flight sensor (VL53L5CX/L8CX family) publishing an 8×8 depth matrix for obstacle awareness and, combined with leg odometry, 2D localization.
    • A dedicated motor-bus IMU board (LSM6DSV16X) with on-chip SFLP sensor fusion, so robotd reads an already-fused orientation quaternion straight off the same bus as the servos instead of integrating raw gyro/accel itself.
    • A front camera (IMX219) streaming over WebRTC for teleoperation and, increasingly, on-device vision.
  • Procedural Sound Engine: No bulky audio libraries or canned MP3 files. Microduck uses microduck_sounds, a pure NumPy procedural synthesizer where sound profiles are dynamically generated from deterministic integer seeds. Changing a single seed completely alters the robot’s voice register, pitch, quackiness, and harmonic tilt.

2. The Software Stack: Rust Daemons Over Monolithic Middleware

Rather than saddling an ultra-lightweight SBC with heavy ROS nodes, Pollen Robotics designed Microduck around a cohesive, single-workspace Rust daemon architecture.

Each daemon owns a single responsibility and exposes a clean JSON-RPC interface over Unix domain sockets:

+-------------------------------------------------------------------+
|                           Microduck Host                          |
|                                                                   |
|  +--------+  +-------+  +---------+  +---------+  +------------+  |
|  |  padd  |  |  btd  |  | configd |  | mediad  |  |    tofd    |  |
|  |(Gamepad)| |(BLE)  |  |(Wifi/ID)|  |(WebRTC) |  |(ToF Depth) |  |
|  +---+----+  +---+---+  +----+----+  +----+----+  +-----+------+  |
|      |           |           |            |              |        |
|      +-----------+-----------+------------+--------------+        |
|                               |                                   |
|                               v                                   |
|                [ JSON-RPC 2.0 over Unix Sockets ]                 |
|                               |                                   |
|                               v                                   |
|                        +--------------+                           |
|                        |    robotd    | (50 Hz Control Loop)      |
|                        +------+-------+                           |
|                               |                                   |
|                               v                                   |
|                    [ Dynamixel Motor Bus ]                        |
|                               |                                   |
|                  (15x XL330 Actuators + IMU)                      |
+-------------------------------------------------------------------+

Seven daemons, each with exactly one unix socket and one job:

  • robotd: The only process that touches the motors. Runs the 50 Hz control loop, reads IMU and joint telemetry, evaluates the ONNX policy, enforces fall-detection and thermal/joint safety limits, and is authoritative over anything that can hurt the robot. Clients only ever send intents; robotd decides what’s actually executable.
  • tofd: Owns the head’s ToF sensor, publishing its 8×8 depth matrix. It reads nothing and answers no one — mediad and robotd just subscribe to its stream.
  • mediad: The camera/audio pipeline and the WebRTC/remote gateway. Heaviest daemon on the board, deliberately split from robotd so a media crash can’t take out motor control.
  • configd: Owns wifi, robot identity/naming, and gamepad Bluetooth pairing (bonding needs root and BlueZ, so it lives here rather than in the unprivileged padd).
  • padd: A thin, unprivileged gamepad-input transport — reads the pad and forwards the same intents an app would send.
  • btd: The BLE GATT transport a phone app uses to reach robotd/configd/updaterd when there’s no wifi.
  • updaterd: A/B release management — verifies signatures, swaps releases atomically, health-gates against robotd, and rolls back automatically on a failed boot.

configd, updaterd, and btd deliberately have no dependency on robotd: they’re the recovery path for a robot whose control loop won’t start.

How to Customize the Software

Because all inter-process communication occurs via standard JSON-RPC over local Unix domain sockets, developers can write controllers, behavior state machines, or high-level agents in any language (Python, C++, Go, Rust) without touching the low-level motor drivers:

import socket
import json

# Connect directly to robotd's control socket
sock = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
sock.connect("/run/robotd.sock")

# Send a standard JSON-RPC command (one object per line, NDJSON)
req = {
    "jsonrpc": "2.0",
    "method": "robot.move",
    "params": {"vx": 0.2, "vy": 0.0, "vyaw": 0.4},
    "id": 1
}
sock.sendall(json.dumps(req).encode() + b"\n")
response = json.loads(sock.recv(4096).decode())

3. Sim-to-Real: Training Custom RL Behaviors in MuJoCo

Microduck’s agility doesn’t come from classical inverse kinematics or hand-tuned spline trajectories; it runs deep reinforcement learning policies trained in simulation.

The training pipeline lives in microduck_rl, built on top of mjlab (MuJoCo Warp) using Proximal Policy Optimization (PPO):

  1. Simulation Environment: The robot’s MJCF models are exported straight from Onshape CAD via onshape-to-robot, so the sim geometry and mass properties track the real hardware rather than a hand-tuned approximation.
  2. Actuator Fidelity: At this scale, actuator dynamics dominate the sim-to-real gap more than rigid-body dynamics do. Rather than an ideal PD controller, microduck_rl models each XL330 with Rhoban’s BAM actuator model — voltage control law, back-EMF, and Coulomb/Stribeck/load-dependent friction — with domain randomization on battery voltage, voltage sag, command delay, and friction. A backlash variant of every task additionally simulates ±1° of gear play per joint.
  3. Sim-to-Real Policy Export: Once a policy converges (thousands of parallel environments via MuJoCo Warp), scripts/export.py bakes the observation normalizer into the graph and exports to ONNX.
  4. On-Device Inference: robotd loads the ONNX file directly into its 50 Hz execution loop. Because every task shares the same 61-dimensional observation contract, robotd can hot-swap between walk/recover/trick policies at runtime.

Training Your Own Custom Behaviors

microduck_rl already ships over a dozen registered tasks, and community members can fork any of them into new behaviors:

  • Rolling Gait: A -Rollers variant of every task swaps in passive wheels under the feet, with dedicated RollerCrouch, RollerSlope, and RollerStandUp tasks for gliding and getting back up on wheels.
  • Self-Righting: StandUp policies recover from face-down, face-up, or seated; VelStand folds walking and fall recovery into a single policy.
  • Manipulation / Picking: GroundPick crouches and touches the ground with the beak tip; BallKick learns to kick a 70 mm ball forward.
  • Acrobatics: Roulade trains a full forward roll over the head, landing back on the feet — a good example of how far a from-scratch reward function can push this platform.

To train a custom gait (requires a CUDA GPU and uv):

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

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

# Export the trained checkpoint to ONNX
uv run scripts/export.py Mjlab-Velocity-Flat-MicroDuck --wandb-run-path <entity/project/run_id>

Once exported, push the ONNX model to the robot and point robotd to your new policy configuration. No GPU on hand? --hf-jobs on any train command offloads the run to Hugging Face Jobs.


4. Community Roadmap: Where to Build Next

Microduck is designed as an open canvas, and more of the “roadmap” is already flying than you’d expect — the opportunity is extending it, not starting from zero:

  1. SLAM & Local Navigation: microduck_maploc_rs isn’t a stub — it’s a working submap-based pose-graph SLAM stack with loop closure, boot-time Monte Carlo relocalization, and A* planning, driven purely by the head ToF sensor and leg odometry deltas. It’s already wired into the robot’s runtime behind a --maploc flag. The opening for contributors is porting it fully into the new robotd daemon architecture and building on top of it: frontier exploration, multi-floor maps, or smarter path smoothing.
  2. Edge Vision & Object Tracking: The RK3566’s onboard NPU (0.8 TOPS INT8, via rknpu2) is largely untapped. A “recognize our own duck” detector — a small YOLOv8n/11n-class model reading raw NV12 frames from mediad — is already in progress for precise bearing tracking and follow-the-leader behavior, fusing camera bearing with ToF distance and BLE presence. Person-following, visual docking, and better dataset tooling (auto-labeling duck’s-eye-view footage) are wide open.
  3. Multi-Robot Behaviors: Ducks already coordinate over BLE advertising, not the JSON-RPC control plane — robotctl chorale gets two or more ducks singing a synced four-part piece with no clock sync (~20 ms drift), and each robot advertises a stable id, RSSI-based proximity, and a shared beat other behaviors can read. That groundwork is the real opportunity: formation walking, beat-synced group motion, or turning chorale from a manual command into something ducks do spontaneously when they sense company.

Getting Started

All hardware designs, CAD files, firmware, and training code are completely open:

Microduck proves that bipedal robotics doesn’t require five-figure hardware budgets or closed commercial ecosystems. With open CAD, affordable smart servos, and accessible sim-to-real reinforcement learning, the foundation for accessible legged robotics is already here.

Share

The week in humanoid robotics, edited for signal.

One concise briefing covering the most relevant papers, open-source releases, tutorials, and industry moves. No hype cycle recap, no inbox spam.

Research highlights Project releases Build tutorials

One email a week. Unsubscribe anytime.

Related Articles

Open Source Projects Project watch
June 4, 2026 7 min read

NVIDIA FlashDreams Is the Open-Source Inference Engine Robotics World Models Needed

FlashDreams is NVIDIA's Apache 2.0 inference framework for real-time autoregressive world models. Built for robotics synthetic training data and sim-to-real pipelines, it delivers 68–103 FPS closed-loop generation with OmniDreams on GB300, and ships first-party integrations for OmniDreams, Cosmos-Predict2.5, and Self-Forcing.