5.3 KiB
5.3 KiB
19 · QoS (服务质量) 完全指南
目标: 理解 ROS2 QoS 的 5 个维度、兼容规则、9 种常用组合、能独立为节点选 QoS。
目录
- 1. 是什么
- 2. 5 大维度
- 3. 兼容规则
- 4. 9 种常用组合
- 5. Python API
- 6. C++ API
- 7. rclpy QoSProfile 详解
- 8. 调试 QoS 不兼容
- 9. 推荐阅读
1. 是什么
QoS (Quality of Service) 控制 DDS 通信的可靠性、实时性、持久性等。
ROS2 默认 QoS = RELIABLE + VOLATILE + KEEP_LAST(10),适合大多数场景。
但高频传感器流 / 控制指令 / 参数发布等场景需要自定义 QoS。
2. 5 大维度
| 维度 | 取值 | 默认 | 含义 |
|---|---|---|---|
| Reliability | RELIABLE / BEST_EFFORT | RELIABLE | 必须投递 / 丢一帧无所谓 |
| History | KEEP_LAST(N) / KEEP_ALL | KEEP_LAST(10) | 队列策略 |
| Durability | VOLATILE / TRANSIENT_LOCAL | VOLATILE | 晚订阅者是否收到旧数据 |
| Deadline | Duration | ∞ | 最长多久发一次 |
| Lifespan | Duration | ∞ | 多旧的消息失效 |
3. 兼容规则
关键规则 — RELIABLE ↔ BEST_EFFORT 单向兼容:
| Publisher ↓ \ Subscriber → | RELIABLE | BEST_EFFORT |
|---|---|---|
| RELIABLE | ✅ | ❌ |
| BEST_EFFORT | ✅ | ✅ |
为什么 RELIABLE → BEST_EFFORT 不兼容:
- RELIABLE pub 等 ACK(确保投递)
- BEST_EFFORT sub 不发 ACK
- pub 等不到 ACK → 报 "QoS incompatible"
报错样例:
[WARN] ... New subscription discovered on this topic with incompatible QoS ...
4. 9 种常用组合
| Reliability | Durability | History | 适用场景 |
|---|---|---|---|
| RELIABLE | VOLATILE | KEEP_LAST(10) | 默认 / 跨语言互通基线 |
| RELIABLE | VOLATILE | KEEP_LAST(1) | 控制指令(只关心最新) |
| RELIABLE | TRANSIENT_LOCAL | KEEP_LAST(1) | 参数 / 配置(晚订阅者也能拿到) |
| RELIABLE | VOLATILE | KEEP_ALL | 日志(必须投递,不丢) |
| RELIABLE | TRANSIENT_LOCAL | KEEP_ALL | 启动期参数 |
| BEST_EFFORT | VOLATILE | KEEP_LAST(1) | 视频流(丢一帧无所谓) |
| BEST_EFFORT | VOLATILE | KEEP_LAST(10) | Lidar / 雷达 |
| BEST_EFFORT | TRANSIENT_LOCAL | KEEP_LAST(1) | 较老的状态快照 |
| SYSTEM_DEFAULT | VOLATILE | KEEP_LAST(10) | 由 RMW 决定 |
5. Python API
from rclpy.qos import (
QoSProfile,
ReliabilityPolicy,
HistoryPolicy,
DurabilityPolicy,
)
# 视频流:BEST_EFFORT + 深度 1
sensor_qos = QoSProfile(
reliability=ReliabilityPolicy.BEST_EFFORT,
history=HistoryPolicy.KEEP_LAST,
depth=1,
)
# 控制指令:RELIABLE + 深度 1
control_qos = QoSProfile(
reliability=ReliabilityPolicy.RELIABLE,
history=HistoryPolicy.KEEP_LAST,
depth=1,
)
# 参数:TRANSIENT_LOCAL(晚订阅者能拿历史)
param_qos = QoSProfile(
reliability=ReliabilityPolicy.RELIABLE,
durability=DurabilityPolicy.TRANSIENT_LOCAL,
depth=1,
)
# 用
publisher_ = self.create_publisher(String, 'topic', sensor_qos)
6. C++ API
#include "rclcpp/qos.hpp"
using namespace rclcpp;
// 视频流
auto sensor_qos = QoS(1)
.reliability(RMW_QOS_POLICY_RELIABILITY_BEST_EFFORT)
.history(RMW_QOS_POLICY_HISTORY_KEEP_LAST);
// 参数
auto param_qos = QoS(1)
.reliability(RMW_QOS_POLICY_RELIABILITY_RELIABLE)
.durability(RMW_QOS_POLICY_DURABILITY_TRANSIENT_LOCAL);
// 用
publisher_ = this->create_publisher<String>("topic", sensor_qos);
7. rclpy QoSProfile 详解
完整参数:
QoSProfile(
# Reliability
reliability=ReliabilityPolicy.RELIABLE, # or BEST_EFFORT, SYSTEM_DEFAULT
# History
history=HistoryPolicy.KEEP_LAST, # or KEEP_ALL
depth=10, # 仅 KEEP_LAST 时有效
# Durability
durability=DurabilityPolicy.VOLATILE, # or TRANSIENT_LOCAL
# Deadline(可省)
deadline=Duration(seconds=0), # 0 = 无
# Lifespan(可省)
lifespan=Duration(seconds=0), # 0 = 无
# Liveliness(可省)
liveliness=LivelinessPolicy.SYSTEM_DEFAULT,
liveliness_lease_duration=Duration(seconds=0),
)
8. 调试 QoS 不兼容
症状: ros2 topic echo 没输出,ros2 topic info -v 显示 QoS incompatible 警告。
调试步骤:
# 1) 看 pub/sub 各自 QoS
ros2 topic info /topic -v
# 2) 检查 pub/sub 是否在同 domain
echo $ROS_DOMAIN_ID
# 3) 看具体 incompatibility
# 错误信息: PolicyKind=RMW_QOS_POLICY_RELIABILITY
修法: 改一边 QoS 匹配,或用 SYSTEM_DEFAULT。
9. 推荐阅读
📖 阅读路径导航
💡 这是仓库
doc/下所有文档的推荐阅读顺序。返回 README 总导航⏱ 本文预计阅读时间: 25 分钟 📍 当前位置: 第 10 / 24 篇
- ⏮ 上一篇: Composable Node
- ⏭ 下一篇: Topic pub/sub 深度