Instructions to use AdsumSOK/microduck-bow with libraries, inference providers, notebooks, and local apps. Follow these links to get started.
- Libraries
- Microduck
How to use AdsumSOK/microduck-bow 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 AdsumSOK/microduck-bow
- Notebooks
- Google Colab
- Kaggle
bow v8: no floor contact, symmetric legs; English model card and manifest; new preview
Browse files- README.md +43 -16
- manifest.json +15 -14
- media/preview.mp4 +2 -2
- policy.onnx +2 -2
README.md
CHANGED
|
@@ -1,44 +1,71 @@
|
|
| 1 |
---
|
| 2 |
license: apache-2.0
|
| 3 |
-
|
|
|
|
| 4 |
---
|
| 5 |
|
| 6 |
# microduck-bow
|
| 7 |
|
| 8 |
<video src="https://huggingface.co/AdsumSOK/microduck-bow/resolve/main/media/preview.mp4" controls autoplay muted loop width="640"></video>
|
| 9 |
|
| 10 |
-
*
|
| 11 |
|
| 12 |
-
|
| 13 |
-
|
|
|
|
| 14 |
|
| 15 |
-
|
| 16 |
-
|
|
|
|
| 17 |
|
| 18 |
-
##
|
| 19 |
|
| 20 |
-
|
| 21 |
-
|
| 22 |
|
| 23 |
```
|
| 24 |
sudo robotctl policy load ground_pick <user>/microduck-bow
|
| 25 |
```
|
| 26 |
|
| 27 |
-
|
| 28 |
|
| 29 |
-
|
| 30 |
-
set
|
| 31 |
-
|
| 32 |
-
remontée.
|
| 33 |
|
| 34 |
```
|
| 35 |
sudo robotctl policy load ground_pick <user>/microduck-bow
|
| 36 |
-
#
|
| 37 |
```
|
| 38 |
|
| 39 |
-
##
|
|
|
|
|
|
|
|
|
|
| 40 |
|
| 41 |
```
|
| 42 |
uv run scripts/infer_policy.py --walking alpha_walking.onnx --standing alpha_stand.onnx \
|
| 43 |
--ground-pick policy.onnx --ground-pick-period 10.0 --ground-pick-end-phase 0.7 --new-cmd-obs
|
| 44 |
```
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
---
|
| 2 |
license: apache-2.0
|
| 3 |
+
language: en
|
| 4 |
+
tags: [microduck, policy, bow, reinforcement-learning, mujoco, onnx]
|
| 5 |
---
|
| 6 |
|
| 7 |
# microduck-bow
|
| 8 |
|
| 9 |
<video src="https://huggingface.co/AdsumSOK/microduck-bow/resolve/main/media/preview.mp4" controls autoplay muted loop width="640"></video>
|
| 10 |
|
| 11 |
+
*One full cycle in simulation (mjlab / MuJoCo Warp, BAM actuators), 11 s.*
|
| 12 |
|
| 13 |
+
A bow for the Microduck (Pollen Robotics). Episodic, phase-driven policy (10 s cycle, 6.1 s
|
| 14 |
+
gesture, hand-back at 7 s), trained with `pollen-robotics/microduck_rl` on a custom task
|
| 15 |
+
(`Mjlab-Bow-Flat-MicroDuck`).
|
| 16 |
|
| 17 |
+
The gesture: the beak comes down to 2 cm above the floor without touching it, with the legs
|
| 18 |
+
bending symmetrically during the descent; the head turns about 83° to the left and back; the
|
| 19 |
+
knees bend; the duck stands back up.
|
| 20 |
|
| 21 |
+
## Installing on the robot
|
| 22 |
|
| 23 |
+
This is a `phase`-encoded policy: it goes into the `ground_pick` slot (the ground-pick button
|
| 24 |
+
triggers it), not into a skill (`policy add` refuses non-constant encodings).
|
| 25 |
|
| 26 |
```
|
| 27 |
sudo robotctl policy load ground_pick <user>/microduck-bow
|
| 28 |
```
|
| 29 |
|
| 30 |
+
Back to the official ground pick: `sudo robotctl policy reset ground_pick`.
|
| 31 |
|
| 32 |
+
The daemon drives the phase with the period set in `robotd.toml` and hands back at φ = 0.7 (the
|
| 33 |
+
official set's value, not configurable). The policy is trained on a 10 s cycle whose gesture fills
|
| 34 |
+
the first 6.1 s: with `ground_pick_period = 10.0`, the hand-back lands at 7 s, after the rise.
|
|
|
|
| 35 |
|
| 36 |
```
|
| 37 |
sudo robotctl policy load ground_pick <user>/microduck-bow
|
| 38 |
+
# then in /etc/robot/robotd.toml: ground_pick_period = 10.0
|
| 39 |
```
|
| 40 |
|
| 41 |
+
## Rehearsal in simulation
|
| 42 |
+
|
| 43 |
+
With the official walking and standing policies from `pollen-robotics/microduck-policies`
|
| 44 |
+
(press G to trigger the bow):
|
| 45 |
|
| 46 |
```
|
| 47 |
uv run scripts/infer_policy.py --walking alpha_walking.onnx --standing alpha_stand.onnx \
|
| 48 |
--ground-pick policy.onnx --ground-pick-period 10.0 --ground-pick-end-phase 0.7 --new-cmd-obs
|
| 49 |
```
|
| 50 |
+
|
| 51 |
+
## Evaluation (simulation)
|
| 52 |
+
|
| 53 |
+
Headless rollout, 256 environments × 20 s, no pushes (mjlab 1.3.0, BAM XL330 actuator model):
|
| 54 |
+
|
| 55 |
+
| Metric | Value |
|
| 56 |
+
|---|---|
|
| 57 |
+
| Falls | 0 % |
|
| 58 |
+
| Beak contact with the floor | none (minimum height 1.8 cm, head/floor force ≤ 0.16 N) |
|
| 59 |
+
| Clean hover (beak never below 1.5 cm, no contact force) | 90 % of cycles |
|
| 60 |
+
| Left/right leg symmetry during the descent | 1.2° mean mirror error |
|
| 61 |
+
| Head yaw reached | 83° |
|
| 62 |
+
| Knee bend before the rise | 62° / 61° |
|
| 63 |
+
| Trunk tilt at the lowest point | 33° |
|
| 64 |
+
|
| 65 |
+
## Provenance
|
| 66 |
+
|
| 67 |
+
Checkpoint `model_499.pt` of run `v8_hover_sym` (500 iterations, warm-started from the previous
|
| 68 |
+
version). Version lineage: v1 → v2 (force cap, strict feet, sliding descent target) → v4
|
| 69 |
+
(contact-force band) → v5 (no second contact) → v6 (knee bend) → v7 (10 s period for the daemon's
|
| 70 |
+
0.7 cutoff) → v8 (no contact, symmetric legs). The ONNX graph embeds the observation normalizer
|
| 71 |
+
(exported with `scripts/export.py`); the training checkpoint is not included.
|
manifest.json
CHANGED
|
@@ -15,7 +15,7 @@
|
|
| 15 |
"chain": false,
|
| 16 |
"entry_pose": "standing",
|
| 17 |
"slot": "ground_pick",
|
| 18 |
-
"description": "
|
| 19 |
"command": {
|
| 20 |
"encoding": "phase",
|
| 21 |
"slots": "twist.vx,twist.vy",
|
|
@@ -26,7 +26,7 @@
|
|
| 26 |
0.0,
|
| 27 |
0.0
|
| 28 |
],
|
| 29 |
-
"twist": "[cos 2πφ, sin 2πφ, 0], φ
|
| 30 |
"head": "unused (zeros)",
|
| 31 |
"body": "unused (zeros)"
|
| 32 |
},
|
|
@@ -36,22 +36,23 @@
|
|
| 36 |
"commit": "b02fdea49",
|
| 37 |
"branch": "develop",
|
| 38 |
"dirty": true,
|
| 39 |
-
"run": "logs/rsl_rl/bow/2026-10-
|
| 40 |
-
"checkpoint":
|
| 41 |
-
"source_file": "
|
| 42 |
-
"exported": "2026-10-
|
| 43 |
-
"lineage": "
|
| 44 |
},
|
| 45 |
"eval": {
|
| 46 |
-
"sim": "mjlab 1.3.0 / MuJoCo Warp, BAM XL330, scripts/bow_eval.py, 256 envs x 20 s,
|
| 47 |
"falls": "0 %",
|
| 48 |
-
"beak_contact": "
|
| 49 |
-
"
|
|
|
|
| 50 |
"knees_end_of_crouch_deg": [
|
| 51 |
-
|
| 52 |
-
-
|
| 53 |
],
|
| 54 |
-
"
|
| 55 |
-
"note": "
|
| 56 |
}
|
| 57 |
}
|
|
|
|
| 15 |
"chain": false,
|
| 16 |
"entry_pose": "standing",
|
| 17 |
"slot": "ground_pick",
|
| 18 |
+
"description": "Bow: lowers the beak to 2 cm above the floor WITHOUT touching it, legs symmetric during the descent, turns the head ~83° to the left and back, bends the knees (~62°), then stands back up. 6.1 s gesture on a 10 s phase cycle; the daemon hands back at φ = 0.7 (7 s), after the rise. Load into the ground_pick slot with ground_pick_period = 10.0 in robotd.toml, not as a skill.",
|
| 19 |
"command": {
|
| 20 |
"encoding": "phase",
|
| 21 |
"slots": "twist.vx,twist.vy",
|
|
|
|
| 26 |
0.0,
|
| 27 |
0.0
|
| 28 |
],
|
| 29 |
+
"twist": "[cos 2πφ, sin 2πφ, 0], φ from 0 to 1 over 10 s (segments: descent 0-0.15, low hold 0.15-0.18, lift 0.18-0.21, head turn 0.21-0.31, head return 0.31-0.41, knee bend 0.41-0.46, rise 0.46-0.61, rest 0.61-1.0; daemon cutoff at 0.7)",
|
| 30 |
"head": "unused (zeros)",
|
| 31 |
"body": "unused (zeros)"
|
| 32 |
},
|
|
|
|
| 36 |
"commit": "b02fdea49",
|
| 37 |
"branch": "develop",
|
| 38 |
"dirty": true,
|
| 39 |
+
"run": "logs/rsl_rl/bow/2026-10-28_12-35-32_v8_hover_sym (wandb offline, local)",
|
| 40 |
+
"checkpoint": 499,
|
| 41 |
+
"source_file": "model_499.pt",
|
| 42 |
+
"exported": "2026-10-28T12:45:00Z",
|
| 43 |
+
"lineage": "v7_resume/model_748 -> v8_hover_sym (500 it. warm start: hover at 2 cm without contact, symmetric legs). The tight-std resume (v8_resume) degraded the head turn and was not kept."
|
| 44 |
},
|
| 45 |
"eval": {
|
| 46 |
+
"sim": "mjlab 1.3.0 / MuJoCo Warp, BAM XL330, scripts/bow_eval.py, 256 envs x 20 s, no pushes",
|
| 47 |
"falls": "0 %",
|
| 48 |
+
"beak_contact": "none: minimum beak height 1.8 cm (p10 1.5, p90 2.0), max head/floor force 0.16 N; clean hover on 90 % of cycles",
|
| 49 |
+
"leg_symmetry_descent_deg": 1.2,
|
| 50 |
+
"head_yaw_max_deg": 83.2,
|
| 51 |
"knees_end_of_crouch_deg": [
|
| 52 |
+
62.0,
|
| 53 |
+
-60.8
|
| 54 |
],
|
| 55 |
+
"trunk_tilt_at_lowest_deg": 33,
|
| 56 |
+
"note": "lineage v1 -> v2 (force cap, strict feet, sliding target) -> v4 (force band) -> v5 (no second contact) -> v6 (knee bend) -> v7 (10 s period) -> v8 (no contact, symmetric legs)"
|
| 57 |
}
|
| 58 |
}
|
media/preview.mp4
CHANGED
|
@@ -1,3 +1,3 @@
|
|
| 1 |
version https://git-lfs.github.com/spec/v1
|
| 2 |
-
oid sha256:
|
| 3 |
-
size
|
|
|
|
| 1 |
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:2c41242a761f3b4b7069708f7cab2ad5421fcefcc5bebea7ac1c6f5835d7663f
|
| 3 |
+
size 538774
|
policy.onnx
CHANGED
|
@@ -1,3 +1,3 @@
|
|
| 1 |
version https://git-lfs.github.com/spec/v1
|
| 2 |
-
oid sha256:
|
| 3 |
-
size
|
|
|
|
| 1 |
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:c80c69a4d61fa3ee6af5539eb83210d5d7ee98e37d557682b073c70f985b74da
|
| 3 |
+
size 793742
|