ROS2中的QoS(Quality of Service)详解

ROS2中的QoS(Quality of Service)详解

  • [1. 主要QoS参数](#1. 主要QoS参数)
  • [2. 为什么需要设置QoS](#2. 为什么需要设置QoS)
  • [3. QoS兼容性规则](#3. QoS兼容性规则)
  • [4. 选择QoS策略的建议](#4. 选择QoS策略的建议)
  • [5. 调试QoS问题的方法](#5. 调试QoS问题的方法)
  • [6. 踩坑:订阅话题没有输出](#6. 踩坑:订阅话题没有输出)

QoS是ROS2中用于控制通信质量和行为的机制。它定义了发布者和订阅者之间消息传递的各种策略和保证,包括可靠性、持久性、延迟等特性。

1. 主要QoS参数

  1. Reliability(可靠性)
python 复制代码
# 两种模式:
QoSReliabilityPolicy.RELIABLE      # 可靠传输,确保消息送达
QoSReliabilityPolicy.BEST_EFFORT   # 尽力传输,不保证送达
  1. Durability(持久性)
python 复制代码
QoSDurabilityPolicy.TRANSIENT_LOCAL  # 为新订阅者保留最后的消息
QoSDurabilityPolicy.VOLATILE         # 不保留消息
  1. History(历史记录)
python 复制代码
QoSHistoryPolicy.KEEP_LAST   # 保留最后N条消息
QoSHistoryPolicy.KEEP_ALL    # 保留所有消息
  1. Depth(深度)
python 复制代码
depth=10  # 消息队列深度

2. 为什么需要设置QoS

  1. 发布者和订阅者QoS必须兼容

ROS2中,发布者和订阅者的QoS设置必须兼容才能正常通信。不兼容的QoS设置会导致连接失败。

  1. 默认QoS差异
python 复制代码
# ROS2不同API的默认QoS可能不同
# 有些默认是RELIABLE,有些是BEST_EFFORT

3. QoS兼容性规则

  1. Reliability兼容性
python 复制代码
# 兼容组合:
Publisher: RELIABLE    <-> Subscriber: RELIABLE    ✓
Publisher: BEST_EFFORT <-> Subscriber: BEST_EFFORT ✓
Publisher: RELIABLE    <-> Subscriber: BEST_EFFORT ✓
Publisher: BEST_EFFORT <-> Subscriber: RELIABLE    ✗ (不兼容)
  1. Durability兼容性
python 复制代码
# 兼容组合:
Publisher: TRANSIENT_LOCAL <-> Subscriber: TRANSIENT_LOCAL ✓
Publisher: VOLATILE        <-> Subscriber: VOLATILE        ✓
Publisher: TRANSIENT_LOCAL <-> Subscriber: VOLATILE        ✓
Publisher: VOLATILE        <-> Subscriber: TRANSIENT_LOCAL ✗ (不兼容)

4. 选择QoS策略的建议

  1. 传感器数据(如激光雷达、摄像头)
python 复制代码
# 使用BEST_EFFORT,因为数据频率高,偶尔丢失可接受
qos_profile = QoSProfile(
    depth=10,
    reliability=QoSReliabilityPolicy.BEST_EFFORT,
    history=QoSHistoryPolicy.KEEP_LAST
)
  1. 控制命令
python 复制代码
# 使用RELIABLE,确保命令不丢失
qos_profile = QoSProfile(
    depth=10,
    reliability=QoSReliabilityPolicy.RELIABLE,
    history=QoSHistoryPolicy.KEEP_LAST
)
  1. 配置参数
python 复制代码
# 使用TRANSIENT_LOCAL,新订阅者可以获得最后的配置
qos_profile = QoSProfile(
    depth=1,
    reliability=QoSReliabilityPolicy.RELIABLE,
    durability=QoSDurabilityPolicy.TRANSIENT_LOCAL,
    history=QoSHistoryPolicy.KEEP_LAST
)

5. 调试QoS问题的方法

  1. 检查QoS兼容性
bash 复制代码
# 查看话题的QoS信息
ros2 topic info /inner/information/object_computation -v
  1. 使用QoS分析工具
bash 复制代码
# 安装QoS分析工具
sudo apt install ros-humble-rqt-graph
rqt_graph
  1. 在代码中打印QoS信息
python 复制代码
def check_qos_compatibility(self):
    """检查QoS兼容性"""
    topic_info = self.get_topic_names_and_types()
    self.get_logger().info(f'话题信息: {topic_info}')

您的问题通过设置BEST_EFFORT解决了,说明您的发布程序使用的是BEST_EFFORT策略,而订阅程序默认使用了RELIABLE策略,导致不兼容。设置为BEST_EFFORT后,订阅者可以接收任何可靠性级别的消息。

6. 踩坑:订阅话题没有输出

通过程序发布ros2消息给/test_ros2话题 ,通过python程序

复制代码
self.subscription = self.create_subscription(Object, '/test_ros2', object_callback, 100)

订阅话题后,没有打印任何信息。但是通过终端命令行ros2 topic pub /test_ros2 custom_msgs/Object 去发布,通过ros2 topic echo 查看话题,又有打印的信息。

可能的原因:

  1. 话题名称不匹配

检查您程序中发布消息的话题名称是否完全匹配订阅者的话题名称。确保:

  • 发布者使用的话题名称:/test_ros2
  • 订阅者使用的话题名称:/test_ros2
  • 注意前缀斜杠、大小写、拼写等
  1. 消息类型不匹配

确认发布程序使用的消息类型与订阅者期望的类型完全一致:

python 复制代码
# 发布者应该使用
from custom_msgs.msg import Object
  1. QoS设置不匹配

检查发布者和订阅者的QoS设置是否兼容。

调试方法

  1. 检查话题状态
bash 复制代码
# 查看当前活跃的话题
ros2 topic list
# 查看特定话题的信息
ros2 topic info /test_ros2
# 实时监听话题消息
ros2 topic echo /test_ros2
  1. 检查消息发布频率

如果程序只发布一次消息就退出,可能订阅者还没来得及接收。尝试:

python 复制代码
# 在发布程序中循环发布或添加延迟
for i in range(5):  # 发布5次
    publisher.publish(msg)
    time.sleep(1)
  1. 使用相同的QoS设置

在订阅者中明确设置QoS:

python 复制代码
from rclpy.qos import QoSProfile, QoSReliabilityPolicy

qos_profile = QoSProfile(depth=10)
qos_profile.reliability = QoSReliabilityPolicy.BEST_EFFORT

self.subscription = self.create_subscription(
    Object,
    '/test_ros2',
    self.object_callback,
    qos_profile
)

最终采用方法3得到解决。

相关推荐
June`2 分钟前
IO模型全解析:从阻塞到异步(高并发的reactor模型)
linux·服务器·网络·c++
ASS-ASH8 分钟前
快速处理虚拟机磁盘扩容问题
linux·数据库·vmware·虚拟机·磁盘扩容
AI_56789 分钟前
零基础学Linux:21天从“命令小白”到独立部署服务器
linux·服务器·人工智能·github
不染尘.11 分钟前
Linux基本概述
linux·windows·centos·ssh
是垚不是土13 分钟前
AIOps实践:基于 Dify+LangBot 实现飞书智能体对话机器人
机器人·飞书
TTGGGFF15 分钟前
GLM-4V-9B 视觉多模态模型本地部署教程【保姆级教程】
linux·运维·服务器·图文对话
消失的旧时光-194317 分钟前
函数指针 + 结构体 = C 语言的“对象模型”?——从 C 到 C++ / Java 的本质统一
linux·c语言·开发语言·c++·c
郝学胜-神的一滴21 分钟前
Linux系统编程:深入理解读写锁的原理与应用
linux·服务器·开发语言·c++·程序人生
Larry_Yanan22 分钟前
Qt多进程(十一)Linux下socket通信
linux·开发语言·c++·qt
__雨夜星辰__35 分钟前
VMware 17 下 Ubuntu 虚拟机与宿主机间复制粘贴失效问题
linux·运维·ubuntu