Skip to content

has_sync 到端到端证据:相机与 IMU 时间同步 QA

has_sync=True 很重要,但它只说明某一段同步链路建立了。它不能自动证明相机与 IMU 的消息时间戳已经落在同一时间轴,也不能证明多相机帧属于同一次触发。

要把时间同步从“看起来正常”变成可发布的工程能力,需要分层验证。

五层同步问题

层次要回答的问题典型证据
链路PPS / 串口消息是否持续到达link state、消息率、丢包
时钟offset 是否收敛且稳定raw/smoothed offset、jitter
触发多相机是否属于同一触发trigger seq、bundle complete
时间域相机与 IMU stamp 是否同域stamp domain、转换路径
运动一致性两类传感器是否在物理上对齐光流/角速度相关性、激励条件

任何一层通过,都不能替代下一层。

1. 在线与离线必须复用同一个分析器

最容易出现的维护问题是:在线节点用一套阈值,离线脚本又实现一套,最后同一份数据得到两个结论。

更好的结构是:

text
rosbag / JSONL ─┐
                ├─> shared analyzers ─> summary model
ROS subscribers ┘                         ├─ summary.json
                                          ├─ report.html
                                          └─ junit.xml

在线节点只负责收集滑动窗口,离线 CLI 只负责读取数据,两者把同一种事件模型交给共享 analyzer。

2. 不要混用 receipt time 与 header stamp

ROS 消息至少存在两类常见时间:

  • header.stamp:消息声明的事件时间;
  • receipt time:本机收到回调的时间。

receipt time 会包含调度、传输和队列延迟。它可以衡量链路覆盖与消息新鲜度,但不能直接当作传感器物理 offset。

相机还可能有 driver PTS、group PTS、trigger time;IMU 可能有 PX4 sample time、同步后的 realtime 或 ROS publish time。QA 配置必须明确每个指标使用哪一个源。

3. 多相机同步看 bundle,不只看平均频率

六路相机都在 20 Hz,不等于每个 bundle 都完整。需要按 sync_seqtrigger_seq 聚合,统计:

  • bundle complete ratio;
  • 同组最大 skew;
  • sequence gap;
  • 重复帧与迟到帧;
  • 滑动窗口边缘的半截 bundle。

窗口起止位置天然会截断部分 bundle,因此边缘桶应显式忽略或单独标记,不能把它们误算成真实丢帧。

4. 运动相关性需要足够激励

用图像光流与 gyro 估计 camera-IMU offset 时,如果设备静止,视觉变化和角速度都接近噪声底,算法即使输出一个数也不可信。

测试应包含明确的旋转或运动激励,并设置最低能量门限:激励不足就输出 INSUFFICIENT_EXCITATION,而不是给出伪精确 offset。

5. QA 输出要能进入发布门禁

建议同时输出三种形式:

  • summary.json:给自动化系统和后续聚合;
  • report.html:给工程师快速阅读;
  • junit.xml:直接进入 CI 测试结果。

一个典型 gate 可以包含:

text
link_up == true
offset_jitter_p99 < threshold
bundle_complete_ratio >= threshold
camera_skew_p99 < threshold
imu_rate within expected range
time_domain_consistent == true

阈值应来自硬件和算法需求,而不是为了让当前数据通过。

最终验收边界

时间同步 QA 至少要区分:

  • 代码单测通过;
  • 离线样例通过;
  • 板端在线窗口通过;
  • 动态激励下物理 offset 可估;
  • 正式 release/service 已部署。

把这些层次分开,才能避免用“节点 active”或“has_sync 为真”替代真正的端到端同步证据。