ROS 2 Lyrical 第2章 ROS 2系统架构与核心概念
前言
完成ROS 2 Lyrical部署安装后,本章系统拆解ROS 2完整三层架构,对标原ROS 1 Noetic文档体系,同时区分ROS 1中心化Master与ROS 2去中心化DDS底层差异,覆盖文件系统层、计算图层、开源社区层三大层级,配套Turtlesim实操、自定义消息/服务、Launch文件、动态参数重配置完整实验,全程遵循ROS 2 Humble/Lyrical官方规范,内容严谨可复现。
本章覆盖内容
- ROS 2三层整体架构分层定义(文件系统层、计算图层、社区层)
- ROS 2 ament文件系统规范:工作空间、功能包、元功能包、msg/srv/action
- ROS 2计算图核心实体:节点、DDS分布式发现、话题、服务、动作、参数服务器、rosbag、生命周期节点
- ROS 2命令行工具集(ros2 pkg/ros2 node/ros2 topic/ros2 service/ros2 param等)
- 实操实验:Turtlesim仿真交互、自定义消息/服务/动作、单发布订阅节点开发
- ROS 2 Launch文件(XML+Python两种写法)批量启动多节点
- rqt_reconfigure动态参数实时调参
- 配套编译规则:ament_cmake、ament_python编译配置
2.1 ROS 2三层整体架构总览
ROS 2完整架构划分为三个层级,层级自上而下解耦,各司其职,与ROS 1架构逻辑同源但底层实现完全重构:
- 文件系统层(Filesystem Level):定义源码、功能包、配置文件的目录规范,管理项目工程结构;
- 计算图层(Computation Graph Level):运行时分布式通信网络,节点、话题、服务、参数等实体在此完成数据交互;
- 开源社区层(Community Level):全球共享的软件发行版、源码仓库、官方文档、问答平台、工具生态。
2.1.1 架构层级对比(ROS1 Noetic vs ROS2 Lyrical)
| 层级 | ROS 1 Noetic核心特征 | ROS 2 Lyrical核心改进 |
|---|---|---|
| 文件系统层 | catkin编译,Stack综合包,仅msg/srv | ament编译体系,元功能包metapackage,新增Action通信接口,支持Python原生ament_python |
| 计算图层 | 中心化Master单故障点,TCPROS自定义协议 | 去中心化DDS自动发现,无中心节点;新增生命周期节点、动作Action、分布式参数服务器、SROS2加密通信 |
| 社区层 | Wiki、ROS Answers、Github源码仓 | ROS Index、docs.ros.org、Docker官方镜像、ROS Discourse论坛、官方CI自动构建 |
2.2 理解ROS 2 文件系统层
文件系统层统一规范所有机器人项目代码组织逻辑,解决多包依赖混乱、编译配置不统一问题,核心层级关系如下图:

