返回专辑
·Johan·3 分钟阅读

图像管线 QoS:最新帧优先还是无损优先

视觉链路默认 sensor data 语义;延迟与丢帧分列度量,证明瓶颈在队列还是算法。

图像管线 QoS:最新帧优先还是无损优先

1. 检测「很准」但总是撞——你在追旧帧

相机 30 Hz、检测 10 Hz、跟踪再叠一层,全程 Reliable + depth 10。端到端延迟堆到 800 ms,控制器以为目标在前方 0.8 m,实际已偏到侧向。图像管线必须显式选:最新帧优先(在线感知)还是无损优先(离线标定采集)——两种目标互斥,一套 QoS 假装兼顾会两头做差。RViz 订阅常用 Reliable,与在线 Best Effort 发布不兼容时,表现是「仿真有图、车上无图」,排错方向应在 QoS 而非相机驱动。

2. ROS 2 默认剖面

sensor_data 语义:BEST_EFFORT + KEEP_LAST + depth 小(常 1)。适合相机 → 检测 → 控制。

python
from rclpy.qos import qos_profile_sensor_data

self.create_subscription(
  Image, '/camera/image_raw', self.cb, qos_profile_sensor_data)

发布侧对齐:

python
self.create_publisher(Image, '/camera/image_raw', qos_profile_sensor_data)

订阅与发布 QoS 不兼容时,无数据且无报错——先 ros2 topic info -v /camera/image_raw 看 reliability 与 depth。

3. 何时用 Reliable

标定采集、离线建图、需要每一帧进 bag 时:RELIABLE + 较大 depth,接受带宽与延迟换不丢帧。在线控制与 Reliable 大图混用是常见事故源——任务级剖面,不是全局默认。

场景ReliabilityDepth
在线检测/跟踪BEST_EFFORT1–5
标定/离线 bagRELIABLE10+
可视化(rqt)常 RELIABLE按需

4. 度量:分列延迟与丢帧

bash
ros2 topic hz /camera/image_raw
ros2 topic delay /camera/image_raw   # 若可用,或用自写 stamp 差

记录三项:发布 hz端到端延迟(header.stamp → 结果 stamp)、丢帧/跳帧计数。优化前先证明延迟来自重传/排队,而不是模型 FLOPs——否则在旧帧上加速模型无意义。延迟预算应写进控制需求:若闭环 50 ms,视觉链路占用不应超过其三分之一,否则先砍分辨率而非换更大 backbone。

5. image_transport 与压缩

大图先用 image_transport 协商 raw/compressed/theora:

bash
ros2 run image_transport list_transports

订阅 compressed 而发布只有 raw,会 silent 失败。压缩降低带宽,但编解码占 CPU——在预算表里与分辨率、帧率一起算,不能单靠 QoS KeepLast(1) 变出带宽。

6. 与 Executor 的接缝

图像回调里跑重推理 + 默认 MutuallyExclusive 回调组 = 阻塞其他订阅。剖面正确后仍卡,再考虑:独立 callback group、组件化节点、NPU 推理进程。顺序反了会把 Executor 问题当成「再加 depth」。

7. 录包 vs 在线

ros2 bag record 订阅常用 RELIABLE;在线节点用 BEST_EFFORT——录包配置不要无脑复制在线 QoS。回放时配对率、延迟与现场不一致,会在 bag 上「调好」、上车又崩。

8. 端到端预算表

定规格前先算:分辨率 × 帧率 × 字节/像素 × 链路数 ≤ 带宽与 CPU 预算。超预算顺序:降分辨率 → 降帧率 → 压缩 → 换 QoS,最后才上更大模型。QoS 保最新只保证处理「尽可能新」的帧,不能凭空变出千兆网。

9. 验收

  • 在线链路:topic info 显示 BEST_EFFORT + 小 depth;端到端延迟 < 控制周期
  • 故意压测 CPU:应丢旧帧而非排队延迟无限增长
  • 标定任务:Reliable 剖面下 bag 帧数与相机计数一致
  • 设计文档并排:预算表 + QoS 剖面表,签字后再换模型

10. 案例:Reliable 导致「跟踪滞后一个身位」

叉车跟踪用 Reliable depth 20,队列在负载尖峰存 15 帧,延迟 500 ms。改为 BEST_EFFORT + KeepLast(1) 后延迟 35 ms,同模型命中率相当——瓶颈在队列语义。迁移视觉栈时先冻结分辨率/帧率/剖面,再换骨干网;否则会把队列延迟当成「模型不够准」。

11. 默认策略

在线感知保最新;采集任务另开剖面;延迟与丢帧分列度量;录包与在线 QoS 分文档。视觉栈的「准」必须含「够新」,否则准的是历史。

12. 多相机与同步

多路相机若各用 KeepLast(1),时间对齐靠 stamp 而非队列——与 message_filters 章节同一逻辑。硬件触发同步时可用 ExactTime 订阅;自由运行则 Accept Approximate slop。每路相机独立 QoS 剖面写进契约,禁止「主相机 Reliable、辅相机 Best Effort」却期望同一融合节点隐式对齐。

← 全部文章

johan's blog