首页
学习
活动
专区
圈层
工具
发布
社区首页 >专栏 >理解QoS ROS2中为什么你的消息收不到?

理解QoS ROS2中为什么你的消息收不到?

作者头像
点云PCL博主
发布2026-05-13 17:57:30
发布2026-05-13 17:57:30
610
举报
文章被收录于专栏:点云PCL点云PCL

公众号致力于点云处理,SLAM,三维视觉,具身智能,自动驾驶等领域相关内容的干货分享,欢迎各位加入,有兴趣的可联系dianyunpcl@163.com。文章未申请原创,未经过本人允许请勿转载,有意转载联系微信920177957。

摘要

很多人在学习 ROS 2 时,都会遇到一个非常诡异的问题:节点明明启动了,Topic 名称也一致,代码没有报错,但消息就是收不到。更离谱的是:ros2 topic list 能看到 Topic,ros2 topic echo 却没有数据。最后排查半天,发现问题是QoS的问题。

很多开发者刚接触 ROS2 时,会把 QoS 当成一种“高级参数”,甚至直接复制默认配置。但实际上,在 ROS2 中,QoS(Quality of Service)并不是一个简单的通信选项,而是整个系统通信机制的核心。因为从 ROS2 开始,系统不再只是“把消息发出去”,而是开始真正关注:

  • 数据是否可靠
  • 延迟是否可控
  • 消息是否允许丢失
  • 新节点是否能获取历史数据
  • 系统是否满足实时性要求

这一篇文章就结合 ROS2 官方文档,从工程角度彻底讲清:QoS 到底是什么?为什么它会导致“消息收不到”?它又是如何影响整个机器人系统的?

ROS2 为什么一定要引入 QoS?

在 ROS 中,通信主要基于 TCPROS,大多数情况下开发者几乎不用关心通信策略。但 ROS2 不同。ROS2 底层基于 DDS(Data Distribution Service),DDS 天生面向:

  • 分布式系统
  • 实时系统
  • 工业通信
  • 自动驾驶
  • 无线网络环境

这意味着不同的数据,需要不同的通信策略。例如:激光雷达数据频率极高,可以允许部分丢包;控制指令必须低延迟;地图数据必须完整可靠;参数信息需要持久保存。因此 ROS2 引入 QoS,用来描述系统应该如何“对待数据”。官方文档中提到ROS2 可以像 TCP 一样可靠,也可以像 UDP 一样高效。这正是 QoS 的核心意义。

ROS2 QoS 核心策略总览

Reliability:ROS2 为什么既像 TCP 又像 UDP?Reliability(可靠性)是 ROS2 中最重要的 QoS 之一,它决定的是消息到底“必须送达”,还是“尽力送达”。ROS2 提供两种模式:

🔹 Reliable(可靠模式)。保证消息一定送达,必要时会自动重传,这种模式类似 TCP。适用于:地图数据,路径规划,关键状态信息。缺点是:延迟更高,网络压力更大

🔹 Best Effort(尽力而为)。尽量发送,允许丢包,类似 UDP。适用于:激光雷达,相机图像,高频传感器数据。因为对于传感器来说:“最新数据”远比“完整数据”更重要。

Durability(持久性)决定的是系统是否保存历史消息。

🔹 Volatile(易失性)。只接收新消息,不保存历史。适用于:激光雷达;相机;实时数据流

🔹 Transient Local(本地持久化)。Publisher 会保存最近消息;后加入的节点也能收到。适用于:地图;参数;初始化信息。这其实非常像 ROS1 中的:Latch Topic。例如地图节点提前发布地图,而定位节点稍后启动。如果使用 Volatile,定位节点永远收不到地图

如果使用 Transient Local,后加入节点也能立即获取地图。

History 与 Depth:为什么系统会突然丢数据?ROS2 的 History 策略决定消息如何缓存。

🔹 Keep Last。只保留最近 N 条消息,这是最常用模式。例如QoS(10):表示最多缓存 10 条。