2.2.1 文件系统层级结构图
#mermaid-svg-VoIwhxdTcm1vYfSv{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-VoIwhxdTcm1vYfSv .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-VoIwhxdTcm1vYfSv .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-VoIwhxdTcm1vYfSv .error-icon{fill:#552222;}#mermaid-svg-VoIwhxdTcm1vYfSv .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-VoIwhxdTcm1vYfSv .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-VoIwhxdTcm1vYfSv .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-VoIwhxdTcm1vYfSv .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-VoIwhxdTcm1vYfSv .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-VoIwhxdTcm1vYfSv .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-VoIwhxdTcm1vYfSv .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-VoIwhxdTcm1vYfSv .marker{fill:#333333;stroke:#333333;}#mermaid-svg-VoIwhxdTcm1vYfSv .marker.cross{stroke:#333333;}#mermaid-svg-VoIwhxdTcm1vYfSv svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-VoIwhxdTcm1vYfSv p{margin:0;}#mermaid-svg-VoIwhxdTcm1vYfSv .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-VoIwhxdTcm1vYfSv .cluster-label text{fill:#333;}#mermaid-svg-VoIwhxdTcm1vYfSv .cluster-label span{color:#333;}#mermaid-svg-VoIwhxdTcm1vYfSv .cluster-label span p{background-color:transparent;}#mermaid-svg-VoIwhxdTcm1vYfSv .label text,#mermaid-svg-VoIwhxdTcm1vYfSv span{fill:#333;color:#333;}#mermaid-svg-VoIwhxdTcm1vYfSv .node rect,#mermaid-svg-VoIwhxdTcm1vYfSv .node circle,#mermaid-svg-VoIwhxdTcm1vYfSv .node ellipse,#mermaid-svg-VoIwhxdTcm1vYfSv .node polygon,#mermaid-svg-VoIwhxdTcm1vYfSv .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-VoIwhxdTcm1vYfSv .rough-node .label text,#mermaid-svg-VoIwhxdTcm1vYfSv .node .label text,#mermaid-svg-VoIwhxdTcm1vYfSv .image-shape .label,#mermaid-svg-VoIwhxdTcm1vYfSv .icon-shape .label{text-anchor:middle;}#mermaid-svg-VoIwhxdTcm1vYfSv .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-VoIwhxdTcm1vYfSv .rough-node .label,#mermaid-svg-VoIwhxdTcm1vYfSv .node .label,#mermaid-svg-VoIwhxdTcm1vYfSv .image-shape .label,#mermaid-svg-VoIwhxdTcm1vYfSv .icon-shape .label{text-align:center;}#mermaid-svg-VoIwhxdTcm1vYfSv .node.clickable{cursor:pointer;}#mermaid-svg-VoIwhxdTcm1vYfSv .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-VoIwhxdTcm1vYfSv .arrowheadPath{fill:#333333;}#mermaid-svg-VoIwhxdTcm1vYfSv .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-VoIwhxdTcm1vYfSv .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-VoIwhxdTcm1vYfSv .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-VoIwhxdTcm1vYfSv .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-VoIwhxdTcm1vYfSv .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-VoIwhxdTcm1vYfSv .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-VoIwhxdTcm1vYfSv .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-VoIwhxdTcm1vYfSv .cluster text{fill:#333;}#mermaid-svg-VoIwhxdTcm1vYfSv .cluster span{color:#333;}#mermaid-svg-VoIwhxdTcm1vYfSv div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-VoIwhxdTcm1vYfSv .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-VoIwhxdTcm1vYfSv rect.text{fill:none;stroke-width:0;}#mermaid-svg-VoIwhxdTcm1vYfSv .icon-shape,#mermaid-svg-VoIwhxdTcm1vYfSv .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-VoIwhxdTcm1vYfSv .icon-shape p,#mermaid-svg-VoIwhxdTcm1vYfSv .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-VoIwhxdTcm1vYfSv .icon-shape .label rect,#mermaid-svg-VoIwhxdTcm1vYfSv .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-VoIwhxdTcm1vYfSv .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-VoIwhxdTcm1vYfSv .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-VoIwhxdTcm1vYfSv :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} Filesystem Level 文件系统层
Metapackage 元功能包
Package 普通功能包
package.xml 功能包清单
msg 自定义消息
srv 双向服务
action 长时动作接口
src/include 源代码/头文件
launch 启动文件
cfg 动态参数配置
其他资源:urdf/模型/脚本
对应原图逻辑:元功能包聚合一组功能相近的普通功能包,普通功能包包含程序代码、消息、服务、启动文件、清单配置。
2.2.2 核心概念定义
1)功能包 Package
ROS 2软件分发、编译的最小单元,必须包含package.xml清单文件,支持两种编译模板:
ament_cmake:C++项目,适配机器人算法、硬件驱动;ament_python:纯Python项目,快速原型、数据处理脚本。

