Team Ai
Datasetpublic

pollen-robotics/microduck-emotions

Microduck Emotions A collection of emotions for the Microduck robot. Each one is a motion and a sound designed together, beat by beat, with the beak opening on the sound, rendered in the physics simulation and validated on the real robot. Every emotion is three files: the motion (emotions/<name>.json, keyframes at 30 fps: head and body offsets played on top of whichever trained policy is active, plus the policy hand-overs, such as the sit that devastated and play dead start)… See the full description on the dataset page: https://huggingface.co/datasets/pollen-robotics/microduck-emotions.

sourceHugging Faceapache-2.0updated 29d agoView on Hugging Face
6likes1.1kdownloads
Dataset Card

Microduck Emotions

A collection of emotions for the Microduck robot. Each one is a motion and a sound designed together, beat by beat, with the beak opening on the sound, rendered in the physics simulation and validated on the real robot. Every emotion is three files: the motion (emotions/<name>.json, keyframes at 30 fps: head and body offsets played on top of whichever trained policy is active, plus the policy hand-overs, such as the sit that devastated and play dead start), the sound the robot plays (emotions/<name>.wav, 48 kHz mono), and the render with its sound (videos/<name>.mp4). metadata.jsonl indexes them all.

See and hear them

<table> <tr><td align="center"><video src="https://huggingface.co/datasets/pollen-robotics/microduck-emotions/resolve/main/videos/sad.mp4" controls preload="metadata" width="100%"></video></td><td align="center"><video src="https://huggingface.co/datasets/pollen-robotics/microduck-emotions/resolve/main/videos/devastated.mp4" controls preload="metadata" width="100%"></video></td><td align="center"><video src="https://huggingface.co/datasets/pollen-robotics/microduck-emotions/resolve/main/videos/curious.mp4" controls preload="metadata" width="100%"></video></td></tr> <tr><td align="center"><b>sad</b> · 7.5 s</td><td align="center"><b>devastated</b> · 8.0 s</td><td align="center"><b>curious</b> · 3.0 s</td></tr> <tr><td align="center"><video src="https://huggingface.co/datasets/pollen-robotics/microduck-emotions/resolve/main/videos/mmh.mp4" controls preload="metadata" width="100%"></video></td><td align="center"><video src="https://huggingface.co/datasets/pollen-robotics/microduck-emotions/resolve/main/videos/yes.mp4" controls preload="metadata" width="100%"></video></td><td align="center"><video src="https://huggingface.co/datasets/pollen-robotics/microduck-emotions/resolve/main/videos/yesfast.mp4" controls preload="metadata" width="100%"></video></td></tr> <tr><td align="center"><b>mmh</b> · 2.0 s</td><td align="center"><b>yes</b> · 1.5 s</td><td align="center"><b>yes fast</b> · 1.5 s</td></tr> <tr><td align="center"><video src="https://huggingface.co/datasets/pollen-robotics/microduck-emotions/resolve/main/videos/no.mp4" controls preload="metadata" width="100%"></video></td><td align="center"><video src="https://huggingface.co/datasets/pollen-robotics/microduck-emotions/resolve/main/videos/angry.mp4" controls preload="metadata" width="100%"></video></td><td align="center"><video src="https://huggingface.co/datasets/pollen-robotics/microduck-emotions/resolve/main/videos/excited.mp4" controls preload="metadata" width="100%"></video></td></tr> <tr><td align="center"><b>no</b> · 1.8 s</td><td align="center"><b>angry</b> · 2.6 s</td><td align="center"><b>excited</b> · 3.4 s</td></tr> <tr><td align="center"><video src="https://huggingface.co/datasets/pollen-robotics/microduck-emotions/resolve/main/videos/laugh.mp4" controls preload="metadata" width="100%"></video></td><td align="center"><video src="https://huggingface.co/datasets/pollen-robotics/microduck-emotions/resolve/main/videos/mock.mp4" controls preload="metadata" width="100%"></video></td><td align="center"><video src="https://huggingface.co/datasets/pollen-robotics/microduck-emotions/resolve/main/videos/defiant.mp4" controls preload="metadata" width="100%"></video></td></tr> <tr><td align="center"><b>laugh</b> · 3.0 s</td><td align="center"><b>mock</b> · 2.6 s</td><td align="center"><b>defiant</b> · 2.2 s</td></tr> <tr><td align="center"><video src="https://huggingface.co/datasets/pollen-robotics/microduck-emotions/resolve/main/videos/impatient.mp4" controls preload="metadata" width="100%"></video></td><td align="center"><video src="https://huggingface.co/datasets/pollen-robotics/microduck-emotions/resolve/main/videos/playdead.mp4" controls preload="metadata" width="100%"></video></td></tr> <tr><td align="center"><b>impatient</b> · 2.6 s</td><td align="center"><b>play dead</b> · 7.5 s</td></tr> </table>

Bindings and what each one does

Emotion mode = a tap on D-pad Up; short press under 0.6 s, long press held.

