• 欢迎访问少将全栈,学会感恩,乐于付出,珍惜缘份,成就彼此、推荐使用最新版火狐浏览器和Chrome浏览器访问本网站。
  • 吐槽,投稿,删稿,交个朋友
  • 如果您觉得本站非常有看点,那么赶紧使用Ctrl+D 收藏少将全栈吧

Microduck 的感知系统:ToF 深度传感与 IMU 在 50Hz 控制循环中的协同设计

Build in Public admin 1小时前 3次浏览 已收录 扫描二维码

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 来说,这些数据主要用在两个场景:

  1. 头部前方地面高度检测:当鸭子低头时,ToF 能测出前方是否有台阶或悬空——但当前版本的策略并未使用这个信息,属于预留能力
  2. 交互检测:有人伸手到鸭子面前时,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 的传感器设计,几条原则很清晰:

  1. 时间对齐靠硬件,不靠软件:IMU 挂 Dynamixel 总线而不是走独立 SPI,就是为了和关节数据在同一时刻到达
  2. 非关键传感器不参与控制循环:ToF 和摄像头的数据不走观测空间,它们是扩展能力不是核心依赖
  3. 纯发布者模式防止级联阻塞:tofd 只读 I²C 只写 socket,不依赖任何其他进程
  4. 数据面和控制面分离:视频流走 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 复刻进度。

喜欢 (0)
[🍬谢谢你请我吃糖果🍬🍬~]
分享 (0)
关于作者:
少将,关注Web全栈开发、项目管理,持续不断的学习、努力成为一个更棒的开发,做最好的自己,让世界因你不同。