标准功能包目录结构(以turtlesim为例):
turtlesim/
├── CMakeLists.txt / setup.py # 编译构建文件
├── package.xml # 功能包清单
├── images/ # 静态资源图片
├── include/turtlesim/ # C++头文件
├── launch/ # 批量启动文件
│ └── multisim.launch.py
├── msg/ # 自定义消息
│ ├── Color.msg
│ └── Pose.msg
├── src/ # C++源码
│ ├── turtle_frame.cpp
│ └── turtlesim.cpp
├── srv/ # 服务接口
│ ├── Kill.srv
│ ├── SetPen.srv
│ └── Spawn.srv
└── action/ # ROS2独有:长时动作接口
2)功能包清单 package.xml
描述包名、版本、许可证、编译依赖、运行依赖,核心标签:
<buildtool_depend>ament_cmake</buildtool_depend>:指定编译工具;<build_depend>:编译阶段依赖包;<exec_depend>:程序运行时依赖(对应ROS1的run_depend);
元功能包额外添加<metapackage/>导出标记,仅聚合其他包,无源码。
3)元功能包 Metapackage
仅包含package.xml,无源代码、可执行程序,通过<exec_depend>批量引用一组功能包,例如nav2导航元包、ros_tutorials教程合集,替代ROS1的Stack功能包集。
元功能包package.xml关键片段:
xml
<package>
<name>ros_tutorials</name>
<version>0.10.0</version>
<buildtool_depend>ament_cmake</buildtool_depend>
<exec_depend>roscpp_tutorials</exec_depend>
<exec_depend>rclpy_tutorials</exec_depend>
<exec_depend>turtlesim</exec_depend>
<export>
<metapackage/>
</export>
</package>
4)消息 msg
定义节点间异步传输的数据结构,存放于包内msg/目录,.msg文件,支持基础类型、嵌套自定义消息、Header时间戳帧标识。
标准基础数据类型兼容ROS1,新增ROS 2专属内置类型;std_msgs/msg/Header内置seq序列号、timestamp时间戳、frame_id坐标系标识,用于机器人定位、感知数据同步。
5)服务 srv
短同步请求-应答通信接口,.srv文件用---分割请求段、应答段,适合单次快速查询(读取传感器参数、清除画布)。
6)动作 action(ROS 2独有)
长耗时异步交互接口,拆分请求、实时反馈、最终结果 三部分,.action文件,适用于导航、机械臂运动规划等长时间任务,ROS 1无原生支持。
2.2.3 工作空间 Workspace
工作空间是存放多套源码包的顶层文件夹,ROS 2采用colcon编译工具,固定三层子目录:
- src 源空间 :存放所有自建/克隆功能包,内置
CMakeLists.txt(colcon初始化生成); - build 编译空间:缓存CMake配置、中间编译文件;
- install 安装空间:编译完成的可执行文件、消息头文件、启动脚本,无需系统安装即可直接测试(替代ROS1的devel)。
工作空间基础操作
bash
# 创建空工作空间
mkdir -p ~/ros2_ws/src
cd ~/ros2_ws/src
colcon init-workspace .
# 编译全部功能包
cd ~/ros2_ws
colcon build
# 仅编译指定包
colcon build --packages-select chapter2_tutorials
# 加载编译后的环境
source install/setup.bash
# 永久写入终端配置
echo "source ~/ros2_ws/install/setup.bash" >> ~/.bashrc
source ~/.bashrc
2.2.4 ROS 2文件系统命令行工具
ROS 2重构全套包管理工具,统一前缀ros2 pkg,替代ROS1的rospack/roscd/rosls:
| 功能 | ROS 1命令 | ROS 2 Lyrical等效命令 |
|---|---|---|
| 查找包路径 | rospack find turtlesim | ros2 pkg prefix turtlesim |
| 进入包目录 | roscd turtlesim | cd $(ros2 pkg prefix turtlesim)/share/turtlesim |
| 列出包内文件 | rosls turtlesim | ls $(ros2 pkg prefix turtlesim)/share/turtlesim |
| 查看包依赖 | rospack depends pkg | ros2 pkg list-deps pkg |
| 创建C++功能包 | catkin_create_pkg | ros2 pkg create --build-type ament_cmake pkg_name deps |
| 创建Python功能包 | 无原生命令 | ros2 pkg create --build-type ament_python pkg_name |
创建本章示例包完整命令(C++):
bash
cd ~/ros2_ws/src
ros2 pkg create --build-type ament_cmake chapter2_tutorials std_msgs rclcpp rclpy
2.3 理解ROS 2计算图层(核心运行时网络)
计算图是ROS 2程序运行时构建的分布式通信网络,所有节点、数据、服务、参数都在此交互。核心变革:取消中心化Master,依靠DDS中间件完成节点自动发现,支持跨多机、跨操作系统实时通信。

