ARTICLE DETAIL

建站实战干货

来自一线的建站与推广经验沉淀,每一条都经过真实交付验证。

OOMWOO MCU I/O 固件与 ROS 2 桥接:无硬件环境下的端到端 CPU↔MCU 安全链路验证

2026/9/24 3:47:39 拓冰建站 浏览量
OOMWOO MCU I/O 固件与 ROS 2 桥接:无硬件环境下的端到端 CPU↔MCU 安全链路验证 智能硬件机器人嵌入式物联网【免费下载链接】oomwooOpen-source vacuum robot cleaner项目地址https://gitcode.com/gh_mirrors/oo/oomwoo点击查看免费下载OOMWOO 是一台开源的 ROS2 扫地机器人架构说明 定义其 CPU/MCU 双处理器拆分CPU 负责 ROS2/SLAM/Nav2STM32G473 MCU 独占电机、编码器、传感器与硬安全。本文聚焦 Creative-Dhanush 的 MCU I/O 固件贡献它用一台笔记本把CPU↔MCU 链路端到端跑通——ROS 2 栈驱动真实的 MCU 安全逻辑、走真实的二进制线格式且当 ROS 2 一侧被 kill 时MCU 会自行刹停电机。读完本文你将掌握如何在纯软件环境复现这套演示、固件五个核心翻译单元各自承担什么职责、54 项测试与差分模糊测试如何证明线格式正确以及MCU 独占安全、刻意保持简单这一安全立场如何在源码层面落地。本文主体内容来自 contributions/mcu-io-firmware/Creative-Dhanush/README.md并辅以同仓库的 CPU/MCU 串口契约草案、ROS 2 映射草案 与参考编解码实现 oomwoo_mcu_frame.py 作纵深佐证。贡献模型两个仓库各自独立 CI按本模块的贡献模型该实现拆成两个仓库MCU 侧与 CPU 侧各自持有 CI仓库职责CIoomwoo-io-firmwareMCU 侧帧编解码frame codec、流式解码器、安全状态机、链路层以及一个 MCU 模拟器firmware CIoomwoo-mcu-bridgeCPU 侧oomwoo_mcu_bridgeROS 2 节点由 ros2_mapping.md 起草并命名bridge CI开始阅读其余内容前请先明确一个边界已被证明的是——线格式相对一个独立实现是正确的、解析器能扛住损坏与分片输入、安全策略在每种指定条件下行为正确——这些全部发生在笔记本上尚未被证明的是——与真实芯片相关的任何事没有实测反应时间、没有中断优先级、没有证据表明一个挂死的 Arduino 级任务无法击穿切断逻辑。那是 模块里程碑 6需要一块 Nucleo。这是安全系统脚下的地基而不是安全系统本身。眼见为实在笔记本上让整条链路跑起来运行前提Linux模拟器依赖openpty与 ROS 2 Jazzy。把两个仓库克隆到相邻目录后# MCU 侧 —— 把安全核心编译成宿主二进制跑在伪终端上 git clone https://github.com/Creative-Dhanush/oomwoo-io-firmware pip install -U platformio (cd oomwoo-io-firmware pio run -e native_sim) # CPU 侧 —— ROS 2 桥接节点 git clone https://github.com/Creative-Dhanush/oomwoo-mcu-bridge cd oomwoo-mcu-bridge colcon build source install/setup.bash ros2 launch oomwoo_mcu_bridge demo.launch.py \ sim_binary:$PWD/../oomwoo-io-firmware/.pio/build/native_sim/programlaunch 文件会启动模拟器、创建 pty并驱动桥接节点走完configure→activate因此稳定下来时心跳已在运行、遥测已在流动。用ros2 lifecycle get /oomwoo_mcu_bridge应看到active。驱动它、破坏它看谁刹停机器人操作现象ros2 run teleop_twist_keyboard teleop_twist_keyboard轮子转动/joint_states与/odom前进向模拟器 stdin 输入cliff left on/oomwoo/io/cliff→ 1轮子停止/cmd_vel无法覆盖它输入cliff left off仍然停止——cliff 闩锁不会自清除ros2 service call /oomwoo/io/clear_faults std_srvs/srv/Trigger故障释放运动恢复kill 桥接节点心跳停止 →MCU 自行刹停电机没有任何 ROS 2 侧指令要求它这么做最后一行就是设计本身而不是兜底方案。其契约依据见 CPU/MCU 串口契约草案 的时序规则CPU 以 20–50 Hz 发布HEARTBEATMCU 在错过心跳后 150 ms 硬停契约失败行为表也明确规定CPU 心跳超时 → 停止驱动与清洁电机发出CPU_HEARTBEAT_TIMEOUT。此刻实际在运行的拓扑Nav2 / recovery / jobs ow_sim_mcu (今天一台笔记本) │ real I/O board (将来协议不变) ▼ ▲ oomwoo_mcu_bridge ──── OW binary frames, CRC-16 ──────┘ │ (现在是 pty将来是 UART) ▼ /joint_states /odom /battery_state /oomwoo/io/* /diagnostics注意ow_sim_mcu上方的real I/O board (later, unchanged protocol)——设计意图是模拟器与真实板卡之间协议不变桥接节点无需改动即可对接真实硬件。为什么说它是 drop-in 替换模拟器是 oomwoo-install 中换行分隔 JSON 桩ubuntu/tools/oomwoo_sim_mcu_serial.py的直接替代品——同样的--link、--period、--battery-mv参数——但它说的是真正的契约。而且它不是固件的模型它运行的就是固件本身。ow_frame/ow_stream_decoder/ow_safety_core这三个翻译单元与交叉编译到 STM32G473 的是同一份代码。只有一份实现所以模拟器与目标板永远不会漂移。已实现的模块逐一看模块用途ow_frame.{h,cpp}CRC-16/CCITT-FALSE、小端辅助函数、全部 12 种已定义消息类型的编解码——逐字节构建绝不通过 struct 做memcpy从而绕开 C/struct.pack的结构体填充padding不一致问题ow_stream_decoder.{h,cpp}固定缓冲流式解码器跨多次读取缓冲不完整帧损坏后逐字节重新同步ow_safety_core.{h,cpp} 设计文档安全状态机——心跳超时、设定点过期、bumper/cliff/wheel-drop/过流/e-stop、闩锁故障ow_link.{h,cpp}把上述三者绑成一个可用的 MCU字节进 → 策略 → 成帧字节出带出站排序。不拥有任何传输这正是同一份代码既能零 I/O 单元测试、又能跑在 pty 上、还能交叉编译到目标板的原因ow_telemetry.{h,cpp}按 ros2_mapping.md 要求的 50–100 Hz 周期性FAST_TELEMETRYow_sim_mcu跑在伪终端上的 MCU支持 stdin 故障注入oomwoo_mcu_bridgerclpy lifecycle 节点9 个订阅 9 个发布接口、四种规定的 lifecycle 状态以及仲裁钳位clamp关键设计桥接节点直接 import 参考编解码器桥接节点原封不动地 importxbattlax 的oomwoo_mcu_frame.py而不是重新实现一份。这样一来链路两端共享同一个线格式定义而不是对契约的两次独立解读。该参考编解码器正是 CPU/MCU 串口契约草案 所述给固件、ROS2 与测试工作一个共享可执行参考的实现其帧头布局为offset size field 0 2 magic: ASCII OW 2 1 protocol version: 1 3 1 flags 4 2 sequence number 6 2 message type 8 2 payload length 10 N payload 10N 2 CRC-16/CCITT-FALSE over header payloadmagic 字节计入 CRC解码器必须拒绝版本错误、长度不可能或 CRC 错误的帧流式解码器可以把噪声丢弃到下一个OWmagic 为止。而ow_frame在 C 侧逐字节构建帧、从不通过结构体memcpy正是为了规避 C 结构体填充与 Pythonstruct.pack的 padding 不一致——这是两端共享同一份格式定义时必须处理的实际工程问题。证据CI 里 2 分钟跑完的验证矩阵以下所有检查都在每次 push 时的 CI 中运行约 2 分钟跑在一台非作者所有的机器上检查结果帧编解码、流式解码器、安全核心、链路回环pio test -e nativeASanUBSan54 项测试——10 / 9 / 15 / 20金样本帧向量从上游参考再生成字节级一致pass差分模糊测试流式解码器 vs Python 参考2000 例0 失配pty 上的模拟器每个字节都由上游参考解码并重新编码6 例字节精确桥接节点组帧单元测试10桥接 ↔ 模拟器端到端只断言 ROS 2 话题5pio run -e nucleo_g474re交叉编译pass两项最不该被伪造的检查线格式检查以上游参考实现为 oracle。模拟器发出的每一帧都被 vendored 的上游参考解码、重新编码并要求与原字节完全一致。说的是真实协议这件事是被检验的而不是被断言的。回环测试套件全程走线。与安全核心测试直接把已解码帧交给SafetyCore不同test/test_link里的每个测试都以字节进入、以字节离开——因此组帧、CRC、排序或载荷打包的任何缺陷都会让测试失败。桥接节点 CI 日志原文逐字/cmd_vel moved the wheels 0.000 - 6.743 rad, odom x0.236 m cliff latched; /cmd_vel could not override it and the sensor clearing did not release it /oomwoo/io/clear_faults released the latch and motion resumed heartbeat stopped on deactivate and the MCU stopped the wheels by itself 5/5 passed这与上面演示表的每一行一一对应/cmd_vel驱动轮子、cliff 闩锁无法被覆盖、clear_faults释放闩锁、deactivate 后 MCU 自行刹停。立场MCU 拥有的安全留在 MCU而且刻意保持简单这一节是该实现的架构宣言可逐一在源码结构中找到印证安全核心只会在故障时停止执行器。它不后退、不扫描、不重规划、不决定机器人下一步去哪。导航、建图以及一切需要完整上下文的工作都留在 CPU 上这正是 #49 讨论中 kaiaai 问过的拆分——在这里通过核心没有任何办法命令运动只能扣住运动来强制落实。闩锁故障不自清除。Cliff、wheel-drop 与 e-stop 只在显式CLEAR_LATCHED_FAULT后释放。一条悬崖传感器一闪就立即恢复行驶的机器人正是这个设计排除的失败模式。wheel-drop 是唯一刻意的例外——它随轮子重新触地而清除与契约的字面措辞一致。对应消息见契约最小消息目录0x0003 CLEAR_LATCHED_FAULTu16 fault_mask与0x8002 SAFETY_EVENTu16 event, u8 active, u16 detail。过流只停受影响的电机并在SAFETY_EVENT.detail中报告是哪一台而不是一刀切全停。契约中事件 7BRUSH_OVERCURRENT停止受影响的刷、detail 带刷 ID与事件 8FAN_OVERCURRENT停风扇、驱动交由 MCU 策略正是这一行为。每个入口点都把当前时间作为参数传入从不读取时钟——所以一个 150 ms 的超时可以在恰好 149 ms 和 151 ms 处确定性测试无需任何 sleep。这与契约MCU 硬停 150 ms草案一致且时间作为参数的设计让边界测试不依赖调度器。核心内无堆、无异常、无 Arduino 头文件。operator new在编译期被删除。同一份源码既能以普通宿主 C17 构建也能构建为目标固件。安全状态如何重建SAFETY_STATE与兼容字段契约在实现两端之后新增了0x8005 SAFETY_STATEu32 timestamp_ms, u16 active_flags, u16 latched_flags作为权威的周期性安全快照安全事件码 N 映射到位 N−1当前 1–10 号事件因此恰好塞进一个u16。旧的FAST_TELEMETRY.safety_latched_flags单字节保留为低 8 位兼容字段但新桥接节点必须用SAFETY_STATE重建完整的 active/latched 状态未知高位必须保留用于诊断并视为抑制运动直到其含义被明确。oomwoo_mcu_frame.py中safety_event_flag()返回1 (event - 1)正是这条位映射的可执行表达。启动进展与尚未开始的部分对照 模块里程碑#里程碑状态1在 G473 开发板上 Blink SWD 串口回显未开始——需要硬件2CPU 串口链路组帧 健康/看门狗握手回环测试宿主端完成3一个驱动电机闭环未开始4全部执行器未开始5全部传感器未开始6ISR 级安全、IWDG、实测最坏反应时间未开始——策略已存在ISR 与定时工作尚未做7充电监管未开始8与 CPU 或模拟 MCU 串口工具联调模拟 MCU 一半已完成ROS 2 桥接节点端到端驱动它里程碑 3–7 仍开放、无人认领。这里也没有任何东西排斥不同的固件框架——线契约就是接口所以一个能说这种协议的 Zephyr MCU 可以直接搭配此桥接节点无需改动。未实现事项直说没有 STM32 HAL 或板级 bring-up。以上全部是可在宿主上测试的逻辑。没有电机 PWM、电机电源使能 GPIO、充电或 IWDG。安全核心发出的是意图stop、SAFETY_EVENT、NACK由调用方把它们接到硬件上。任何电机负载都不应接在这里。没有实测最坏反应时间。模拟器时序是抢占式调度下的笔记本时序说明不了真实器件。编码器与轮距常量是占位符并在源码中如实标注因为 SPEC.md 尚未定齿轮箱减速比与编码器分辨率。模拟器的里程计距离无意义方向、符号以及安全说停就停这个事实有意义。POWER_TELEMETRY与MCU_DIAGNOSTIC在契约中没有载荷布局这正是/battery_state的充电字段、/oomwoo/io/mcu_status与四个/oomwoo/dock_ir/*话题发不出来的原因。这些话题选择不发布而不是塞入看似合理的值——在标准 ROS 2 话题上给一个编造的battery.percentage比缺失一个更糟。参考实现里这两个消息在 conformance 清单中以payload_status: open保留与此一致。同时实现两端挖出的契约缺口同时按同一份文档实现 CPU 侧与 MCU 侧产出了这些有价值的发现接口契约现已全部解决同时保留既有 protocol-v1 帧完整安全快照SAFETY_STATE携带 16 位 active 与 latched 掩码。旧FAST_TELEMETRY.safety_latched_flags单字节保留为兼容字段事件 9、10 在权威周期快照中呈现。迟到的 CPU 接入IDENTIFY_REQUEST0x0004空载荷让 CPU 在每次连接/重连后请求一份全新的MCU_HELLO无需武装输出或刷新心跳。契约明确请求不武装输出、不刷新心跳、不重放此前命令MCU 在启动时仍自发发出MCU_HELLO并在每个合法 identify 请求后重新发出。拆分的 magic参考StreamDecoder现在保留结尾孤立的一个O并有回归测试证明当W在下一次读取到达时能完成整帧。这与 oomwoo_mcu_frame.py 中StreamDecoder.feed()的逻辑吻合缓冲以MAGIC首字节结尾时保留该字节等待下一块数据补齐。实现方仍需采用两个新消息 ID 后才能移除各自的临时 workaround。未定义的POWER_TELEMETRY、MCU_DIAGNOSTIC与 dock-IR 载荷仍是独立的契约决策与板级 bring-up 测量绑定。关于CPU 心跳超时维护者在 #49 中答复约为5 分钟用于 CPU 启动时间。这是与稳态心跳超时不同的定时器——后者契约仍标记为草稿100、150 还是 250 ms?——因此稳态值是一个Config字段默认 150 ms而不是硬编码常量。启动通过结构而非长超时处理启动或重连后执行器保持禁用直到一份新鲜的HEARTBEAT且一份新鲜的DRIVE_SETPOINT都到达——所以无论数值是多少一个慢启动的 CPU 都无法产生运动。一个待决的小问题MCU 当前在启动约 150 ms 后就会报告心跳超时而此时 Linux 还在起来。由于运动已被门控而无害——但如果意图是直到 CPU 说过话之前保持安静那是一个小改动值得决定。深入仓库继续验证契约与消息目录全文CPU/MCU 串口契约草案ROS 2 话题/服务映射、QoS 与生命周期行为ROS 2 映射草案——桥接节点的 9 订阅/9 发布、四种 lifecycle 状态与仲裁钳位均由此定义参考编解码器oomwoo_mcu_frame.pyCRC-16/CCITT-FALSE、12 消息的 pack/unpack、StreamDecoder一致性工具包conformance 目录protocol_v1.json、金样本向量、C11/C17 验证器ROS 2 硬件桥接草案SOFTWARE_INTERFACES.md §Hardware Bridge Draft系统级 CPU/MCU 拆分与安全理由ARCHITECTURE.md §5.4这套实现的完整故事可以概括为一句话线格式对、解析器扛打、安全策略在每种规定条件下行为正确——而且这一切都在一块真实 MCU 到位之前就已在笔记本上被端到端证明。剩下的是把这份证明搬到真实芯片上那正是里程碑 6 与后续板级工作要做的事。赞分享智能硬件机器人嵌入式物联网【免费下载链接】oomwooOpen-source vacuum robot cleaner项目地址https://gitcode.com/gh_mirrors/oo/oomwoo点击查看免费下载相关推荐OOMWOO I/O Board 软件接口实战指南CPU↔MCU 串行契约、安全机制与 ROS2 桥接设计OOMWOO I/O Board 软件接口实战指南CPU↔MCU 串行契约、安全机制与 ROS2 桥接设计 OOMWOO 开源扫地机器人通过一张定制 I/O智能硬件机器人嵌入式物联网OOMWOO CPU/MCU 串行接口契约全解ROS2 桥与 STM32 固件的安全集成规范与验证方案OOMWOO CPU/MCU 串行接口契约全解ROS2 桥与 STM32 固件的安全集成规范与验证方案 OOMWOO 是一个开源真空扫地机器人项目本文聚焦其智能硬件机器人嵌入式物联网OOMWOO 开箱验证计划从协议测试到整机带载的 CPU/MCU 桥接七阶段排雷手册OOMWOO 开箱验证计划从协议测试到整机带载的 CPU/MCU 桥接七阶段排雷手册 导读 本文以 OOMWOO开源扫地机器人项目中 xbattlax 的智能硬件机器人嵌入式物联网创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考