ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

Microduck的50Hz控制环:robotd如何用一条串口总线驱动15个舵机

Microduck的50Hz控制环:robotd如何用一条串口总线驱动15个舵机 02-50Hz控制环robotd如何用一条串口总线驱动15个舵机引子机器人的心跳大家好我是黒漂技术佬。上一篇我们解剖了 microduck 的整体架构认识了那个 50Hz 的控制核心 robotd。今天这篇我们要钻进 robotd 内部看看它的核心——控制环control loop——到底是怎么运转的。先理解一个物理事实机器人不会自己待着不动。重力时刻在拉着它任何一个关节的角度偏差都会累积成摔倒。所以机器人的控制必须是一个持续不断的闭环读传感器 → 算动作 → 发指令 → 再读传感器……如此往复一刻不能停。这个循环的每一次迭代就叫一个控制周期tick。microduck 的控制周期是20 毫秒50Hz。20 毫秒意味着什么你眨一次眼大约 100~150 毫秒也就是说在人类眨一次眼的时间里机器人已经完成了 5~7 次完整的感知-决策-执行。这个速度对于双足平衡是够用但不宽裕的——这决定了 robotd 里每一个函数都要为这 20ms 服务。说句题外话人形机器人的控制频率通常更高MIT 的 Cheetah 能跑到 1kHz 以上但 microduck 用 50Hz 就够——因为它是 25cm 的小个子惯性小对控制频率的要求天然低。控制频率不是越高越好而是够用就好因为频率越高每周期可用的计算预算越少。一、先看总线15 个舵机怎么共享一条串口microduck 用的舵机是Dynamixel系列——这几乎是双足小机器人界的标准件。Dynamixel 是韩国 ROBOTIS 公司做的智能串行总线舵机每个舵机内置 MCU、驱动、编码器可以通过一条总线菊花链串联。关键信息在架构文档里15 个 Dynamixel 舵机 1 个 IMU共享同一路 UART一条串行总线。控制环独占这条总线。┌──────────────────────────────────────────────┐ │ robotd │ │ 控制环50Hz 独占 │ └──────────────────────┬───────────────────────┘ │ 一根 TX/RX 串口线 ▼ ┌──────────┐ ┌──────────┐ ┌──────────┐ ┌──────┐ │ Dynamixel │ │ Dynamixel │ │ Dynamixel │ … │ IMU │ │ #1 │ │ #2 │ │ #3 │ │ │ └──────────┘ └──────────┘ └──────────┘ └──────┘为什么 15 个舵机能共用一条 UART因为 Dynamixel 是半双工总线协议每个舵机有唯一 ID主机发指令帧时带上目标 ID只有匹配的舵机响应。整条总线上的设备分时共享一根线——发送、接收轮流来。这里就引出了嵌入式实时控制里一个非常经典的总线时序问题50Hz 控制环 × 15 个舵机 每个周期只有 20ms要完成 15 个舵机的读 15 个舵机的写。读查询每个舵机当前角度比如用Read指令写下发每个舵机的目标位置/速度/力矩Write指令。一个 Dynamixel 帧大约几十字节在 1Mbps 波特率下传一个帧大约零点几毫秒。但串口是半双工的一次只能传一个方向所以 30 个操作按顺序排下来一个周期内总线就占用得七七八八了。这是控制环设计中必须精打细算的预算项。有的机器人会为每条腿配一路串口来提升带宽microduck 只用了 1 路——这又是够用就好的哲学。代价是控制环的时序必须把总线带宽算进去这反而让它的设计更值得学习。二、控制环内部一个 20ms 的循环里发生了什么架构文档里 robotd 的职责清单是motor control电机控制、kinematics运动学、odometry里程计、gait policies步态策略、sensor loop传感器循环、safety安全。我们把它画成一个 50Hz 的流水线一个 tick 大致长这样┌──────────────────── 一个控制周期20ms────────────────────┐ │ │ │ ① 读传感器 ──► ② 状态估计 ──► ③ 策略推理 ──► ④ 安全校验 ──► ⑤ 下发指令 │ │ (15舵机角度) (更新里程计/ (神经网络算出 (检查关节限位、 (写Dynamixel │ │ IMU姿态) 姿态等) 目标动作) 温度、摔倒) 总线) │ │ │ │ ⑥ 计时等待 —— 如果提前完成sleep 到周期边界 │ │ │ └──────────────────────────────────────────────────────────┘几个细节值得展开2.1 里程计odometry不是独立服务注意架构文档里这句话odometry 是循环内的一个 struct不是独立服务。它的输入恰好是循环已经读取的样本。很多机器人系统会把里程计做成一个独立的模块或进程但 microduck 选择把它塞进控制环内部。为什么因为里程计需要的是当前周期刚读到的舵机角度而不是可能延迟了几毫秒的别人算好的结果。把状态估计放进控制环里可以保证它读到的一定是最新鲜的样本且不需要跨进程通信的开销。这是嵌入式实时系统的经典取舍与周期强耦合的计算就应该住在周期里。2.2 策略推理神经网络在 50Hz 下跑microduck 的步态不是写死的正弦曲线而是神经网络策略在仿真里用强化学习训练出来的这个我们第 05 篇细讲。策略模型的输入是观察observation——包含关节角度、IMU 姿态、上一时刻动作等输出是动作action——通常是目标关节位置或力矩。在 RK3566四核 A55无 GPU 参与上跑一个 ONNX 格式的小型 MLP 网络单次推理大约几毫秒——完全装得进 20ms 的预算。这也是强化学习落地嵌入式的前提模型必须小到端侧推理不吃掉整个控制周期。2.3 安全层在意图和电机之间上一篇提到过robotd 收到的是各种客户端发来的intent意图比如站起来“往前走”。安全层就在意图和电机指令之间客户端意图 ──► 安全层仲裁 ──► 电机指令 │ ├── 摔倒检测姿态异常 ├── 关节限位角度超界 ├── 温度限制舵机过热 └── 安全姿态safe pose逻辑任何一个检查不过意图就会被降级或拒绝。没有任何客户端能绕过这一层——本地手柄不行远程 WebRTC 不行脚本不行。这在机器人领域叫权威仲裁本地客户端可以抢占远程客户端但谁都不能跳过安全。三、实时性的三个铁律微控制器社区有个老梗“实时系统里没有’等一下’只有’刚好’和’来不及’。”robotd 的设计里藏着三条保证实时性的铁律值得我们每个做嵌入式的人抄作业。铁律一控制环绝不阻塞架构文档原话控制环绝不阻塞于其他服务跨服务读取均为 last-value-wins 缓存非同步 RPC。翻译成人话robotd 需要其他服务的数据比如 mediad 算出来的球的位置时不调用阻塞式 RPC 去等结果而是读一个最新值缓存——拿到什么算什么拿不到就用上一次的如果一个服务响应慢robotd 不会等它直接带着旧值继续跑。为什么要这么极端因为在 20ms 的周期里一次网络阻塞可能就是 5~10ms 的延迟——控制环等不起。等一次可能没事累积几次机器人就摔了。铁律二deadman/heartbeat 心跳机制安全章节里有一条deadman/heartbeatRTT 超阈值自动停止。如果你连着手机遥控鸭子但手机和应用之间的链路延迟爆炸了——机器人必须能察觉客户端失联然后自动进入安全姿态比如停住、坐稳而不是在等一个永远不会来的指令。实现上通常是一个看门狗式心跳客户端定期发心跳包robotd 如果超过 N 个周期没收到就判定链路失效触发安全停止。这跟我们做无人售货柜设备与服务器的断线重连逻辑异曲同工只不过机器人这边断线后果更严重——是物理性的摔倒。铁律三每个状态只有一个写者架构文档的四条不变式invariants里有一条单写者每状态single-writer per state。任何一个共享状态关节角度、机器人姿态、任务状态在任意时刻只能有一个进程/模块负责写入。多写者必然带来竞态和不确定性——在实时系统里竞态不是 bug是事故。这和分布式系统的单一权威思想一脉相承在 robotd 内部体现为机器人状态只由控制环更新其他模块只读。四、可观测性实时系统怎么看病一个 50Hz 的系统出了问题往往一闪而过——你没法暂停它来调试。所以 robotd 对可观测性的重视是刻进骨子里的手段说明结构化日志各服务 stderr → journaldsystemd 日志首行统一格式WARN starting service... exe...健康状态接口robotd 暴露robot.health一个命令/一次调用就能看全机健康robotctl health命令行一键体检非零退出码可以直接做脚本门控robotctl version报告四维版本信息系统/安装/运行/回滚判断状态分歧“能不能一命令看出所有东西的状态”——这是判断一个嵌入式系统工程成熟度最直观的标尺。很多项目代码写得花团锦簇可现场排障时连现在跑的是哪个版本、哪个服务活着都查不清楚那就是可观测性欠债。microduck 在这点上是个模范生。五、我们能学到什么这一篇的技术点落到我们自己的项目上可以提炼成四条可迁移经验控制频率 需求驱动不是越大越好。先算清楚物理系统的惯性时间常数再定频率频率定下来每个周期能用的计算预算就定了所有优化都要在这个预算里做。与周期强耦合的计算住进周期里。里程计、状态估计这种必须用最新样本的模块别拆成独立进程放循环里最稳。安全执行权要收敛。在安全关键系统里唯一能动手的模块必须是受控的、可审计的其他一切模块只能提建议发意图。这是 robotd 整个架构的魂。实时系统必须自带心跳和看门狗。不管是机器人还是设备端凡是物理后果严重的链路都要有超时即停的兜底。小结robotd 的 50Hz 控制环本质上是一个**在 20ms 预算里完成感知-决策-执行闭环的工程**。它的精彩之处不在某一行代码而在于每一个设计决策都服务于同一个目标让这个 20ms 的循环稳定、安全、可观测地永远跑下去。15 个舵机 IMU 挤在一条 UART 上 → 逼出了对总线时序的精打细算神经网络策略跑在 50Hz → 逼出了模型必须小到装得进预算的约束多客户端控制 → 逼出了 intent 安全层的权威仲裁架构实时性要求 → 逼出了绝不阻塞 last-value-wins 单写者三条铁律。资源受限不是缺陷而是设计的催化剂。这句话在 microduck 身上体现得淋漓尽致。下一篇我们从 robotd 走出来看看它周围那 6 个守护进程是怎么通过 Unix socket 上的 JSON-RPC 协作成一个微服务生态的。我是黒漂技术佬咱们下篇见。
返回列表