Introduction
PuddleDuck provides a safe, extensible, hardware-aware API for controlling high-torque robotic actuators. It is the foundation layer for Duckling droids and related projects, handling everything from bus management to motor safety.
PuddleDuck
|
Key features
- Safety framework for high-torque motors
- Joints described declaratively in YAML
- Normalized joint position interface (
-1.0, 0.0, 1.0)
- Support for degrees/radians position
- Support for inverted joints
- Runtime updates of joint limits
- Protection against invalid or dangerous commands
- Built-in motion capture support
Supported motors
- Unitree Go series (Go1, Go2)
- Unitree Uki series (A1, B1)
- Cybeargear (in progress)
- Dynamixel
|
Host utilities and Teensy firmware targets live under src/tools and are built via the top-level Makefile:
- CMake + Ninja for host tools (macOS, Linux)
- PlatformIO for Teensy 4.0 firmware
Quick start
Host utilities (macOS/Linux)
git clone https://github.com/openbiped/PuddleDuck
cd PuddleDuck
make
# Binaries: .build/<triple>/<BUILD>/
Teensy firmware (build + upload)
git clone https://github.com/openbiped/PuddleDuck
cd PuddleDuck
make puddleduck UPLOAD=1 VERBOSE=1
Prerequisites
- CMake (≥ 3.20 recommended)
- Ninja
- Python 3
- PlatformIO Core CLI (
pio)
- C/C++ toolchain:
- macOS: Xcode/clang
- Linux: gcc or clang
- (Optional) Google Chrome for auto-opening docs
- (Optional) For building protoc libtools and autoconf are required
- (Optional) For building documentation doxygen is required
Build variables
BUILD — debug (default) or release
VERBOSE=1 — pass -v to Ninja/PlatformIO
UPLOAD=1 — upload firmware after a successful build
DUCK_CONFIG=<name> — select a non-default duck configuration
MAIN=<symbol> — define -DPUDDLEDUCK_MAIN=<symbol> for firmware
- Cross-compile host utilities with
TOOLCHAIN=<path/to/toolchain.cmake>
Examples:
make BUILD=release
make VERBOSE=1
make puddleduck UPLOAD=1
make TOOLCHAIN=toolchains/linux-armv7.cmake
Host build outputs:
.build/<triple>/<BUILD>/
e.g. .build/x86_64-unknown-linux-gnu/debug/
Teensy / PuddleDuck firmware
PuddleDuck uses PlatformIO for Teensy 4.0 targets. The Makefile patches Teensy USB headers when needed.
Common targets:
make teensy — minimal Teensy environment build
make puddleduck — full firmware (builds runtime wheels, patches Teensy, compiles)
make puddleduck-usb — USB-oriented firmware
make puddleduck-v1-usb — revision 1 USB firmware
Flash after build:
make teensy UPLOAD=1 VERBOSE=1
make puddleduck-usb UPLOAD=1 VERBOSE=1
Duckling install over SSH
SSH_UPLOAD_USER — defaults to duck
SSH_UPLOAD_HOST — defaults to duckling
Example:
SSH_UPLOAD_USER=duck SSH_UPLOAD_HOST=duckling.local \
make puddleduck UPLOAD=1 VERBOSE=1
Runtime wheels (Python)
Build both CPU and GPU wheels:
Or individually:
make runtime-cpu
make runtime-gpu
Artifacts are written to runtime/dist .
Selecting a custom duck configuration
Using local.ini (recommended)
cp configs/puddleduck/default.ini configs/puddleduck/local.ini
cp configs/puddleduck/default.yaml configs/puddleduck/myduck.yaml
sed -i 's/default/myduck/g' configs/puddleduck/local.ini
make puddleduck VERBOSE=1
Using DUCK_CONFIG
cp configs/puddleduck/default.ini configs/puddleduck/myduck.ini
cp configs/puddleduck/default.yaml configs/puddleduck/myduck.yaml
sed -i 's/default/myduck/g' configs/puddleduck/myduck.ini
DUCK_CONFIG=myduck make puddleduck VERBOSE=1
Configuration (default)
The YAML defines buses, joints (safe ranges & gains), sensors, and scripts:
- Control loop:
frequency (Hz), optional dt, cutoff
- Buses: RS485, SBUS, I2C, TTL (baud, adapter, timeouts)
- Armatures with joints:
type (e.g., Go1, UkiA1, Dynamixel)
id and optional bus override
- Safe
range (e.g., [!deg -118, !deg 118])
- Gains:
kp, kd (and ki for Dynamixel)
- Optional
start or zero; optional:true for headless testing
- Sensors: e.g.,
QuackHead, BN085 IMU, GoBMS
- Policy: named joint groupings
- Scripts: named step sequences (name, target pos, duration)
Example Duck configuration
# Go1/Uki Duckling
frequency: 400
cutoff: 37.5
...
This example shows buses, joint definitions with safe ranges and gains, policies grouping joints, and a simple script (stand) with step timings.
Motion mapping cheatsheet
Normalized command conventions (from default config):
- head_neck_pitch: 0→1 back, 0→−1 front
- head_pitch: 0→1 down, 0→−1 up
- head_yaw: 0→1 left, 0→−1 right
- head_roll: 0→1 list left, 0→−1 list right
- hip_rotation_left: 0→1 inward, 0→−1 outward
- hip_abduction_left: 0→1 outward, 0→−1 inward
- hip_flexion_left: 0→1 backward, 0→−1 forward
- thigh_joint_left: 0→1 knee contracts, 0→−1 knee extends
- toe_joint_left: 0→1 heel up, 0→−1 heel down
- hip_rotation_right: 0→1 outward, 0→−1 inward
- hip_abduction_right: 0→1 inward, 0→−1 outward
- hip_flexion_right: 0→1 forward, 0→−1 backward
- thigh_joint_right: 0→1 knee extends, 0→−1 knee contracts
- toe_joint_right: 0→1 heel up, 0→−1 heel down
Makefile targets
Documentation
Generate Doxygen:
Cleaning
Clean artifacts: