Microduck 的感知系统:ToF 深度传感与 IMU 在 50Hz 控制循环中的协同设计
双足机器人最难的问题不是”怎么走”,而是”我怎么知道自己走歪了”。
Pollen Robotics 在 Microduck 上选了三类传感器:IMU、ToF 深度传感器和摄像头。数量不多,但每类的集成方式完全不同——有的挂在总线上和控制循环同步,有的走独立进程只发布不读取,有的只在特定场景下唤醒。
这篇文章把传感器感知层面的架构拆开,不单讲硬件规格,更看这些传感器怎么在 50Hz 的控制循环里协同工作。
三类传感器,三种集成策略
从官方架构文档可以梳理出完整的传感器拓扑:
- IMU:BMI088,随 Robot HAT PCBA 板载,但数据通过 imu_to_dxl v2 板挂在 Dynamixel 总线上,作为第 16 个设备参与 sync_read
- ToF:VL53L8CX,8×8 深度阵列,通过 I²C 接 HAT,由独立守护进程 tofd 管理
- 摄像头:IMX219,8 MP,由 mediad 管理,走 TCP 数据面
每个传感器的集成策略都不一样。不是技术能力问题,而是数据流特性决定的。
IMU:为什么挂在舵机总线上
IMU 放在 Dynamixel 总线上这个设计,第一次看到时觉得奇怪——IMU 不是通常走 SPI 或 I²C 吗?挂到舵机总线上,总线负载不是更重了?
读设计文档才知道原因。Pollen 的 imu_to_dxl v2 板是一个硬件翻译器:BMI088 的 SPI 输出被转成 Dynamixel Protocol 2.0 的 register block,和舵机用同一套协议回答查询。
这意味着 robotd 可以在一次 sync_read 里读完所有数据。 不是先读 IMU 再读舵机,而是一条命令发出去,总线上的 16 个设备依次应答:
sync_read id vector: [200, 10, 11, 12, 13, 14, 20, 21, 22, 23, 24, 30, 31, 32, 33, 34]
[IMU, 右腿×5, 左腿×5, 脖子/头×5]
id 200 排在第一位,因为 imu_to_dxl 板响应速度最快,先应答避免总线上产生空隙。
IMU 板输出的数据是 SFLP 四元数——一种紧凑的四元数编码格式,比标准四元数省 25% 带宽。在 1 Mbps 的 Dynamixel 总线上,省出的字节可以留给舵机寄存器。
这个设计的直接后果是:控制循环的观测空间天然包含 IMU 数据,不需要额外的数据对齐或时间戳同步。 61 维观测向量里的 roll/pitch/yaw 来自和关节角度同一时刻的 sync_read,不存在两个传感器采样时间差的问题。
观测构建流程:
sync_read(16 设备,3-5ms)
│
├── 关节角度(reg 124-136):15 舵机 × 3 寄存器
├── 关节速度:同上 register 范围的不同偏移
├── 关节负载:同上
└── IMU 四元数:imu_to_dxl 板 → SFLP 解码 → roll/pitch/yaw
│
└── IMU 加速度:同一 register block 的附加字段
│
▼
Observation::build → 48 维本体感受(含 IMU)+ 13 维指令 → 61 维
不需要传感器融合库、不需要卡尔曼滤波器——因为所有数据在硬件层面已经对齐了。这是极简但有效的设计。
BMI088 的规格
BMI088 是博世的一款工业级 IMU,在机器人领域用得很多。它的两个传感器单元独立运行:
- 加速度计:±24g 量程,噪声密度 230 μg/√Hz,ODR 最高 1.6 kHz
- 陀螺仪:±2000°/s 量程,零偏稳定性 0.2°/s,ODR 最高 2 kHz
对 Microduck 这个尺度的双足机器人来说,BMI088 的参数绰绰有余。陀螺仪的 0.2°/s 零偏意味着短时间姿态估计不需要频繁校准,50Hz 控制循环里一次读取就够了。
数据来源:博世 BMI088 数据手册、microduck 仓库 architecture.md、robotd-design.md。
ToF:独立的发布者,不读取任何东西
和 IMU 深度集成不同,ToF 传感器的设计理念完全相反。
Microduck 在头顶装了一颗 VL53L8CX——ST 微电子的飞行时间传感器,输出 8×8 共 64 个深度点,视野 45°×45°,最远 4 米。这不是做壁障的(机器人没有自主导航),而是做”地面检测”和”头部交互”用的。
架构文档里有一句话很关键:
“tofd — the head’s 8×8 depth matrix, on /run/tofd/tof.sock. mediad and robotd read it; it reads no one.”
tofd 是纯发布者。 它只读 I²C 总线上的传感器数据,然后通过 Unix socket 广播出去。它不调用任何其他进程的接口,不参与任何 IPC 协商。这不是功能不足,是有意设计的——一个只发布不订阅的服务,不可能因为调用其他进程而被阻塞。
tofd 的数据流:
VL53L8CX(I²C 总线)
│ tofd 守护进程轮询读取
▼
/run/tofd/tof.sock(Unix socket)
│ 广播 8×8 深度矩阵
├──► mediad:集成到 WebRTC 流,远程查看
└──► robotd:fall detection 辅助,地面高度判断
VL53L8CX 在 Microduck 上的实际能力
VL53L8CX 的 64 个深度点以 8×8 网格排列,每个点覆盖约 5.6° 的视场角。对 Microduck 来说,这些数据主要用在两个场景:
- 头部前方地面高度检测:当鸭子低头时,ToF 能测出前方是否有台阶或悬空——但当前版本的策略并未使用这个信息,属于预留能力
- 交互检测:有人伸手到鸭子面前时,ToF 能感知到深度变化,可用于触发交互行为
从官方文档看,ToF 在当前版本的 Microduck 里定位是”非关键”的——鸭子没有它也能走路。这和 IMU 完全不同:IMU 是 61 维观测空间的固定组成部分,缺少它就构建不了观测向量。
但这种”非关键但可扩展”的设计有它的道理。如果你在复刻时想给鸭子加自主壁障或地形感知,tofd 的纯发布者架构让你不需要修改控制循环,只要 robotd 订阅一个额外的 socket 就行。
摄像头:另一个数据面
IMX219 8 MP 摄像头由 mediad 管理,和传感器走完全不同的路径。它不参与控制循环,不提供观测向量——mediad 的定位是”视频流出口”,不是”传感器”。
一帧 640×480 的 RGB 图像约 921 KB,30fps 下是 27 MB/s。如果走 Unix socket 和 RPC 通道,50Hz 控制循环会被堵死。所以 mediad 单独开 TCP 端口:
- :8080:控制台页面 + PNG 单帧 GET
- :8443:WebRTC 信令
控制循环可以偶尔从 mediad 拉一帧做 pet detection(宠物检测功能),但频率很低,通过 /run/mediad/media.sock 调用 media.frame 请求。
摄像头不参与控制循环,意味着步态不依赖视觉。这是有意为之——双足机器人最可靠的行走不应该依赖有没有光、摄像头有没有对焦。视觉用来做交互层,步态靠本体感受和 IMU。
传感器数据在控制循环中的实际使用
回到 50Hz 的控制循环,看三类传感器数据怎么进入 tick:
每个 tick(20ms)必有:
- 15 个舵机的角度、速度、负载(sync_read)
- IMU 的 roll/pitch/yaw 和加速度(同一笔 sync_read)
每个 tick 可选的(if subscribed):
- ToF 的 8×8 深度矩阵(从 tofd 的 socket 拉取,但非阻塞)
- 摄像头帧(极低频,仅 pet detection 场景)
每秒一次:
- 慢速传感器:舵机电压、温度(registers 144-146)
这里有个微妙的设计点:ToF 和摄像头数据进入控制循环时,没有任何同步保证。 它们的时间戳和 IMU/关节数据的时间戳可能差几毫秒甚至几十毫秒。但这不是问题——因为这些数据本身就不参与高频控制。ToF 用于地面检测时的更新率大约是 15-30 Hz,远低于控制循环,一个 tick 里读到的是”最近的可用数据”而非”当前数据”。
在复刻场景下的传感器集成
如果你在复刻 Microduck 并换用了国产舵机,传感器部分的调整相对可控。
IMU 部分:如果你不重绘 imu_to_dxl 板(比如直接用官方 Robot HAT 的打样文件),BMI088 走 imu_to_dxl v2 的固件逻辑不变。即使换用其他 IMU,只要把输出转成 Dynamixel register block 格式,robotd 的观测构建代码不需要改。
ToF 部分:VL53L8CX 在复刻 BOM 里标价 ¥70,走 I²C 和 HAT 通信。如果你不用原版 HAT,需要确保 imu_to_dxl 自绘板或者单独的传感器板上有 I²C 接口接 ToF。tofd 守护进程本身是一个独立的小程序,可以从官方仓库移植——它做的事情很简单:轮询 I²C 读寄存器,把 8×8 矩阵发布到 Unix socket。
纯发布者模式的借鉴价值:tofd 的设计值得在复刻中保留。给每个传感器一个独立的、只发布不读取的守护进程,可以防止任何一个传感器的 I²C 或 SPI 阻塞影响到主控制循环。这不是 Microduck 独有的思路——ROS2 的 single writer principle 也是类似的道理,但 Microduck 用 Unix socket + NDJSON 做到了比 ROS2 轻得多的实现。
复刻的传感器进度:从 duck.whatled.com 的进度看,IMX219 相机(¥32.8)和 VL53L8CX ToF(¥70)已经列入 BOM 待购清单,imu_to_dxl 自绘板的设计包已就绪、固件协议 6/6 测试通过。传感器层是电控设计中优先级最低但最清晰的一块——不依赖舵机到货,可以在 HAT 板打样的同时并行开发。
传感器融合的架构原则
回头看 Microduck 的传感器设计,几条原则很清晰:
- 时间对齐靠硬件,不靠软件:IMU 挂 Dynamixel 总线而不是走独立 SPI,就是为了和关节数据在同一时刻到达
- 非关键传感器不参与控制循环:ToF 和摄像头的数据不走观测空间,它们是扩展能力不是核心依赖
- 纯发布者模式防止级联阻塞:tofd 只读 I²C 只写 socket,不依赖任何其他进程
- 数据面和控制面分离:视频流走 TCP 端口,不走控制循环的 IPC 通道
这些原则不是 Microduck 独创的,但在一台 25cm、800g、399 美元的开源机器人上做到这个程度,说明团队在设计时没把传感器当作”外设”来对待——每类传感器的集成策略都是根据数据流特性重新设计的。
数据来源:pollen-robotics/microduck 仓库 architecture.md (2026-07-22)、robotd-design.md (2026-08-20)、GitHub README、博世 BMI088 数据手册、duck.whatled.com 复刻进度。
