ROS2基础:架构、通信机制与开发环境搭建
2.1 ROS2的层次化架构
ROS2不是单一的程序,而是一套分布式中间件 + 机器人开发框架的组合。理解其架构,最有效的方式是自底向上拆解为四个层次:OS层 → 中间件层(DDS)→ ROS2客户端库(rcl)→ 应用层。这种分层设计使得ROS2在实时性、可靠性、跨平台能力上远超ROS1。
在四层架构中,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 常见误区与复盘
ros2命令报错“command not found”,原因是~/.bashrc未生效或未写入。解决:执行source /opt/ros/humble/setup.bash,并确认echo $ROS_DISTRO输出humble。
复盘清单:在完成本节学习后,请自查以下能力项——
- 能否画出ROS2四层架构图并解释每层职责?
- 能否说明DDS与ROS1通信的本质差异?
- 能否在30秒内创建一个可运行的Python发布-订阅节点?
- 能否解释QoS的Reliable与Best Effort对传感器数据的影响?
- 能否独立完成工作空间的创建、编译、source全流程?