2.3.1 计算图核心实体总览
#mermaid-svg-JOZxg9BzZtFGlxWH{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-JOZxg9BzZtFGlxWH .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-JOZxg9BzZtFGlxWH .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-JOZxg9BzZtFGlxWH .error-icon{fill:#552222;}#mermaid-svg-JOZxg9BzZtFGlxWH .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-JOZxg9BzZtFGlxWH .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-JOZxg9BzZtFGlxWH .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-JOZxg9BzZtFGlxWH .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-JOZxg9BzZtFGlxWH .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-JOZxg9BzZtFGlxWH .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-JOZxg9BzZtFGlxWH .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-JOZxg9BzZtFGlxWH .marker{fill:#333333;stroke:#333333;}#mermaid-svg-JOZxg9BzZtFGlxWH .marker.cross{stroke:#333333;}#mermaid-svg-JOZxg9BzZtFGlxWH svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-JOZxg9BzZtFGlxWH p{margin:0;}#mermaid-svg-JOZxg9BzZtFGlxWH .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-JOZxg9BzZtFGlxWH .cluster-label text{fill:#333;}#mermaid-svg-JOZxg9BzZtFGlxWH .cluster-label span{color:#333;}#mermaid-svg-JOZxg9BzZtFGlxWH .cluster-label span p{background-color:transparent;}#mermaid-svg-JOZxg9BzZtFGlxWH .label text,#mermaid-svg-JOZxg9BzZtFGlxWH span{fill:#333;color:#333;}#mermaid-svg-JOZxg9BzZtFGlxWH .node rect,#mermaid-svg-JOZxg9BzZtFGlxWH .node circle,#mermaid-svg-JOZxg9BzZtFGlxWH .node ellipse,#mermaid-svg-JOZxg9BzZtFGlxWH .node polygon,#mermaid-svg-JOZxg9BzZtFGlxWH .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-JOZxg9BzZtFGlxWH .rough-node .label text,#mermaid-svg-JOZxg9BzZtFGlxWH .node .label text,#mermaid-svg-JOZxg9BzZtFGlxWH .image-shape .label,#mermaid-svg-JOZxg9BzZtFGlxWH .icon-shape .label{text-anchor:middle;}#mermaid-svg-JOZxg9BzZtFGlxWH .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-JOZxg9BzZtFGlxWH .rough-node .label,#mermaid-svg-JOZxg9BzZtFGlxWH .node .label,#mermaid-svg-JOZxg9BzZtFGlxWH .image-shape .label,#mermaid-svg-JOZxg9BzZtFGlxWH .icon-shape .label{text-align:center;}#mermaid-svg-JOZxg9BzZtFGlxWH .node.clickable{cursor:pointer;}#mermaid-svg-JOZxg9BzZtFGlxWH .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-JOZxg9BzZtFGlxWH .arrowheadPath{fill:#333333;}#mermaid-svg-JOZxg9BzZtFGlxWH .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-JOZxg9BzZtFGlxWH .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-JOZxg9BzZtFGlxWH .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-JOZxg9BzZtFGlxWH .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-JOZxg9BzZtFGlxWH .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-JOZxg9BzZtFGlxWH .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-JOZxg9BzZtFGlxWH .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-JOZxg9BzZtFGlxWH .cluster text{fill:#333;}#mermaid-svg-JOZxg9BzZtFGlxWH .cluster span{color:#333;}#mermaid-svg-JOZxg9BzZtFGlxWH div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-JOZxg9BzZtFGlxWH .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-JOZxg9BzZtFGlxWH rect.text{fill:none;stroke-width:0;}#mermaid-svg-JOZxg9BzZtFGlxWH .icon-shape,#mermaid-svg-JOZxg9BzZtFGlxWH .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-JOZxg9BzZtFGlxWH .icon-shape p,#mermaid-svg-JOZxg9BzZtFGlxWH .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-JOZxg9BzZtFGlxWH .icon-shape .label rect,#mermaid-svg-JOZxg9BzZtFGlxWH .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-JOZxg9BzZtFGlxWH .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-JOZxg9BzZtFGlxWH .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-JOZxg9BzZtFGlxWH :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} Computation Graph Level 计算图层
Node 节点
DDS分布式发现服务
Topic 话题 异步发布订阅
Service 服务 同步请求应答
Action 动作 长时任务反馈
Parameter Server 分布式参数服务器
Message 消息数据结构
Bag2 消息录制回放包
Lifecycle Node 生命周期节点
2.3.2 各实体详细定义
1)节点 Node
独立可执行进程,实现单一功能(读取相机、底盘控制、路径规划),遵循单一职责 设计;使用rclcpp(C++)/rclpy(Python)客户端库开发。
- 每个节点拥有全局唯一名称,支持运行时重映射名称、话题、参数;
- 新增Lifecycle生命周期节点:标准化配置/激活/休眠/关闭流程,适合工业机器人稳定控制;
- Nodelet机制整合进rclcpp,同一进程内多节点共享内存,大幅降低高带宽传感器(激光雷达、深度相机)网络延迟。
节点管理命令:
bash
# 列出所有运行节点
ros2 node list
# 查看节点完整发布/订阅/服务信息
ros2 node info /turtlesim
# 启动节点(等效rosrun)
ros2 run turtlesim turtlesim_node
# 运行时重映射话题名称
ros2 run turtlesim turtle_teleop_key --ros-args -r /turtle1/cmd_vel:=/robot/cmd_vel
# 传递私有参数
ros2 run turtlesim turtlesim_node --ros-args -p background_r:=50
2)DDS分布式发现(替代ROS1 Master)
ROS 2底层通信标准为DDS(Data Distribution Service),Lyrical默认搭载Fast-DDS,无中心节点:
- 节点上线自动组播广播自身发布/订阅/服务信息;
- 匹配话题/服务类型的节点自动建立点对点通信;
- 支持QoS服务质量策略:可靠传输、尽力传输、历史消息缓存,适配实时控制/视频流不同场景;
- 支持SROS2加密,跨设备通信数据加密,工业安全合规。
3)话题 Topic
异步一对多/多对多通信总线,发布者与订阅者完全解耦,无需感知对方存在:
- 强类型约束:发布与订阅消息类型必须完全匹配;
- 传输模式:TCP可靠传输、UDP低延迟实时传输;
话题操作工具ros2 topic:
bash
ros2 topic list # 列出所有活跃话题
ros2 topic echo /turtle1/pose # 打印话题实时消息
ros2 topic pub /turtle1/cmd_vel geometry_msgs/msg/Twist "{linear: {x: 1.0}, angular: {z: 0.5}}" -r 10
ros2 topic type /turtle1/cmd_vel # 查看话题消息类型
ros2 topic hz /turtle1/pose # 统计话题发布频率
4)服务 Service
同步RPC通信,客户端发送请求、服务端阻塞返回应答,适合瞬时查询操作:
工具ros2 service:
bash
ros2 service list
ros2 service call /clear std_srvs/srv/Empty
ros2 service type /spawn
5)动作 Action(ROS 2独有)
针对导航、机械臂运动等长耗时任务,三层通信:请求指令 + 过程实时反馈 + 最终执行结果。
工具ros2 action:
bash
ros2 action list
ros2 action send_goal /navigate_to_pose nav2_msgs/action/NavigateToPose ...
6)分布式参数服务器 Parameter Server
取消ROS1集中式参数服务,参数归属对应节点本地存储,全网络可访问读写,支持整数、浮点、字符串、布尔、数组、二进制数据。
工具ros2 param:
bash
ros2 param list /turtlesim
ros2 param get /turtlesim background_b
ros2 param set /turtlesim background_b 120
ros2 param dump /turtlesim --output params.yaml # 保存参数文件
ros2 param load /turtlesim params.yaml # 加载参数配置
7)Bag2 消息记录包
ROS 2使用.bag2格式替代ROS1 .bag,性能更高、支持多存储后端(sqlite3/文件),录制/回放全话题、服务、动作数据,用于算法离线调试:
bash
# 录制所有话题
ros2 bag record -o sensor_data /camera/image_raw /scan
# 回放数据包
ros2 bag play sensor_data
# 查看bag信息
ros2 bag info sensor_data
2.3.3 rqt_graph可视化计算图
rqt_graph图形化展示所有节点、话题发布订阅关系,直观调试通信链路:
bash
rqt_graph
界面可清晰区分发布者、订阅者、服务服务器/客户端,替代ROS1节点状态图。
2.4 ROS 2开源社区层
社区层提供全球统一的资源共享渠道,ROS 2社区体系相比ROS1全面升级:
- 发行版Distribution:Lyrical为2026 LTS版本,5年长期官方维护,配套Ubuntu26.04系统二进制源;
- 源码仓库Repository:官方仓库ros2/组织,第三方功能包托管Github/Gitlab;
- 官方文档docs.ros.org:替代传统ROS Wiki,分版本、可检索、多语言教程;
- ROS Discourse论坛:替代邮件列表,技术问答、开发交流;
- ROS Index:检索所有开源功能包、源码、依赖;
- Bug追踪系统:各仓库Github Issues提交缺陷与功能需求;
- Docker官方镜像:一键部署干净ROS 2环境,无系统污染。
2.5 实操实验:Turtlesim仿真交互

