2. ROS2基础架构

ROS2 并不是“ROS1 的升级版补丁”,而是一次通信内核的重构。理解 ROS2,关键不是记住 API,而是看清它如何把应用逻辑与通信机制解耦:上层用节点、话题、服务、动作、参数描述“系统要做什么”,下层用 DDS 完成“数据怎么可靠、实时、可发现地流动”。本节从分层架构入手,逐层拆解核心概念及其协作关系。

一、ROS2 分层架构:从应用到 DDS

ROS2 采用清晰的分层设计,自上而下可划分为四层:

  • 应用层:开发者编写的节点、算法、感知/规划/控制模块,使用 rclcpp、rclpy 等客户端库。
  • 客户端库层:rclcpp(C++)、rclpy(Python)等,提供节点、发布者、订阅者、服务、动作、参数等编程接口。
  • 中间件抽象层(rmw):ROS Middleware Interface,定义统一通信 API,屏蔽不同 DDS 实现的差异。
  • DDS 层:具体 DDS 实现(如 Fast DDS、Cyclone DDS),负责发现、序列化、QoS、传输。

这种分层的价值在于:更换 DDS 实现时,上层应用代码几乎不需要改动,只需替换 rmw 实现并重新编译。对于自动驾驶系统,这意味着可以在开发阶段用通用 DDS,在量产阶段切换到满足功能安全与实时性要求的 DDS 实现。

ROS2 分层架构与核心概念映射 应用层 感知节点 · 规划节点 · 控制节点 · 定位节点 · 诊断节点 自动驾驶业务逻辑 与通信解耦 客户端库层 rclcpp(C++) · rclpy(Python) · 节点/发布者/订阅者/服务/动作/参数 API 统一编程接口 语言无关语义 中间件抽象层(rmw) ROS Middleware Interface · 统一通信 API · 屏蔽 DDS 差异 可替换 DDS 实现 不改变上层代码 DDS 层 Fast DDS · Cyclone DDS · 发现机制 · QoS · 序列化 · 传输 实时 · 可靠 · 可发现 数据分发核心 核心思想:应用逻辑与通信机制解耦,DDS 负责数据流动,ROS2 负责语义与工具链

二、核心概念:节点、话题、服务、动作、参数

ROS2 用五种基本通信模式覆盖自动驾驶中的绝大多数交互场景:

概念 通信模式 典型场景 关键特征
节点 Node 进程/线程单元 感知、规划、控制各一个节点 最小功能单元,可独立启停
话题 Topic 发布/订阅,异步 激光雷达点云、摄像头图像、车辆状态 多对多,持续数据流,QoS 可配
服务 Service 请求/响应,同步 查询地图、切换模式、标定触发 一对一,短时交互,有返回值
动作 Action 目标/反馈/结果,异步 导航到目标点、泊车、跟车 长时任务,可取消,带进度反馈
参数 Parameter 键值配置,动态可调 控制增益、阈值、传感器标定值 节点级配置,支持运行时修改

选择通信模式的核心判断依据是:数据是持续流还是单次请求?交互是短时还是长时?是否需要反馈和取消? 例如,激光雷达数据必须用话题,因为它是高频持续流;而“请求地图切片”适合服务;导航任务则必须用动作,因为需要持续反馈进度并允许中途取消。

三、执行器与客户端库:让节点真正跑起来

节点定义好后,需要执行器(Executor)来驱动回调。ROS2 提供多种执行器:

  • 单线程执行器:所有回调在一个线程中顺序执行,简单但可能阻塞。
  • 多线程执行器:回调可并行执行,适合高吞吐场景,但需注意线程安全。
  • 事件执行器:基于事件循环,适合实时性要求高的场景。

客户端库方面,rclcpp 和 rclpy 是最常用的两个。rclcpp 适合性能敏感的感知、控制模块;rclpy 适合快速原型、脚本工具和调试。两者共享相同的 rmw 接口,因此可以混合使用。

# 查看当前节点列表
ros2 node list

# 查看话题列表及类型
ros2 topic list -t

# 查看某个话题的实时数据
ros2 topic echo /vehicle/status

# 调用服务
ros2 service call /map/query nav_msgs/srv/GetMap "{}"

# 发送动作目标
ros2 action send_goal /navigate_to_pose nav2_msgs/action/NavigateToPose "{pose: ...}"

# 查看和修改参数
ros2 param list /controller
ros2 param set /controller max_speed 5.0

四、DDS 通信模型:发现、QoS 与数据流

DDS 是 ROS2 的通信底座,其核心机制包括:

  • 自动发现:节点加入网络后自动发现彼此,无需中心 broker,避免单点故障。
  • QoS 策略:可靠性(RELIABLE/BEST_EFFORT)、持久性(TRANSIENT_LOCAL/VOLATILE)、历史深度、截止时间等,直接决定通信行为。
  • 数据序列化:CDR 格式,跨语言、跨平台一致。
  • 传输层:支持 UDP、TCP、共享内存,共享内存可大幅降低大点云传输延迟。

自动驾驶场景中的 QoS 选择示例:

  • 激光雷达点云:BEST_EFFORT + 深度 5,允许丢帧但不能阻塞。
  • 车辆控制指令:RELIABLE + 深度 1,必须可靠且只保留最新。
  • 地图/标定数据:TRANSIENT_LOCAL + RELIABLE,晚加入的节点也能拿到。

五、案例与误区复盘

案例:某自动驾驶项目在实车上出现“控制指令偶尔延迟 200ms”的问题。排查发现,控制话题使用了默认 QoS(RELIABLE + 深度 10),当网络抖动时,DDS 重传旧指令,导致控制节点处理了过期数据。改为 RELIABLE + 深度 1 后,问题消失。

常见误区:

  • 把所有话题都设为 RELIABLE,导致高带宽场景下重传风暴。
  • 用服务做长时任务,导致客户端阻塞、无法取消。
  • 忽略执行器线程模型,在回调中做重计算,造成回调堆积。
  • 认为 ROS2 自带实时性,实际上实时性依赖 DDS 配置、执行器选择和操作系统调优。

理解 ROS2 基础架构,最终要落到“选对通信模式、配好 QoS、用对执行器”这三件事上。它们共同决定了自动驾驶中间件是否可靠、实时、可扩展。