ROS2基础:架构、通信机制与开发环境搭建

2.1 ROS2的层次化架构

ROS2不是单一的程序,而是一套分布式中间件 + 机器人开发框架的组合。理解其架构,最有效的方式是自底向上拆解为四个层次:OS层 → 中间件层(DDS)→ ROS2客户端库(rcl)→ 应用层。这种分层设计使得ROS2在实时性、可靠性、跨平台能力上远超ROS1。

应用层(机器人功能包) 导航栈 · 机械臂控制 · 视觉SLAM · 语音交互 · 自定义节点 以 ament_python / ament_cmake 构建的独立可执行程序 ROS2 客户端库(rcl / rclcpp / rclpy) 节点生命周期管理 · 参数服务 · 时钟同步 · QoS策略映射 提供统一的 C++ / Python API,屏蔽底层DDS差异 DDS 中间件(Fast DDS / Cyclone DDS / RTI Connext) 发布-订阅通信 · 服务请求-响应 · 发现机制 · 可靠性QoS 数据以 IDL 格式描述,支持多机分布式部署 操作系统层(Linux / Windows / macOS / RTOS) Ubuntu 22.04(Humble)为最常用 · 实时补丁 PREEMPT_RT 提供进程调度、网络协议栈、文件系统等基础能力 上层依赖下层,下层为上层提供抽象接口

在四层架构中,DDS层是ROS2最具革命性的变化。ROS1的自研TCPROS通信机制在跨平台、实时性、安全性方面存在天然短板;而DDS是工业界成熟的发布-订阅中间件标准,具备去中心化发现、多播通信、自动故障转移等特性。ROS2将DDS作为默认通信底座,同时通过rmw(ROS Middleware Interface)抽象层,允许用户在不同DDS实现之间切换,而不影响上层代码。

2.2 核心通信机制:话题、服务与动作

ROS2的通信模型围绕三种原语展开,每种原语解决不同场景的问题。理解它们的区别是编写正确节点的前提。

通信原语通信模式典型场景QoS关键设置
话题(Topic)异步发布-订阅,多对多传感器数据流、里程计、点云Best Effort / Reliable
服务(Service)同步请求-响应,一对一开关灯、获取地图、执行单次计算Reliable + Volatile
动作(Action)异步请求 + 反馈 + 结果导航到目标点、机械臂抓取Reliable + Keep Last

以话题通信为例,其数据流遵循“发布者 → DDS全局数据空间 → 订阅者”的路径。发布者调用publish()后,数据被序列化为DDS消息,通过共享内存或网络传输到所有匹配的订阅者。ROS2的发现机制基于DDS的SPDP协议,节点启动后自动广播自身信息,无需中心节点(区别于ROS1的roscore)。

# 话题通信最小示例(Python)
# 发布端
import rclpy
from rclpy.node import Node
from std_msgs.msg import String

class Talker(Node):
    def __init__(self):
        super().__init__('talker')
        self.pub = self.create_publisher(String, 'chatter', 10)
        self.timer = self.create_timer(1.0, self.timer_cb)
    def timer_cb(self):
        msg = String()
        msg.data = 'Hello ROS2'
        self.pub.publish(msg)

rclpy.init()
rclpy.spin(Talker())
rclpy.shutdown()

2.3 开发环境搭建与工作空间配置

搭建ROS2开发环境的核心目标是建立可复现、可调试、可扩展的工程结构。推荐使用Ubuntu 22.04 + ROS2 Humble组合,这是当前长期支持版本中资料最丰富、兼容性最好的搭配。安装完成后,必须验证环境变量是否正确加载:

# 1. 安装ROS2 Humble(桌面版)
sudo apt update
sudo apt install ros-humble-desktop python3-argcomplete

# 2. 配置环境变量(写入 ~/.bashrc)
echo "source /opt/ros/humble/setup.bash" >> ~/.bashrc
source ~/.bashrc

# 3. 验证安装
ros2 --version
ros2 topic list   # 应输出 /parameter_events /rosout 等

工作空间采用colcon构建系统,其目录结构遵循“src → build → install → log”四目录规范。创建自己的功能包时,使用ros2 pkg create命令自动生成模板:

# 创建自己的工作空间
mkdir -p ~/ros2_ws/src
cd ~/ros2_ws

# 创建C++功能包(依赖rclcpp)
ros2 pkg create my_robot_bringup \
  --build-type ament_cmake \
  --dependencies rclcpp std_msgs

# 构建并生效
colcon build --symlink-install
source install/setup.bash

# 运行节点测试
ros2 run my_robot_bringup my_robot_node
关键经验:使用 --symlink-install 参数构建,Python代码修改后无需重新编译即可生效,大幅提升迭代效率。对于C++节点,修改头文件后仍需重新构建。

2.4 案例:搭建激光雷达数据采集节点

下面通过一个真实案例,将上述概念串联起来。假设我们有一个2D激光雷达(如RPLIDAR A1),需要编写节点读取扫描数据并发布到/scan话题。该案例覆盖了驱动安装、话题通信、QoS匹配、可视化验证的完整链路。

# 安装雷达驱动(以rplidar为例)
sudo apt install ros-humble-rplidar-ros

# 启动雷达节点(发布 /scan 话题)
ros2 launch rplidar_ros rplidar_a1_launch.py

# 在另一个终端验证话题数据
ros2 topic echo /scan --once
# 输出包含 angle_min, angle_max, ranges 等字段

# 使用RViz可视化点云
rviz2

在RViz中,将Fixed Frame设置为laser,添加LaserScan显示插件,选择/scan话题,即可看到实时点云。若雷达数据不显示,优先检查QoS策略是否匹配——雷达驱动通常使用Best Effort,而RViz默认订阅为Reliable,需手动调整RViz的QoS为Best Effort才能收到数据。

2.5 常见误区与复盘

误区1:忘记source环境变量。新开终端直接运行ros2命令报错“command not found”,原因是~/.bashrc未生效或未写入。解决:执行source /opt/ros/humble/setup.bash,并确认echo $ROS_DISTRO输出humble。
误区2:混淆话题与服务的使用场景。初学者常试图用话题实现“请求-响应”逻辑(如调用传感器执行一次采集),导致代码复杂且难以同步。正确做法:单次请求用服务,持续数据流用话题,长时任务带进度反馈用动作。

复盘清单:在完成本节学习后,请自查以下能力项——

  • 能否画出ROS2四层架构图并解释每层职责?
  • 能否说明DDS与ROS1通信的本质差异?
  • 能否在30秒内创建一个可运行的Python发布-订阅节点?
  • 能否解释QoS的Reliable与Best Effort对传感器数据的影响?
  • 能否独立完成工作空间的创建、编译、source全流程?