🔹 Keep All。保存所有历史消息,听起来很安全,但实际上非常危险。如果 Subscriber 处理不过来,内存会无限增长。因此在工程实践中99% 的场景都应该使用 Keep Last。

Deadline:ROS2 如何支持实时系统?Deadline 用于描述两条消息之间允许的最大时间间隔。例如控制器要求 10ms 必须收到一次控制指令。如果超过 Deadline系统会触发 QoS 事件,这使 ROS2 不再只是“消息通信框架”,而开始具备实时系统,工业控制,故障检测能力。

QoS Event:系统终于开始“感知异常”,这是 ROS2 相比 ROS1 巨大的升级之一。ROS2 中,QoS 不只是静态配置,它还会产生事件(QoS Events)。例如

Publisher 可以检测:

  • Deadline Missed
  • Liveliness Lost
  • Offered Incompatible QoS

Subscriber 可以检测:

  • Requested Deadline Missed
  • Requested Incompatible QoS
  • Publisher 掉线

这意味着ROS2 开始具备“系统状态感知能力”。

为什么你的消息“收不到”?

消息“收不到”是 ROS2 中最经典的问题之一。QoS 必须兼容,通信才能建立。官方文档采用的是:Request vs Offered模型。也就是说:Subscriber 提出“最低要求”,Publisher 提供“最大能力”。只有双方兼容,连接才会建立。例如:

最容易踩坑的情况:

  • Publisher: Best Effort
  • Subscriber: Reliable

结果就是直接无法通信,因为 Subscriber 要求“必须可靠”,但 Publisher 只能“尽力发送”。

ROS2 为什么比 ROS1 更复杂?

很多开发者第一次接触 ROS 2 时,会觉得“为什么 ROS2 比 ROS1 复杂这么多?”其实很简单。因为 ROS1 更像研究工具,而 ROS2 的目标是:自动驾驶,工业机器人,分布式系统,实时控制。在这些场景中“能通信”远远不够。更重要的是:数据是否可靠,延迟是否可控,系统是否稳定,网络是否健壮。而 QoS就是 ROS2 为这些问题提供的核心机制。

QoS 的本质,其实是“系统设计”,很多人学习 QoS,只关注:rclcpp::QoS(10)。但真正重要的问题是:

  • 为什么激光雷达允许丢包?
  • 为什么地图必须持久化?
  • 为什么控制系统更关注延迟?
  • 为什么高频点云不能无限缓存?

这些问题本质上都不是代码问题,而是系统设计问题。QoS 真正描述的,并不是“通信方式”。而是系统如何理解数据。

C++ 的 QoS API

C++ 的 QoS API 可以參考 rclcpp::QoS Class Reference.基本上作法是先 init QoS,然后在 create publisher / subscriber 的時候把 QoS 带入即可。

代码语言:javascript
复制
// 先 init QoS 的物件
rclcpp::QoS qos_settings(10);
// 如果要设定 keep_last 10, reliable, volatile
qos_settings.keep_last(10).reliable().durability_volatile();
// 如果要设定 keep_all, best_effort, transient local
qos_settings.keep_all().best_effort().transient_local();
// 然后再将 QoS 在 create publisher 时带入即可
publisher_ = this->create_publisher<std_msgs::msg::String>("topic", qos_settings);

总结

在 ROS 2 中,QoS 从来不是一个简单的“通信参数”。Reliable、Best Effort、Transient Local、Deadline……这些配置背后,实际上代表的是数据是否重要,系统是否实时,网络是否可靠,节点是否允许掉线。当我们真正理解 QoS 时,你会意识到ROS2 的通信,本质上是在设计整个系统的数据流规则。所以QoS 不是关注“怎么发消息”,而是“系统如何对待数据”。

以上内容如有错误请留言评论,欢迎指正交流。如有侵权,请联系删除

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2026-05-09,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 点云PCL 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档