实验前置
完整安装ROS 2 Lyrical桌面版,自动包含turtlesim教程包。
步骤1:启动仿真海龟节点
终端1:
bash
ros2 run turtlesim turtlesim_node
弹出蓝色画布海龟窗口。
步骤2:键盘遥控海龟移动
终端2:
bash
ros2 run turtlesim turtle_teleop_key
选中终端2窗口,方向键控制海龟,画布绘制运动轨迹。
步骤3:查看通信链路
bash
# 查看节点
ros2 node list
# 查看话题
ros2 topic list
# 打印速度指令话题
ros2 topic echo /turtle1/cmd_vel
# 手动发布指令让海龟画圆
ros2 topic pub /turtle1/cmd_vel geometry_msgs/msg/Twist "{linear: {x: 0.5}, angular: {z: 0.8}}" -r 10
步骤4:服务调用实操
bash
# 清空画布轨迹
ros2 service call /clear std_srvs/srv/Empty
# 生成新海龟
ros2 service call /spawn turtlesim/srv/Spawn "{x:3.0, y:3.0, theta:0.0, name:'turtle2'}"
# 删除海龟
ros2 service call /kill turtlesim/srv/Kill "{name:'turtle2'}"
步骤5:修改画布背景参数
bash
# 读取蓝色通道值
ros2 param get /turtlesim background_b
# 修改蓝色通道,画布变色
ros2 param set /turtlesim background_b 80
2.6 实操:自定义消息、服务、单发布订阅节点
2.6.1 创建自定义消息msg
-
在chapter2_tutorials新建
msg文件夹,创建CustomNum.msgint32 A
int32 B
int32 C -
修改package.xml添加依赖:
xml
<buildtool_depend>ament_cmake</buildtool_depend>
<build_depend>rosidl_default_generators</build_depend>
<exec_depend>rosidl_default_runtime</exec_depend>
<depend>std_msgs</depend>
- CMakeLists.txt添加消息生成规则:
cmake
find_package(ament_cmake REQUIRED)
find_package(std_msgs REQUIRED)
find_package(rosidl_default_generators REQUIRED)
rosidl_generate_interfaces(${PROJECT_NAME}
"msg/CustomNum.msg"
)
ament_export_dependencies(rosidl_default_runtime)
- 编译并验证消息:
bash
colcon build --packages-select chapter2_tutorials
source install/setup.bash
ros2 interface show chapter2_tutorials/msg/CustomNum
2.6.2 C++发布/订阅节点开发
发布节点 publisher.cpp
cpp
#include "rclcpp/rclcpp.hpp"
#include "chapter2_tutorials/msg/custom_num.hpp"
using namespace std::chrono_literals;
class PublisherNode : public rclcpp::Node
{
public:
PublisherNode() : Node("example_pub")
{
pub_ = this->create_publisher<chapter2_tutorials::msg::CustomNum>("num_topic", 10);
timer_ = this->create_wall_timer(100ms, std::bind(&PublisherNode::timer_cb, this));
}
private:
void timer_cb()
{
auto msg = chapter2_tutorials::msg::CustomNum();
msg.A = 1; msg.B = 2; msg.C = 3;
RCLCPP_INFO(this->get_logger(), "Publish A:%d B:%d C:%d", msg.A, msg.B, msg.C);
pub_->publish(msg);
}
rclcpp::Publisher<chapter2_tutorials::msg::CustomNum>::SharedPtr pub_;
rclcpp::TimerBase::SharedPtr timer_;
};
int main(int argc, char * argv[])
{
rclcpp::init(argc, argv);
rclcpp::spin(std::make_shared<PublisherNode>());
rclcpp::shutdown();
return 0;
}
订阅节点 subscriber.cpp
cpp
#include "rclcpp/rclcpp.hpp"
#include "chapter2_tutorials/msg/custom_num.hpp"
class SubNode : public rclcpp::Node
{
public:
SubNode() : Node("example_sub")
{
sub_ = this->create_subscription<chapter2_tutorials::msg::CustomNum>(
"num_topic", 10, std::bind(&SubNode::callback, this, std::placeholders::_1));
}
private:
void callback(const chapter2_tutorials::msg::CustomNum::SharedPtr msg)
{
RCLCPP_INFO(this->get_logger(), "Recv A:%d B:%d C:%d", msg->A, msg->B, msg->C);
}
rclcpp::Subscription<chapter2_tutorials::msg::CustomNum>::SharedPtr sub_;
};
int main(int argc, char * argv[])
{
rclcpp::init(argc, argv);
rclcpp::spin(std::make_shared<SubNode>());
rclcpp::shutdown();
return 0;
}
CMakeLists.txt添加编译规则
cmake
add_executable(publisher src/publisher.cpp)
ament_target_dependencies(publisher rclcpp std_msgs)
add_executable(subscriber src/subscriber.cpp)
ament_target_dependencies(subscriber rclcpp std_msgs)
install(TARGETS
publisher subscriber
DESTINATION lib/${PROJECT_NAME}
)
编译运行
bash
colcon build --packages-select chapter2_tutorials
source install/setup.bash
# 终端1启动发布端
ros2 run chapter2_tutorials publisher
# 终端2启动订阅端
ros2 run chapter2_tutorials subscriber
2.7 ROS 2 Launch启动文件(批量启动多节点)
ROS 2推荐Python格式launch文件(替代ROS1 XML),一键启动多个节点、配置参数、自动加载DDS配置,无需多开终端。

