Microduck全栈拆解:一只25厘米的小黄鸭,装着一整个软件工程

01-microduck全栈拆解:一只25厘米的小黄鸭,装着一整个软件工程课堂
引子:先认识这只鸭子
大家好,我是黒漂技术佬。
先别急着看代码——我们今天的主角,是一只鸭子。
不是超市里那种橡皮鸭,是法国公司 Pollen Robotics 做的一只双足机器人,名字叫 microduck:身高约 25 厘米,体重 800 克,会走路、会捡东西、会踢球、被推倒了能自己站起来,还会发出属于自己的"嘎嘎"声。它的大脑,是一块瑞芯微 RK3566 的开发板,运行着用 Rust 写的软件系统。
(它比你家猫轻,但代码量可能比你手头的项目还讲究。)
Pollen Robotics 这家公司你可能没听过,但如果你关注过开源人形机器人,大概率见过他们的大块头亲戚——Reachy,一台几万欧元的成人尺寸服务机器人。microduck 就是这家公司在"小巧、便宜、人人都玩得起"方向上的尝试。
它凭什么值得你花时间研究?一句话:这是一只 25 厘米的小鸭子,装着一整个软件工程课堂。
25 厘米的体型决定了它的资源极其有限(内存几百 MB、Flash 若干 GB、CPU 是四核 A55);但它的野心却很大(实时控制、无线升级、远程视频、蓝牙配网、强化学习策略部署全都要)。于是,团队把大型机器人系统里那些"因为钱多所以随便造"的奢侈,全部砍掉,只留下最本质的工程决策。
这正是研究 microduck 的价值:在资源极度受限的环境里,你能看到软件架构里哪些是刚需,哪些是习惯。
一、它能干什么?先看能力清单
官方 README 里用四张动图概括了它的绝活:
| 能力 | 说明 |
|---|---|
| 会走路 | 拿起手柄(gamepad),开着它满屋跑 |
| 会滚 | 装上轮子,按住 D-pad 上键,它自动切换成"轮式大脑" |
| 会捡东西 | 嘴(beak)贴地,一个按钮完成拾取 |
| 会自己爬起来 | 把它推倒,它自己站起来 |
除此之外:会坐、会踢球、会按指令滚动,还会用"只属于自己"的嗓音嘎嘎叫。
注意最后一条——“a voice that is its own”。这句话很关键,它暗示了一个重要的设计取向:这只鸭子不是一个单纯的"玩具",而是一个可个性化、可编程、有自己身份的机器人平台。身份(identity)、语音、个性化配置,这些词在后面的架构里会反复出现。
二、硬件底子:800 克的机器人里装了什么
在做软件分析之前,先认识一下它的"身体"。根据 README 和架构文档,我们可以还原出大致的硬件构成:
| 部件 | 规格/说明 |
|---|---|
| 主控 SoC | 瑞芯微 RK3566(四核 Cortex-A55,带 Mali-G52 GPU 和 0.8 TOPS NPU) |
| 舵机 | 15 个 Dynamixel 系列数字舵机(串行总线舵机) |
| IMU | 惯性测量单元(用于姿态感知) |
| 相机 | 板载摄像头(640×480 RGB @ 30fps 级别) |
| 深度传感器 | 头部一颗 ToF(飞行时间)传感器,8×8 深度矩阵 |
| 通信 | WiFi(NetworkManager 管理)+ 蓝牙 BLE + 可选手柄 BLE/USB |
| 系统底座 | Armbian 类 Linux 发行版(原厂基于 Debian 的 ARM 发行版) |
有几个数字值得停下来琢磨:
15 个舵机——双足机器人每条腿至少 5~6 个自由度(髋 3 + 膝 1 + 踝 2),加上身体、脖子、嘴,15 个是"刚好够用"的配置。舵机全部是 Dynamixel 串行总线舵机,意味着所有舵机挂在同一条串口总线上——这是后面控制环设计的地基。
0.8 TOPS NPU——非常小的算力。但架构文档里提到,团队正在把"鸭子检测器"(duck detector)部署到这块 NPU 上。这说明什么?端侧 AI 在 0.8 TOPS 上也能跑,关键是模型和管线要对胃口。这一点对做嵌入式视觉的朋友是重要参照。
25cm / 800g——这个体积意味着:电池很小,续航有限;舵机扭矩有限;CPU 不能全速跑(散热);没有风扇。每一个软件决策,最终都要回到"这块电池能撑多久、这个 CPU 会不会过热"上来。
三、软件骨架:一张图看懂整只鸭子
这是全文的"导航图",建议截图保存。microduck 的软件系统可以总结成一句话:
一块 RK3566 上跑着 7 个 Rust 守护进程(daemon),它们通过 Unix socket 上的 JSON-RPC 2.0 协议互相通信;其中 robotd 是唯一能碰机器人的进程,负责一个 50Hz 的实时控制环,用神经网络策略驱动 15 个舵机。
先看这张分层图:
┌─────────────────────────────────────────────────────────┐
│ 外部世界 │
│ 手柄(BLE/USB) 手机(BLE) 电脑(SSH) 远程对端(WebRTC) │
└──────────┬─────────────┬───────────┬───────────┬─────────┘
│ │ │ │
▼ ▼ ▼ ▼
┌────────┐ ┌────────┐ ┌────────┐ ┌──────────┐
│ padd │ │ btd │ │robotctl│ │ mediad │
│手柄输入│ │蓝牙通道│ │ CLI │ │摄像头+WebRTC│
└───┬────┘ └───┬────┘ └───┬────┘ └────┬─────┘
│ │ │ │
│ Unix socket + JSON-RPC 2.0 (NDJSON) │
│ │ │ │
▼ ▼ ▼ ▼
┌──────────────────────────────────────────────┐
│ robotd(控制核心) │
│ 50Hz 控制环 · 运动学 · 里程计 · 策略推理 │
│ 安全层 · 传感器循环 · 机器人健康状态 │
└──────────────┬───────────────────────────────┘
│ Dynamixel 串行总线
▼
┌──────────────┐
│ 15个Dynamixel舵机 + IMU │
└──────────────┘
另外还有两个不在图上的守护进程:
- configd:负责 WiFi、机器人身份与名字、配对 PIN、手柄绑定、重启——它在 robotd 挂了之后还能干活(后面细说为什么);
- updaterd:负责固件更新的"验证、安装、切换、健康检查、回滚"——保证 OTA 不会把鸭子变成砖头;
- tofd:单独管理头部 ToF 深度传感器,只发布数据,没人读也无所谓。
七个 daemon 的分工(官方架构文档的表格,我翻译整理):
| 服务 | 拥有(Owns) | 监听 | 访问目标 |
|---|---|---|---|
robotd | 电机控制、传感、策略、安全、健康状态 | /run/robotd.sock | Dynamixel 总线 |
configd | WiFi、机器人身份、配对 PIN、手柄绑定、重启 | /run/configd.sock | BlueZ & NetworkManager(经 D-Bus) |
updaterd | 发布版本:验证、安装、切换、健康门控、回滚 | /run/updaterd.sock | GitHub Releases、systemd、robotd |
btd | 无(纯 BLE 传输通道) | BLE GATT 服务 | robotd/configd/updaterd |
padd | 无(手柄传输,原始输入转发) | /run/padd/pad.sock | robotd |
mediad | 摄像头/音频管线、WebRTC 传输 | TCP 8080/8443 | robotd/configd/updaterd |
tofd | 头部 ToF 传感器(8×8 深度矩阵) | /run/tofd/tof.sock | HAT 的 I²C 总线 |
四、最重要的三个工程决策
在讲细节之前,先把整只鸭子最值得学习的三个决策拎出来——它们几乎贯穿了后面每一篇文章。
决策一:控制平面与数据平面严格分离
机器人上有两类完全不同的数据:
- 控制平面:命令、配置、状态、感知事件——几十字节,频率 ≤100Hz,走 Unix socket RPC;
- 数据平面:视频帧/音频帧——640×480 RGB @30fps 大约是 27MB/s,绝不跨 socket 传输。
27MB/s 什么概念?Unix socket 能扛得住,但没意义——robotd 的控制环根本不需要看视频帧,它只需要"球在 (x,y)"这种几十字节的感知结果(10~30Hz)。
设计铁律:能传特征,就绝不传原始数据。
这和我们做无人售货柜视频识别时踩过的坑一模一样——把整帧视频从采集进程传到识别进程,带宽和延迟瞬间爆炸;后来改成采集进程先做目标检测,只把"目标框+分类"传出去,整个系统立刻轻快起来。microduck 把这个原则写进了架构文档第一条。
决策二:robotd 是唯一能碰机器人的进程
七个子系统,但只有 robotd 有权限操作舵机。所有其他进程——手柄、手机 App、电脑命令行、远程 WebRTC——都只能向 robotd 发送 intent(意图):
- “走这么快”
- “看向那里”
- “站起来”
robotd 内部有一个安全层,负责决定这个意图能不能执行:会不会摔倒?关节有没有超限?温度是否过高?没有谁能绕过摔倒检测、关节限位和安全姿态逻辑——本地不行,远程更不行。
这是机器人领域最核心的安全架构:执行权收敛到单一权威,其他人只提想法。
决策三:恢复路径不依赖机器人本体
细心的读者会发现,configd 和 updaterd 都不依赖 robotd:
- robotd 挂了,configd 照样能配 WiFi——因为"配网"这种操作必须能在"机器人已经疯了"的时候进行;
- updaterd 同样独立——因为 OTA 恰恰经常发生在"机器人出问题"的时候。
这个决策让整个系统的可救性(recoverability)大幅提升:任何单点故障,都有不依赖该点的恢复通道。
五、技术栈:Rust 和一个有意思的选择
microduck 的软件栈是:
Rust,无框架,一个 workspace。
- 语言:Rust——内存安全、无 GC、性能接近 C,天然适合嵌入式系统级开发;
- 异步运行时:tokio;
- IPC:JSON-RPC 2.0,NDJSON 格式(每行一个 JSON 对象),用
tokio_util::codec::LinesCodec做帧切分,serde 做序列化; - “无框架”:没有用现成的机器人中间件(比如 ROS 2),而是自己定义了一套极简的 Unix socket RPC 协议。
这个"无框架"的决策值得展开说。团队在架构文档里明确写了为什么不用现成的方案:
| 候选方案 | 为什么没用 |
|---|---|
| HTTP/WebSocket | 需要服务端→客户端主动推送(订阅),HTTP 轮询太笨;NDJSON 长连接无握手开销,还能统一"请求/响应"与"通知"两种模式 |
| D-Bus | 消息还需要经过 BLE、WebRTC 走,用 plain serde 更通用;JSON 让它免费 |
| jsonrpsee-server | 不能直接 serve Unix socket |
| zbus(D-Bus 的 Rust 绑定) | 依赖太重(66 个 crate),只在 BlueZ/NetworkManager 处用 D-Bus |
最终选了"JSON-RPC/NDJSON + tokio",只有约 30 个依赖。
这里有个值得品味的点:很多工程师一听"机器人"就想到 ROS,但 microduck 证明——对于单板、单进程协作的场景,一套极简的 Unix socket RPC 可能比一整个 ROS 生态更合适。 工具的选择要匹配问题规模,而不是名气。
六、我们能从这只鸭子身上学到什么?——十堂课
这是本系列的"导学案",也是我对这个项目价值最大的总结。后面的文章会逐一展开,这里先给清单:
- 控制平面与数据平面分离——特征而非原始数据,是嵌入式系统设计的通用法则;
- 执行权收敛——安全关键操作只允许一个权威进程执行,其他人只能发意图;
- 故障隔离——媒体崩溃不能拖垮电机;传感器崩溃不能拖垮控制环;
- 恢复路径独立——OTA、配网等救命操作,不能依赖被救的对象;
- 50Hz 实时控制环——嵌入式实时控制的典型形态:周期、预算、不阻塞;
- Unix socket 权限即安全——文件系统权限 + SO_PEERCRED 做进程鉴权,比 HTTP 端口安全得多;
- OTA 不砖机——签名验证 + 原子切换 + 健康门控 + 自动回滚,一套可复用的升级方法论;
- sim2real——MuJoCo 仿真 + PPO 训练 + ONNX 导出 + 端侧推理,RL 落地的完整流水线;
- 配置与代码分离——
/etc/robot/、/var/lib/robot/、/opt/robot/的分层,是嵌入式系统状态管理的范本; - 文档即设计——“One page owns a mechanism”:一个机制只在一个文档里详述,其他文档只引用。这一条对团队协作的启示,可能比技术本身更值钱。
七、本系列规划
这只鸭子值得写的内容太多了,我把它拆成两个系列方向(对应专题文件的两个方向):
系列一:microduck 技术分析,我们能学到什么
- 02-50Hz 控制环:robotd 如何用一条串口总线驱动 15 个舵机
- 03-守护进程军团:Unix socket 上的 JSON-RPC 微服务架构
- 04-OTA 不砖机:签名验证、健康门控与自动回滚的完整设计
- 05-从 MuJoCo 到真鸭子:PPO 策略训练与 ONNX 端侧部署
系列二:如何做自己的 microduck
- 06-从硬件选型到第一行代码:复刻一只小鸭子的完整路线图
小结
一只 25 厘米、800 克的鸭子,装着一套比很多云服务都讲究的软件架构。它的每一个设计决策——数据平面分离、执行权收敛、恢复路径独立、Unix socket 做 IPC——都不是凭空想出来的,而是在"资源极有限 + 可靠性要求高"的约束下逼出来的最优解。
研究一个受约束的项目,比研究一个资源无限的项目,能学到的东西多得多。 因为约束会强迫你把每个决策都做出理由。
下一篇,我们钻进控制核心 robotd,看看那根 50Hz 的"心跳"是怎么打出来的。
我是黒漂技术佬,咱们下篇见。
DAMO开发者矩阵,由阿里巴巴达摩院和中国互联网协会联合发起,致力于探讨最前沿的技术趋势与应用成果,搭建高质量的交流与分享平台,推动技术创新与产业应用链接,围绕“人工智能与新型计算”构建开放共享的开发者生态。
更多推荐

所有评论(0)