2. ROS2通信基础回顾:Topic、Service、Action机制,DDS中间件的作用,QoS策略简介

好,咱们开始第二讲。说实话,很多做Autoware的朋友,上来就调参数、改代码,结果延迟问题怎么都搞不定。我个人的经验是,八成的问题都出在通信机制的理解上。你连ROS2怎么传数据的都不清楚,怎么定位瓶颈?

这一节,咱们把ROS2的通信基础捋一遍。别嫌基础,这可是定位延迟问题的“内功”。

2.1 三大通信机制:Topic、Service、Action

ROS2里就这三种通信方式。我习惯把它们比作三种“说话”的方式。

2.1.1 Topic —— 广播式聊天

Topic是ROS2里最常用的。说白了,就是发布者(Publisher)往一个“频道”里扔数据,订阅者(Subscriber)去听。一个发,多个收,互不影响。

特点:

  • 异步通信:发布者只管发,不管有没有人收。订阅者只管收,不管谁发的。
  • 一对多:一个Topic可以有多个发布者和多个订阅者。
  • 无反馈:发出去就完了,没有“我收到了”的回执。

我在项目中遇到过一个问题:激光雷达的点云数据通过Topic发布,但下游的感知节点总是丢帧。查了半天,发现是发布者的队列深度设得太小,数据来不及处理就被丢弃了。嗯,这就是Topic的典型坑。

延迟关键点: Topic的延迟主要受网络带宽、消息大小、以及QoS设置影响。在Autoware中,/sensing/lidar/pointcloud 这类高频大Topic,往往是延迟的重灾区。

2.1.2 Service —— 打电话

Service是同步的。客户端(Client)发一个请求,服务端(Server)处理完,再返回一个响应。就像你打电话问问题,对方回答完,这通电话才算结束。

特点:

  • 同步通信:客户端发请求后会阻塞,直到收到响应。
  • 一对一:一个Service只能由一个服务端提供。
  • 有反馈:一定有响应,要么成功,要么失败。

你想想看,如果在一个控制循环里调用Service,那延迟就大了。因为调用方得干等着。所以,Autoware里Service一般用于配置查询、参数设置这类低频操作,比如 /control/vehicle_cmd 这种就不适合用Service。

避坑指南: 我曾经在路径规划模块里用Service来请求全局路径,结果发现每次请求都会卡住几百毫秒。后来改成Topic发布路径更新,延迟瞬间降下来了。记住:高频、实时性要求高的数据,别用Service。

2.1.3 Action —— 带进度汇报的长任务

Action是Service的升级版。它也是请求-响应模式,但中间可以发反馈(Feedback)。适合做那种耗时长的任务,比如“从A点导航到B点”。

特点:

  • 异步+反馈:客户端发请求后不阻塞,可以继续干别的。服务端会定期发进度反馈。
  • 可取消:客户端可以随时取消任务。
  • 有目标、结果、反馈:三个部分组成。

在Autoware里,/planning/mission_planning 这类任务就适合用Action。因为它需要时间计算,而且你希望知道计算到哪一步了。

我的建议: 如果你不确定用Topic还是Action,就问自己一个问题:“我需要知道它什么时候做完吗?” 需要,就用Action;不需要,就用Topic。

2.2 DDS中间件的作用

ROS2和ROS1最大的区别,就是底层通信换成了DDS(Data Distribution Service)。ROS1用的是自研的TCPROS/UDPROS,说白了就是自己搞了一套。ROS2直接用了工业级的DDS标准。

DDS到底干了啥?

  • 发现机制:节点之间怎么找到对方?DDS自动搞定。不需要像ROS1那样靠Master。
  • 数据序列化:把C++的结构体变成能在网络上传输的字节流。ROS2默认用CDR(Common Data Representation)。
  • 传输控制:用UDP还是TCP?要不要可靠传输?这些都由DDS的QoS策略控制。
  • 多供应商支持:你可以选Fast DDS、Cyclone DDS、RTI Connext等。不同供应商性能不一样。

我个人习惯用Fast DDS,因为它是开源里性能最好的之一。但要注意,不同DDS实现之间的互操作性有时候会出问题。我曾经在两个不同DDS供应商的节点之间通信,结果发现消息格式不兼容,折腾了半天。

延迟关键点: DDS的发现过程本身就会引入延迟。在大型系统中,节点数量多,发现风暴可能导致网络拥堵。Autoware里,我建议把发现协议改成静态发现,能省下不少时间。

2.3 QoS策略简介

QoS(Quality of Service)是ROS2里控制通信行为的“开关”。说白了,就是告诉DDS:“这个数据该怎么传,丢了怎么办,要不要排队。”

常用的QoS策略:

策略名 作用 常见设置
Reliability 是否保证数据到达 RELIABLE(可靠)/ BEST_EFFORT(尽力)
Durability 晚来的订阅者能否收到历史数据 VOLATILE(不保留)/ TRANSIENT_LOCAL(保留)
Depth 队列里最多存多少条消息 默认10,可自定义
Liveliness 检测节点是否还活着 AUTOMATIC(自动)/ MANUAL_BY_TOPIC(手动)
Deadline 消息发布的最大间隔 设置一个时间,超时则触发警告

怎么选?

  • 传感器数据(激光雷达、摄像头):用BEST_EFFORT + Depth=1。为什么?因为传感器数据更新快,丢一帧无所谓,但延迟必须低。Depth=1保证只处理最新数据。
  • 控制指令:用RELIABLE + Depth=10。控制指令不能丢,丢了车就乱跑了。Depth=10保证即使网络波动,也能缓存几条。
  • 地图数据:用TRANSIENT_LOCAL + RELIABLE。地图数据是静态的,晚来的节点也需要拿到完整地图。
避坑指南: 我曾经在Autoware里把激光雷达Topic设成了RELIABLE,结果发现延迟从10ms飙升到200ms。因为DDS为了保证可靠传输,会重传丢失的包,导致后续数据排队。改成BEST_EFFORT后,延迟立刻降下来了。记住:高频传感器数据,别用RELIABLE。

2.4 知识体系总览

下面这张图,是我自己画的ROS2通信知识体系。你可以把它当成一张地图,随时回来看看。

ROS2通信知识体系 三大通信机制 • Topic:异步广播 • Service:同步请求-响应 • Action:带反馈的长任务 延迟影响:Topic < Action < Service DDS中间件 • 发现机制 • 数据序列化 (CDR) • 传输控制 (UDP/TCP) 常见实现:Fast DDS, Cyclone DDS QoS策略 • Reliability • Durability • Depth 选错QoS = 延迟翻倍 延迟瓶颈定位核心思路 1. 检查Topic类型:高频数据用Topic,别用Service 2. 检查DDS实现:不同DDS性能差异可达30% 3. 检查QoS设置:传感器用BEST_EFFORT,控制用RELIABLE 4. 检查队列深度:Depth太小丢数据,太大延迟高

嗯,这一节的内容就这些。说白了,ROS2通信就是Topic、Service、Action三选一,底层由DDS负责,QoS是调优的旋钮。你把这些搞清楚了,后面定位延迟问题就有了方向。

可可精品资料库