ROS2中的QoS(Quality of Service)详解
ROS2中的QoS(Quality of Service)详解
- 1. 主要QoS参数
- 2. 为什么需要设置QoS
- 3. QoS兼容性规则
- 4. 选择QoS策略的建议
- 5. 调试QoS问题的方法
- 6. 踩坑:订阅话题没有输出
- 可能的原因:
- 调试方法
QoS是ROS2中用于控制通信质量和行为的机制。它定义了发布者和订阅者之间消息传递的各种策略和保证,包括可靠性、持久性、延迟等特性。
1. 主要QoS参数
- Reliability(可靠性)
# 两种模式:
QoSReliabilityPolicy.RELIABLE # 可靠传输,确保消息送达
QoSReliabilityPolicy.BEST_EFFORT # 尽力传输,不保证送达
- Durability(持久性)
QoSDurabilityPolicy.TRANSIENT_LOCAL # 为新订阅者保留最后的消息
QoSDurabilityPolicy.VOLATILE # 不保留消息
- History(历史记录)
QoSHistoryPolicy.KEEP_LAST # 保留最后N条消息
QoSHistoryPolicy.KEEP_ALL # 保留所有消息
- Depth(深度)
depth=10 # 消息队列深度
2. 为什么需要设置QoS
- 发布者和订阅者QoS必须兼容
ROS2中,发布者和订阅者的QoS设置必须兼容才能正常通信。不兼容的QoS设置会导致连接失败。
- 默认QoS差异
# ROS2不同API的默认QoS可能不同
# 有些默认是RELIABLE,有些是BEST_EFFORT
3. QoS兼容性规则
- Reliability兼容性
# 兼容组合:
Publisher: RELIABLE <-> Subscriber: RELIABLE ✓
Publisher: BEST_EFFORT <-> Subscriber: BEST_EFFORT ✓
Publisher: RELIABLE <-> Subscriber: BEST_EFFORT ✓
Publisher: BEST_EFFORT <-> Subscriber: RELIABLE ✗ (不兼容)
- Durability兼容性
# 兼容组合:
Publisher: TRANSIENT_LOCAL <-> Subscriber: TRANSIENT_LOCAL ✓
Publisher: VOLATILE <-> Subscriber: VOLATILE ✓
Publisher: TRANSIENT_LOCAL <-> Subscriber: VOLATILE ✓
Publisher: VOLATILE <-> Subscriber: TRANSIENT_LOCAL ✗ (不兼容)
4. 选择QoS策略的建议
- 传感器数据(如激光雷达、摄像头)
# 使用BEST_EFFORT,因为数据频率高,偶尔丢失可接受
qos_profile = QoSProfile(depth=10,reliability=QoSReliabilityPolicy.BEST_EFFORT,history=QoSHistoryPolicy.KEEP_LAST
)
- 控制命令
# 使用RELIABLE,确保命令不丢失
qos_profile = QoSProfile(depth=10,reliability=QoSReliabilityPolicy.RELIABLE,history=QoSHistoryPolicy.KEEP_LAST
)
- 配置参数
# 使用TRANSIENT_LOCAL,新订阅者可以获得最后的配置
qos_profile = QoSProfile(depth=1,reliability=QoSReliabilityPolicy.RELIABLE,durability=QoSDurabilityPolicy.TRANSIENT_LOCAL,history=QoSHistoryPolicy.KEEP_LAST
)
5. 调试QoS问题的方法
- 检查QoS兼容性
# 查看话题的QoS信息
ros2 topic info /inner/information/object_computation -v
- 使用QoS分析工具
# 安装QoS分析工具
sudo apt install ros-humble-rqt-graph
rqt_graph
- 在代码中打印QoS信息
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 查看话题,又有打印的信息。
可能的原因:
- 话题名称不匹配
检查您程序中发布消息的话题名称是否完全匹配订阅者的话题名称。确保:
- 发布者使用的话题名称:
/test_ros2
- 订阅者使用的话题名称:
/test_ros2
- 注意前缀斜杠、大小写、拼写等
- 消息类型不匹配
确认发布程序使用的消息类型与订阅者期望的类型完全一致:
# 发布者应该使用
from custom_msgs.msg import Object
- QoS设置不匹配
检查发布者和订阅者的QoS设置是否兼容。
调试方法
- 检查话题状态
# 查看当前活跃的话题
ros2 topic list
# 查看特定话题的信息
ros2 topic info /test_ros2
# 实时监听话题消息
ros2 topic echo /test_ros2
- 检查消息发布频率
如果程序只发布一次消息就退出,可能订阅者还没来得及接收。尝试:
# 在发布程序中循环发布或添加延迟
for i in range(5): # 发布5次publisher.publish(msg)time.sleep(1)
- 使用相同的QoS设置
在订阅者中明确设置QoS:
from rclpy.qos import QoSProfile, QoSReliabilityPolicyqos_profile = QoSProfile(depth=10)
qos_profile.reliability = QoSReliabilityPolicy.BEST_EFFORTself.subscription = self.create_subscription(Object,'/test_ros2',self.object_callback,qos_profile
)
最终采用方法3得到解决。