Files
ROS2_learn/doc/19-qos.md
T

4.9 KiB

19 · QoS (服务质量) 完全指南

目标: 理解 ROS2 QoS 的 5 个维度、兼容规则、9 种常用组合、能独立为节点选 QoS。


目录


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. 推荐阅读