机器人在现场偶尔导航超时,回到实验室却怎么也复现不了。开发者通常会加几条日志,再跑一次任务。等真正需要分析时才发现,录包里没有相机时间戳、TF、诊断状态或控制命令,留下的只有一行“action timeout”。
rosbag2 能保存一次运行中的消息,但它不会自动让实验变得确定。要复现故障,必须提前定义录哪些话题、使用哪种 QoS、回放时是否使用仿真时间,以及哪些硬件输入需要替换成回放数据。回放的目标是重建当时的输入和状态,不是把视频重新播放一遍。
先写出你要证明的假设
“导航超时”不是一个根因。可能是感知结果过期,TF 查询外推失败,规划器没有路径,控制命令被 watchdog 丢弃,也可能是 CPU 被录包和推理抢走。录包前先写一个可检验的假设,例如“超时前 200 ms 内,局部地图没有更新”或“Action 已取消,但控制器仍在执行上一段轨迹”。
假设决定需要哪些话题。视觉问题要有原始图像和检测结果,控制问题要有命令、反馈和安全状态,调度问题还要配 tracing 或系统指标。所有东西都录下来会迅速耗尽磁盘,也会带来隐私风险。
录包命令只是起点
可以先用命令行建立一个最小包:
1 | ros2 bag record \ |
实际话题要按系统替换。录制前检查 QoS,尤其是传感器常用的 best-effort 配置。订阅端 QoS 不兼容时,包里可能没有数据,而命令本身不一定明显报错。对于大图像和点云,可先录压缩或低分辨率副本,但要记录这会改变什么证据。
QoS 兼容关系可以先用发布订阅对照实验复现。涉及 /tf 时,还要按TF2 的坐标系与时间查询确认静态变换、动态变换和查询时刻都在包里。
时间必须统一
回放时使用 --clock,并确认所有相关节点设置了 use_sim_time:
1 | ros2 bag play <bag_directory> --clock |
一个节点用墙上时间、另一个节点用仿真时间,回放出来的消息年龄就没有意义。录包中的时间戳也要区分传感器采样时间、节点接收时间和发布完成时间。只保留发布时刻,无法判断问题在传输还是计算。
回放时不要一次改很多东西
第一轮尽量原样回放,确认故障现象仍然出现。第二轮只替换一个变量,例如把真实相机替成固定图像、关闭录包、降低模型负载或使用不同的 TF。每轮都输出同样的指标:Action 完成时间、检测结果年龄、控制命令间隔、规划器状态和安全触发原因。
如果回放无法复现,也不代表原故障不存在。可能是硬件中断、温度、无线网络或未录制的外部输入没有被重建。此时要把“未能复现”和“已排除的变量”写进报告,而不是把回放结果当成真机结论。
把包和环境一起交付
一个可交接的故障包至少应包含:
| 项目 | 作用 |
|---|---|
ros2 bag info 输出 |
说明话题、时间范围、存储格式和消息数量 |
| 参数与启动命令 | 还原节点配置和启动顺序 |
| Git commit/容器摘要 | 固定代码和依赖版本 |
| 设备与负载信息 | 说明 CPU、GPU、温度和功耗条件 |
| 期望现象 | 定义“复现成功”是什么 |
| 隐私和保留期限 | 限制图像、语音或人员信息的传播 |
回放系统还可以和 ROS 2 tracing、结构化日志结合,把一次超时还原成消息时间线。图像能告诉你目标在哪里,时间线才能告诉你为什么控制器没有及时收到它。
故障包交给测试或客户之前,可以按验收报告的证据分层再检查一遍:哪些结论来自回放,哪些来自台架,哪些已经有真机记录。回放复现成功也不能自动升级成真机安全结论。
参考资料
证据边界:回放只能重建被录下来的输入和状态,不能自动重建硬件中断、温度、网络或未记录的外部因素。本文没有声称某次超时已经被复现;实际报告必须说明录包覆盖范围和剩余未知量。