示例 launch/two_nodes.launch.py
python
from launch import LaunchDescription
from launch_ros.actions import Node
def generate_launch_description():
pub_node = Node(
package="chapter2_tutorials",
executable="publisher",
name="pub_node"
)
sub_node = Node(
package="chapter2_tutorials",
executable="subscriber",
name="sub_node"
)
return LaunchDescription([pub_node, sub_node])
运行launch文件
bash
ros2 launch chapter2_tutorials two_nodes.launch.py
ros2 launch会自动拉起DDS发现服务,无需手动启动roscore(ROS1特有)。
2.8 rqt_reconfigure 动态参数实时调参
ROS 2完整兼容动态参数重配置,运行时无需重启节点修改参数,用于PID调试、传感器阈值调整。

- 安装工具:
bash
sudo apt install ros-lyrical-rqt-reconfigure
- 启动自定义节点后打开可视化调参界面:
bash
ros2 run rqt_reconfigure rqt_reconfigure
界面实时展示节点所有可动态修改参数,滑动/输入框修改后节点立即生效,日志同步输出变更记录。
本章小结
- ROS 2三层架构区分文件系统(工程规范)、计算图(运行通信)、开源社区(资源共享),底层DDS去中心化是和ROS1最大差异;
- ament/colcon替代catkin,新增Action长时通信接口、bag2数据录制、生命周期节点;
- 全套
ros2统一命令行工具,覆盖包、节点、话题、服务、参数、bag操作; - Turtlesim、自定义消息/服务、launch文件、动态参数四大实操完整覆盖日常开发基础流程;
- ROS 2无中心化Master,跨机分布式通信原生支持,适配嵌入式、工业机器人多设备组网。
下一章将讲解ROS 2可视化与调试工具:RViz2、rqt工具集、日志分析、rosbag离线算法调试。