emotionpadlengthwhat it does
sadA (short)7.5 sStanding: the head droops over 2.5 s while a low coo glides down with it (200 to 140 Hz), two slow silent 'no' shakes at the bottom, hold, back up. Half depth on purpose: a deeper droop makes the real duck step forward.
devastatedA (long)8.0 sThe shock: the duck sits down at once with an alarmed call, the head droops and shakes 'no' three times while it sobs (one sob per head extreme, the third dying into the ending), then comes back level. It stays seated (D-pad down stands it up).
curiousY (long)3.0 s'What? what?': the head comes forward, tilts right on a rising chirp and left on a second, higher chirp, holds, comes back.
mmhY (short)2.0 s'What do you mean?': a head roll tilt of 0.22 rad held for a second with a muffled rising 'mmh?', then back.
yesLB (short)1.5 sOne clear nod (head pitch +0.7 rad for 0.25 s, back over 0.35 s) with one quack falling three semitones.
yes fastLB (long)1.5 sThe same nod with a curt 'wak'.
noRB (short)1.8 sOne head shake (yaw +0.55 / -0.55 at 0.35 / 0.85 s) with a two-note 'no-ah', the second note a fourth lower. Three voicings: the robot picks one at random.
angryX (short)2.6 sBeak-up glare, then four yaw snaps with hard barks on each, a short head jab and a small fast body pulse; the beak is forced wide on the first bark so a held object drops. Two voicings (barks / growl into barks).
excitedB (short)3.4 sSix accelerating head swings (yaw +-0.6) with a body bob on each, the beak climbing, a flourish at the end; a run of quacks, each higher and shorter than the last.
laughL3 (short)3.0 sBeak aimed up, the head wagging (yaw +-0.45) with a body dip on every 'ha'; one long 'haaa' then seven short ha's dying out.
mockX (long)2.6 s'Gnagnagnagna': beak up, the head rolling +-0.35 on every other syllable with body dips, a staccato mocking run.
defiantRB (long)2.2 s'Says who?': beak up and to the left with a curt quack, then to the right with a second.
impatientB (long)2.6 s'Come on!': four quick yaw shakes with a body bob each, then the beak flicks up on a huff; four grumbles and the huff.
play deadL3 (long)7.5 sAlarm call while the head whips to the side, the duck sits; at 1.8 s the head servos go limp and every leg joint goes to zero over 1.5 s so the seated duck rolls flat onto its back; at 4.0 s the legs come up; a falling death quack with a dying wobble at 5 s. Holds the dead pose until Start. Needs a mat.

Download and use

python
from huggingface_hub import snapshot_download
root = snapshot_download("pollen-robotics/microduck-emotions", repo_type="dataset")
# root/emotions/yes.json, root/emotions/yes.wav, root/videos/yes.mp4, root/metadata.jsonl
python
import json
rows = [json.loads(l) for l in open(f"{root}/metadata.jsonl")]
for r in rows: print(r["name"], r["pad"], r["duration_s"], "s:", r["description"])

On the robot. The emotions are compiled into the pad daemon of the runtime branch pad-expressions (padd/src/expressions.rs: each emotion has a unit test against its keyframe file here). With that build installed: a tap on D-pad Up switches the pad to emotion mode, where each button plays one emotion (short press / long press, see the pad column); and the daemon's cue port (TCP 7777) plays any of them from a script:

python
import json, socket
s = socket.create_connection(("192.168.1.29", 7777)); s.sendall(json.dumps({"express": "yes"}).encode() + b"\n")
print(s.recv(4096))  # {"ok": true, "duration": 1.5}

The theater player that drives Reachy Mini and Microduck together from one scene file lives in agentic_robot_theater (robot/skit.py, robot/duck_cue.py).

In simulation. tools/lib.py renders an emotion from its keyframes in MuJoCo with the real policies (it imports the microduck simulation stack, duckfilm.py), tools/quack.py is a Python port of the robot's quack synthesizer, tools/combine.py muxes a wav onto a render at a given time. They are here as a reference for making new emotions; see METHOD.md.

The motion format

emotions/<name>.json = {"fps": 30, "keyframes": [...], "measured": {...}}, plus joints_order and pose_joints for play dead. One keyframe per frame:

fieldmeaning
tseconds from the trigger
neck, head_pitch, head_yaw, head_rollhead deltas in radians on top of the policy's pose (pitch negative = beak up)
body_pitch, body_z, twistthe body pose command (radians, metres)
skillthe trained skill the duck is in at that frame (sit for devastated from 0.3 s and for play dead from 0 s; null = the standing / walking policy). The offsets above are applied on top of it while it holds the pose
soften, relaxservo compliance flags
mouthbeak opening 0..1, following the sound
pose_joints (top level, play dead only)scripted joint stages sent at at seconds: targets in joints_order (null = leave that joint), off = servos switched limp, gain, ramp_s. Play dead: at 1.8 s the head servos go limp and every leg goes to zero over 1.5 s (the seated duck rolls onto its back), at 4.0 s the legs come up

measured records what the simulation saw (drift, trunk pitch, falls) for the render in videos/.

Real-robot lessons baked in

  • —Anything that moves the head's mass forward makes the walking policy step forward; the simulation does not show it. Sad was halved in depth and curious lost its head-forward for that reason.
  • —The beak is a servo: it is gated on "driving", so a sound after the torque goes off (play dead's death quack) plays with the beak shut.
  • —Sounds were made to be about 20 % quieter than the first drafts; the robot's speaker is loud.

Credits

Designed by Rémi Fabre with Claude Code agents, September 2026, in the microduck_emotions workshop repo (the full history of candidates, rejected takes and reasons). Reachy Mini's side of the films: agentic_robot_theater.