📖 项目概览
核心结论:直接照抄陆吾智能(LuwuDynamics)开源的 XGO Duck 全套方案快速复现第一版。陆吾已把协议适配、RL 重训、扩展板设计全部做完,物料成本约 ¥1800-3200。原版 Microduck 硬件既买不到(Pollen 未开源 PCB/BOM/CAD),强行替换舵机还会触发协议不兼容和必须重训模型两个硬门槛。
这是什么
XGO Duck 是陆吾智能开源的双足机器鸭,基于 Arduino Uno Q 开发板。它是法国 Pollen Robotics(Hugging Face 旗下)开源项目 Microduck 的硬件复刻/本土化版本。运行走路、起身、拾取、翻滚四个预训练策略。
四个开源仓库
核心参数
| 类别 | 参数 | 数值 |
| 物理 | 高度 | ~25 cm |
| 重量 | 0.8 kg |
| 舵机 | 15 × FeeTech HD-1910 |
| 自由度 | 14(嘴独立) |
| 计算 | 策略频率 | 50 Hz |
| 舵机总线 | 100 Hz |
| 观测向量 | 61 维 float32 |
| 动作输出 | 14 维 float32 |
| 通信 | Linux↔MCU | Bridge 串口 2 Mbps |
| MCU→舵机 | Serial1 TTL 1 Mbps |
| IMU | QMI8658A I2C 400kHz, 0x6A/0x6B |
预训练动作
| 模型文件 | 动作 | 时长 | 说明 |
| xgoduck_walk.onnx | 走路 | 持续 | vx ±0.4, vy ±0.3, ωz ±1.0 |
| xgoduck_getup.onnx | 起身 | 自动 | 跌倒后爬起 |
| xgoduck_pick.onnx | 拾取 | 4 秒 | 走过去用嘴夹取 |
| xgoduck_roulade.onnx | 翻滚 | 1.9 秒 | 翻跟头 |
🏗️ 双芯片架构
Arduino Uno Q 是两块电脑焊在一块板上:
| Host(主机端) | MCU(单片机端) |
| 芯片 | Qualcomm QRB2210 Dragonwing,4×Cortex-A53 @2.0GHz,Adreno GPU,双 ISP | STM32U585,Cortex-M33 @160MHz,2MB Flash,786KB SRAM |
| 内存/存储 | 2GB LPDDR4 / 16GB eMMC 5.1 | 片上 SRAM |
| 无线 | WCBN3536A:Wi-Fi 5 双频 + BT 5.1 | — |
| OS | Debian Linux | Zephyr RTOS |
| 频率 | 50Hz ONNX 推理 + Web UI :9527 | 100Hz 总线循环 |
| 职责 | 策略推理、日志、HTTP API | 15 路舵机轮询、IMU 采集、240 字节状态包发布 |
浏览器 :9527
|
Linux 50Hz ONNX ---- duck_command (80字节) ----> STM32 100Hz
^ |
+------------- duck_state (240字节) ------------------+
|
Serial1 1Mbps, ID 10-14/20-24/30-34
QMI8658A IMU (I2C 0x6A)
💡 MCU 不等 Linux:STM32 以 100Hz 持续发状态包,Host 慢了就跳帧,没有动作积压队列。Linux 卡顿/卡死时 MCU 仍维持站立。
陆吾自研扩展板(载板)
堆叠在 UNO Q 上,6 页原理图,47 行 BOM,15 个 Gerber,全套开源。
| 板载器件 | 作用 |
| QMI8658A | 六轴 IMU(躯干中心),I2C,地址 0x6A/0x6B |
| H7651 + AMS1117-3.3 | 5V / 3.3V LDO 二次稳压 |
| SN74LVC1G125 / G126 | 串口缓冲器,TTL 半双工总线方向切换 |
| 舵机连接器 | 3× TE 292253-3 + 3× MX1.25 3-pin,菊花链 |
| 接口 | 电源开关、DC 桶座、XH2.54 电池座 |
整机 BOM 清单
| 功能 | 型号 | 厂家 | 数量 | 关键参数 |
| 主控 MPU | QRB2210 | Qualcomm | 1 | 4×A53 @2.0GHz,跑 Debian |
| 实时 MCU | STM32U585 | ST | 1 | M33 @160MHz,2MB Flash,Zephyr |
| Wi-Fi/BT | WCBN3536A | WINBO | 1 | Wi-Fi 5 + BT5.1 |
| IMU | QMI8658A | QST 矽睿 | 1 | 六轴,I2C @400kHz |
| 5V LDO | H7651 | 国产 | 1 | 电池→5V |
| 3.3V LDO | AMS1117-3.3 | AMS | 1 | 5V→3.3V |
| 串口缓冲 | SN74LVC1G125/126 | TI | 若干 | TTL 三态缓冲 |
| 总线舵机 | HLS1910 | 飞特 | 15 | 4.8-8.4V,9kg·cm,TTL 半双工 1Mbps |
| 电池 | 18650 2S | 成品 | 1 | 7.4V 直供舵机母线 |
| 轴承 | 10×15×3 / 16×22×4 | 标准件 | 13 | 关节旋转支撑 |
| 紧固件 | M2×6 / M2.5×6 / M3×16 | 标准件 | 200+ | 结构组装 |
电源树
- 18650 锂电池直供舵机母线(2S ≈7.4V,在 1910 上限 8.4V 内)
- 母线经扩展板 LDO 降到 5V 给 UNO Q 逻辑
- 再降到 3.3V 给 IMU
- DC 桶座可外接/充电,电池座快拆
结构件
- 3D 打印 PLA 主体,左右件分模(27 个 STL 文件)
- 足底防滑垫、鸭嘴上下唇用柔性 TPU 打印
- 紧固件:M2 沉头 ~200 颗 + M2.5/M3 若干 + 滚珠轴承 13 颗
⚙️ 舵机设置(装到框架之前做!)
⚠️ 一次只接一个舵机!总线上两个同 ID 会同时响应写指令。先设完 ID 再装机。
舵机 ID 映射
| ID | 部位 | 说明 |
| 10–14 | 左腿 | 5 个关节 |
| 20–24 | 右腿 | 5 个关节 |
| 30–33 | 脖子+头 | 颈俯仰、头俯仰、头偏航、头侧倾 |
| 34 | 嘴 | 不在策略动作里,Web UI 直接控 0°–30° |
💡 策略动作顺序:10-14(左腿)→ 30-33(头颈)→ 20-24(右腿),不是总线顺序。
设置步骤
- 打开
http://<板子IP>:9527/servo.html 进入设置模式
- 分配 ID:写 ID 先解锁寄存器
0x37 再写 0x05
- 打中位:移到原始位置 2047 写入。临时 KP=6, KD=20。ID34(嘴)用 KP=10
- 持久化 KP/KD:解锁
0x37 后存到 0x15,默认 KP=5, KD=20
- 断开这个舵机,重复直到每个 ID 唯一
- 装到框架,接线:舵机总线 D0/D1(Serial1, 1Mbps),IMU D20/D21(I2C, 400kHz, 0x6A/0x6B)
上电后自动写的寄存器
| 地址 | 值 | 含义 |
| 40 | 扭矩开关 | 临时扭矩寄存器 |
| 50 | KP=6 | 临时比例增益(ID34 用 KP=10) |
| 51 | KD=20 | 临时微分增益 |
断扭矩时清扭矩但不写目标位置。
Home Pose(初始站立)
| 关节 | 角度 |
| 髋/踝 | ±23° |
| 膝盖 | 0° |
| 髋外展 | ±5° |
| 脖子/头俯仰 | 20° |
| 嘴 | 0° |
| action_scale | 1.0 |
FeeTech HD-1910 规格
| 参数 | 数值 |
| 工作电压 | 4.8–8.4 V |
| 空载转速 | 0.137 sec/60°(73 RPM)@4.8V;~100 RPM @7.4V |
| 堵转扭矩 | 9 kg·cm(0.88 N·m) |
| 堵转电流 | 1.2 A |
| 重量 | 21–22.5 g |
| 尺寸 | 34×20×23 mm |
| 通信 | TTL 半双工,SCS 协议(帧头 0xFF 0xFF),默认 1Mbps |
| 编码器 | 12 位磁编码(0–4095) |
| 控制模式 | 仅位置控制(不开放电流环) |
飞特 HD-1910 产品页
feetech.cn/500263.html
🎯 校准与运行
零位校准(接好线后)
- 打开
http://<板子IP>:9527/calibrate.html
- 策略停止,临时参数变为 KP=3, KD=0,所有舵机命令到 2047
- 每个关节拖滑块对齐机械零点,按 Finish
- 编码器读数存到
data/zero_pos.json
- Host 启动时把它复制到 MCU RAM
启动 App
python3 tools/prepare-bridge.py # 给库缓存打补丁
sudo bash tools/router-2m.sh # 串口设 2Mbps
arduino-app-cli app start "$PWD" # 编译固件 + 启动 Python
| 脚本 | 作用 |
| prepare-bridge.py | patch RouterBridge 0.4.3 的 RPC 线程栈(500→4096 字节),原头文件备份 .h.original。清缓存后要重跑 |
| router-2m.sh | 把 Router 串口从 115200 改到 2Mbps。重启 Router 会复位 MCU,顺序:停 App→重启 Router→启动 App |
⚠️ 固定依赖:Arduino Zephyr Core 1.0.0 / RouterBridge 0.4.3 / RPClite 0.3.1 / MsgPack 0.4.2。别升级工具链——GCC 14 有短跳转 bug 会导致 MCU 起不来(ENOEXEC),陆吾已用 asm nop 规避。
Web UI 按钮(:9527)
| 按钮 | 行为 |
| Inference only | 策略在跑,舵机不上电(默认) |
| Default pose | 保持初始站立 |
| Walk / get up | 上电,走路 + 跌倒自动起身 |
| Pick | 站立时触发,跑拾取模型 4 秒后回走路 |
| Roulade | 站立时触发,翻滚 1.9 秒后回走路 |
| Torque off | 断电 |
键盘控制
| 键 | 作用 | 量程 |
| W/S | 前进/后退 | vx ±0.4 m/s |
| A/D | 左移/右移 | vy ±0.3 m/s |
| Q/E | 左转/右转 | ωz ±1.0 rad/s |
| 空格 | 停 | 死区 0.1 |
🎉 鸭子开始走路了!
🧠 策略模型
4 个 ONNX 模型都在 python/ 目录,启动时加载并预热。每个输入 [1,61],输出 [1,14]。
观测向量(61 维)
| 维度 | 内容 | 数量 |
| 0–2 | 陀螺仪(rad/s) | 3 |
| 3–5 | 重力向量(机身姿态) | 3 |
| 6–19 | 14 个关节位置(相对 home pose) | 14 |
| 20–33 | 14 个关节速度 | 14 |
| 34–47 | 上一步动作 | 14 |
| 48–50 | 速度指令(vx, vy, ωz) | 3 |
| 51–54 | 头部指令 | 4 |
| 55–60 | 补零 | 6 |
跌倒恢复(50Hz 检查)
| 条件 | 动作 |
| 倾斜 >55° 持续 0.15 秒 | 进入起身:动作强制为 0 保持 1 秒,然后 getup 模型 |
| 倾斜 <15° 持续 1 秒 | 回到走路模式 |
通信协议
- Linux → STM32:80 字节指令包
- STM32 → Linux:240 字节状态快照(100Hz)
- 串口波特率 2Mbps;位置/速度都是 float32 度数
- 舵机位置饱和到 0–4095;NaN/Inf 目标拒绝
🎓 RL 训练(xgoduck_rl)
# 训练(1024 并行环境)
uv run --no-sync train Mjlab-Velocity-Flat-XgoDuck --env.scene.num-envs 1024
# 可视化
uv run --no-sync play Mjlab-Velocity-Flat-XgoDuck --checkpoint-file
# viser 在 http://localhost:8080
# TensorBoard
tensorboard --logdir logs/rsl_rl # http://localhost:6006
⚠️ Windows + CUDA 必须:
1. $env:CUDA_VISIBLE_DEVICES="0"
2. --no-sync 防止 uv run 把 torch 同步回 CPU 版
pipeline
MuJoCo Warp 仿真(1024/4096 并行环境,GPU 加速)
↓
PPO 算法(50Hz 策略频率)
↓
保存 model_250.pt, model_500.pt ...
↓
导出 ONNX(归一化器烘焙进计算图)
↓
放到板子 python/ 目录 → 真机运行
关键参数
| 参数 | 值 | 含义 |
| num_envs | 1024(你)/ 4096(官方) | 并行仿真环境 |
| max_iterations | 50000 | 总训练轮数 |
| save_interval | 250 | 存 checkpoint 间隔 |
| 策略网络 | (512,256,128) | 三层 MLP + ELU |
| 学习率 | 1e-3 | 自适应调度 |
| 训练耗时 | 1–2 小时(CUDA GPU) | 4096 环境 |
Reward 组成
| 奖励项 | 权重 | 作用 |
| track_linear_velocity | +2.0 | 跟踪前进速度 |
| track_angular_velocity | +2.0 | 跟踪转向速度 |
| upright | +2.0 | 保持直立 |
| air_time | +3.0 | 腾空迈步 |
| head_pose_tracking | +2.0 | 头部姿态 |
| action_rate_l2 | -1.0 | 惩罚抖动 |
| foot_slip | -0.1 | 惩罚脚打滑 |
| self_collisions | -1.0 | 惩罚自碰撞 |
域随机化
- 电机摩擦、电池电压、控制延迟随机化
- 舵机齿隙 ±1°、质量分布随机化
- MuJoCo 执行器模型:反电动势、库仑/Stribeck/负载相关摩擦
🛠️ 复现流程与花费
工期(17–21 工作日)
| 阶段 | 任务 | 工期 | 依赖 |
| 采购打样 | PCB 打板贴片 | 7 天 | — |
| 3D 打印结构 | 3 天 | — |
| 采购舵机电池 | 5 天 | — |
| 组装 | 舵机烧 ID | 1 天 | PCB 到 |
| 机械组装接线 | 2 天 | 烧 ID 完 |
| 软件部署 | UNO Q 初始化 | 1 天 | 电池到 |
| 烧 STM32 固件 | 1 天 | 初始化完 |
| 零位标定 | 1 天 | 组装完 |
| 调试验证 | 走路/起身调试 | 3 天 | 标定完 |
💡 关键路径:PCB 打板 7 天。3D 打印和采购可并行。
实际花费(2026 年 9 月行情)
| 项目 | 数量 | 单价 | 小计 |
| Arduino UNO Q 2GB/16GB | 1 | ¥480 | ¥480 |
| 飞特 1910 舵机 | 15 | ¥120 | ¥1800 |
| 18650 2S 电池 | 1 | ¥60 | ¥60 |
| PCB 打样(嘉立创) | 1 | ¥50 | ¥50 |
| SMT 贴片+元件 | 1 | ¥150 | ¥150 |
| QMI8658A IMU | 1 | ¥15 | ¥15 |
| 3D 打印 27 件 | 1 批 | ¥80 | ¥80 |
| 螺丝/轴承/紧固件 | 1 批 | ¥80 | ¥80 |
| 杂项 | 1 批 | ¥30 | ¥30 |
| 小计 | | | ¥2745 |
| 损耗余量 | | | ¥300–500 |
| 合计 | | | ¥3050–3250 |
⚠️ 舵机已从年初 ¥45–50 涨到 ¥100–120,是最大预算变量。1688 批量可压到 ¥85/个,整机降到 ¥2500。
难点与坑点
高难度
| 难点 | 对策 |
| 串口波特率改 2Mbps | 跑 router-2m.sh 改 systemd 配置;跑其他 app 要改回来 |
| GCC 14 短跳转 bug | STM32 尾调用优化导致 ENOEXEC,陆吾已加 asm nop 规避,别升级工具链 |
| RouterBridge 线程栈 | 0.4.3 只有 500 字节,prepare-bridge.py 自动 patch 到 4096 |
中难度
- 15 个舵机逐个烧 ID(不能同时接两个同 ID)
- 零位标定左右腿要镜像方向,offset 错了就瘸
- TPU 打印方向:足底和鸭嘴用柔性料,L 型件注意受力方向
陆吾已趟平的坑
- SCS 协议适配层(scs_bus.h)已写完
- 1910 对应的 RL 重训模型已开源(3 个 onnx)
- 扩展板原理图/PCB/BOM/贴片坐标全给了
- Web UI 控制面板已写好
⚖️ Pollen 单芯 vs 陆吾双芯
| Microduck(Pollen) | XGO Duck(陆吾) |
| 主控 | RK3566 单 SoC(4×A55@1.8G + 0.8T NPU),1GB/32GB | QRB2210(A53@2.0G)+ STM32U585(M33@160M)双芯,2GB/16GB |
| 舵机 | 15× Dynamixel XL330(韩国) | 15× FeeTech 1910(深圳) |
| IMU | 双 IMU(躯干 LSM6DSV16X + 头部) | 单 IMU QMI8658A |
| 相机/ToF | 前置广角 + 8×8 ToF | 无 |
| 音频/NFC | Codec + 麦 + 扬声器 + NFC | 无 |
| 结构 | 量产注塑 + 内部骨架 | 3D 打印 PLA + TPU,STL 全开源 |
| 硬件开源 | 仅软件 Apache-2.0,PCB/BOM/CAD 不公开 | 硬件全开源:原理图/PCB/BOM/Gerber/STL/固件/UI/ONNX |
| 价格 | $399(约 ¥2900) | DIY ¥1800–3200 |
工程哲学对比
| Pollen 单芯(Rust + Linux) | 陆吾双芯(Linux + Zephyr) |
| 信任什么 | 智能舵机 + Rust SCHED_FIFO 够用 | 物理隔离才安全 |
| Linux 挂了 | 鸭子失控 | MCU 接管,安全蹲下 |
| 团队基因 | 法国软件/AI 团队,擅长 Rust | 哈工大硬件团队,擅长 MCU |
| 调试 | 一个二进制,简单 | 跨核 UART 协议联调 |
| 成本 | 省一颗 MCU,压 $399 | UNO Q 板自带 STM32,"不用白不用" |
为什么两款舵机不能混用
| Dynamixel XL330-M288 | Feetech HLS1910 |
| 协议 | Dynamixel Protocol 2.0,帧头 0xFF 0xFD,CRC16 | SCS 协议,帧头 0xFF 0xFF,单字节和校验 |
| 波特率 | 9.6k–4Mbps | 38.4k–1Mbps |
| 控制模式 | 电流环/PWM 电压控制 | 仅位置控制 |
| 堵转扭矩 | 0.52 N·m(5.3 kg·cm) | 0.88 N·m(9 kg·cm),大 70% |
| 电压 | 5V | 4.8–8.4V,2S 直供 |
| 重量 | 18g | 21g |
| 编码器 | 12 位(1024 位置分辨率) | 12 位(4096) |
⚠️ 混用 = 改固件协议栈 + 重训 RL + 重画结构 + 改电源,等于重新做一只鸭子。
🏭 Microduck 机载软件栈(Rust 7 daemon)
机载运行时纯 Rust,拆 7 个守护进程,Unix Socket + JSON-RPC 2.0 通信。核心原则 single-writer:只有 robotd 拥有电机控制权。
| 进程 | 职责 | 硬件 |
| robotd | 50Hz 实时控制 + ONNX 推理 + 安全 | 15 舵机 + 双 IMU |
| updaterd | OTA 更新,A/B 分区签名回滚 | 系统分区 |
| configd | Wi-Fi 配网、设备身份 | Wi-Fi |
| btd | 蓝牙通信、手柄配对 | BT |
| padd | 手柄输入解析 | BLE/USB |
| mediad | 摄像头、音频、WebRTC | MIPI-CSI + Codec |
| tofd | ToF 数据读取 | VL53L8CX I2C |
💡 为什么不用 ROS2?DDS 通信栈对 1GB RAM 的 RK3566 太重;50Hz 硬实时需更可控延迟;7 进程规模下 Unix Socket 足够。
训练命令(官方 Microduck)
uv run train Mjlab-Velocity-Flat-MicroDuck --env.scene.num-envs 4096
uv run play Mjlab-Velocity-Flat-MicroDuck --wandb-run-path [run]
uv run scripts/export.py Mjlab-Velocity-Flat-MicroDuck
出厂 7 个策略:摇摆行走、蹲起、用喙捡物、踢球、轮滑、跌倒爬起、NFC 触发交互。
需要学习的技术栈
| 优先级 | 技术 | 用途 | 周期 |
| 必学 | Rust | 机载 7 daemon | 4–8 周 |
| 必学 | Python + PyTorch | 训练/调参 | 2–4 周 |
| 必学 | MuJoCo | 物理仿真 | 2–4 周 |
| 重要 | PPO 强化学习 | 算法/奖励设计 | 4–6 周 |
| 重要 | ONNX 导出部署 | 模型端侧推理 | 1–2 周 |
| 重要 | Linux 嵌入式 | 交叉编译/调试 | 2–4 周 |
| 进阶 | Dynamixel 协议 | 舵机底层 | 1–2 周 |
| 进阶 | ROS2 | 通用框架 | 6–8 周 |
🌏 市场表现与国内玩家
Microduck 首发数据
| 指标 | 数据 |
| 售价 | $399 |
| 24h 销售额 | $260 万(~6500 台) |
| 峰值 | 每 4 秒 1 台 |
| 首发地区 | 8 国(美/加/欧盟/英/挪威/瑞士/日/韩) |
| 中国大陆 | 未首发,代购价 ¥2680 |
| 排期 | 4–6 个月 |
购买者画像
| 人群 | 占比 | 动机 |
| 开发者/AI 工程师 | 35% | 桌面级 RL 实验平台 |
| 高校师生 | 25% | 教学/科研,$399 是实验室可买临界点 |
| 创客/爱好者 | 25% | 开箱视频、改装、UGC |
| 新潮家长 | 15% | 情绪价值+孩子教育 |
💡 没有人为"实用功能"买单——购买者完全接受它"不干活"。
国内玩家
| 公司 | 产品 | 价格 | 路线 |
| 陆吾智能 | RIG-Puppy + XGO-Duck | ¥499 | 开源极客,哈工大背景 |
| 青心意创 Amoo | 毛绒双足机器人 | ~$500–1000 | 毛绒情感陪伴,前华为自动驾驶团队 |
| 华为 × 珞博 | 智能憨憨 | ¥399 | 毛绒公仔+小艺大模型,开售秒罄 |
| 松延动力 | 小布米 Bumi | ¥9998 | 万元内人形,2 天 500 台售罄 |
| 宇树科技 | Go2 四足 | $1600+ | 四足全球市占 69.75% |
| 大象机器人 | myCobot / Mercury | ¥2000–8000 | 桌面机械臂出海标杆 |
| 越疆科技 | Magician/Nova | ¥8000+ | 桌面协作臂开创者,港股 IPO |
三阶段战略路线(消费电子厂商参考)
| 阶段 | 时间 | 动作 |
| P0 轻资产试水 | 0–6 月 | 不做整机,做手机协同 SDK + 投资/合作 + 教育试点 |
| P1 能力验证 | 6–18 月 | 做参考设计/Turnkey 方案,不做品牌 |
| P2 重投入 | 18 月+ | 自有品牌 $99–199,新兴市场首发 |
窗口期 12–18 个月(2026Q4–2027Q4)。超过 2027 年底,宇树/华为/小米进场,先发优势稀释。