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得到解決。