ROS
Ubuntu 24.04 安装 ROS 2 Jazzy 完整指南

什么是 ROS 2?
ROS 2(Robot Operating System 2)是 ROS 的下一代版本,是一个开源的机器人操作系统框架。ROS 2 专为现代机器人应用设计,提供了分布式计算、实时性能、多平台支持和更好的安全性等特性。
ROS 2 的主要特点
- 分布式架构:支持多机器人和多计算机之间的通信
- 实时性能:提供实时通信和调度能力
- 跨平台支持:支持 Linux、Windows 和 macOS
- 多种编程语言:支持 C++、Python、Java 等
- 模块化设计:通过节点(Node)和话题(Topic)实现松耦合的通信
- 丰富的工具链:提供命令行工具、可视化工具(rqt)和调试工具
ROS 2 Jazzy 是 ROS 2 的一个长期支持(LTS)版本,支持 Ubuntu Noble 24.04 的 amd64 和 arm64 架构。在网络通畅的情况下,安装较为顺利,未发现明显问题。
1. 系统环境准备
1.1 设置 Locale
设置系统 locale 为 UTF-8 编码,确保 ROS 2 正常运行:
# 检查当前 locale
locale
# 如果不是 UTF-8,先安装 locales
sudo apt update && sudo apt install locales
# 生成 en_US.UTF-8 locale
sudo locale-gen en_US en_US.UTF-8
# 更新系统 locale
sudo update-locale LC_ALL=en_US.UTF-8 LANG=en_US.UTF-8
# 设置当前会话的 locale
export LANG=en_US.UTF-8
# 再次检查 locale 确认设置成功
locale
1.2 添加 ROS 2 APT 源
确保启用 Ubuntu Universe 仓库,并添加 ROS 2 的 APT 源:
# 安装软件属性管理工具
sudo apt install software-properties-common
# 启用 Universe 仓库
sudo add-apt-repository universe
# 安装 curl(如果尚未安装)
sudo apt update && sudo apt install curl -y
# 获取最新版本的 ROS APT 源包
export ROS_APT_SOURCE_VERSION=$(curl -s https://api.github.com/repos/ros-infrastructure/ros-apt-source/releases/latest | grep -F "tag_name" | awk -F\" '{print $4}')
# 下载 ROS 2 APT 源 deb 包
curl -L -o /tmp/ros2-apt-source.deb "https://github.com/ros-infrastructure/ros-apt-source/releases/download/${ROS_APT_SOURCE_VERSION}/ros2-apt-source_${ROS_APT_SOURCE_VERSION}.$(. /etc/os-release && echo ${UBUNTU_CODENAME:-${VERSION_CODENAME}})_all.deb"
# 安装 APT 源包
sudo dpkg -i /tmp/ros2-apt-source.deb
1.3 安装开发工具
# 更新包列表并安装 ROS 开发工具
sudo apt update && sudo apt install ros-dev-tools
2. 安装 ROS 2
2.1 安装 ROS 2 Desktop
# 更新系统包
sudo apt update
sudo apt upgrade
# 安装 ROS 2 Jazzy Desktop(包含可视化工具)
sudo apt install ros-jazzy-desktop
2.2 设置环境变量
# 临时设置当前会话的环境变量
source /opt/ros/jazzy/setup.bash
3. 测试 FastDDS 通信
FastDDS 是 ROS 2 的默认通信中间件。通过以下步骤测试安装是否成功:
- 在第一个终端中启动 talker 节点:
ros2 run demo_nodes_cpp talker
- 在第二个终端中启动 listener 节点:
# 先设置环境变量
source /opt/ros/jazzy/setup.bash
# 运行 listener
ros2 run demo_nodes_py listener
如果两个终端都能正常打印消息,说明安装成功:

4. 配置 Shell 启动脚本
ROS 2 的 shell 工作区概念允许在同一台电脑上同时安装多个不同版本的 ROS,通过启动脚本来切换版本。如果不加载安装文件,您将无法访问 ROS 2 命令,也无法查找或使用 ROS 2 软件包。
4.1 添加到 ~/.bashrc
# 编辑 ~/.bashrc 文件(使用您喜欢的编辑器,如 nano、vim 或 subl)
nano ~/.bashrc
# 或者使用 Sublime Text
subl ~/.bashrc
在文件末尾添加以下内容:
source /opt/ros/jazzy/setup.bash
4.2 使配置生效
# 重新加载配置
source ~/.bashrc
4.3 验证配置
打开一个新的命令行窗口,直接输入 ros2,如果显示如下内容,说明配置成功:

5. 使用 Turtlesim
Turtlesim 是一个轻量级的 ROS 2 学习模拟器。它以最基本的层面演示了 ROS 2 的功能,让您了解以后使用真实机器人或机器人模拟器时会遇到的问题。
5.1 安装 Turtlesim
sudo apt update
sudo apt install ros-jazzy-turtlesim
5.2 验证安装
ros2 pkg executables turtlesim
如果显示以下内容,说明安装成功:
turtlesim draw_square
turtlesim mimic
turtlesim turtle_teleop_key
turtlesim turtlesim_node
5.3 运行 Turtlesim
- 启动 Turtlesim 节点:
ros2 run turtlesim turtlesim_node
- 在另一个终端中启动键盘控制节点:
ros2 run turtlesim turtle_teleop_key
保持 turtle_teleop_key 的窗口处于激活状态,通过方向键可以控制乌龟移动。此时乌龟指代的是无人机的移动和控制方式。

6. 安装和使用 rqt
rqt 是 ROS 2 的图形用户界面 (GUI) 工具。rqt 中的所有操作都可以在命令行中完成,但 rqt 提供了一种更友好的方式来操作 ROS 2 元素。
6.1 安装 rqt
sudo apt update
sudo apt install '~nros-jazzy-rqt*'
6.2 运行 rqt
rqt
6.3 使用 rqt 调用服务
在 Turtlesim 运行时,可以通过 rqt 调用服务:
- 从下拉菜单选择 Plugins → Services → Service Caller
- 选择服务
/spawn - 在此处可以直接调整生成位置(x、y 坐标)、实例名称等参数
- 点击 Call 按钮

如果服务调用成功,您应该会看到一只新的海龟(同样是随机设计的)在您输入的 x 和 y 坐标处生成。

6.4 控制新创建的海龟实例
如果要控制新创建的实例 turtle2,可以在新的终端中执行:
ros2 run turtlesim turtle_teleop_key --ros-args --remap turtle1/cmd_vel:=turtle2/cmd_vel
然后在这个终端控制即可。
如果您刷新 rqt 中的服务列表,您还会看到除了 /turtle1/... 之外,现在还有与新海龟相关的服务 /turtle2/...。
参考文档
理解 ROS 2 的 node 和 topic
1. 理解 node
node 是 ROS 2 实现模块化的基本组件。ROS 中的每个 node 都应负责单一的模块化功能,例如控制车轮电机或发布来自激光测距仪的传感器数据。每个 node 都可以通过 topic、服务、动作或参数与其他 node 发送和接收数据。
一个完整的机器人系统由许多协同工作的 node 组成。在 ROS 2 中,一个可执行文件(C++ 程序、Python 程序等)可以包含一个或多个 node。

上图展示了两个 ROS 2 node 是如何交互的。
1.1 ROS 2 启动命令
使用以下命令启动 node:
ros2 run <package_name> <executable_name>
例如:
ros2 run demo_nodes_cpp talker
其中 demo_nodes_cpp 是包名字,talker 是可执行文件名。
1.2 查看 node 列表
node 名称可以使用以下命令查找:
ros2 node list

可以看到 /talker 已经显示出来了。
1.3 node 名称重映射(Remapping)
通过 --remap 参数可以重映射 node 名称:
ros2 run turtlesim turtlesim_node --ros-args --remap __node:=my_turtle
上述命令中 --remap __node:=my_turtle 将 node 名称定义为 my_turtle,通过 ros2 node list 应该也可以看到这个新建的实例 /my_turtle。
1.4 查看 node 信息
使用以下命令查看 node 的详细信息:
ros2 node info <node_name>
例如:
ros2 node info /talker
注意要加斜杠。

2. 理解 topic
在上个章节的图片中,我们已经可以看到,publisher node 通过 topic 将信息发送给 subscriber 的过程,只要一个 node 订阅了 topic,就可以收到对应的消息。
ROS 2 将复杂的系统分解为许多模块化 node。topic 是 ROS 图的重要元素,充当 node 交换消息的总线。

一个 node 可以将数据发布到任意数量的 topic,并同时订阅任意数量的 topic。

topic 是在 node 之间以及系统不同部分之间移动数据的主要方式之一。
2.1 使用 rqt_graph 检查通信状态
通过 rqt_graph 可以可视化检查当前 ROS 2 系统的通信状态:
- 打开第一个终端,启动 talker node:
ros2 run demo_nodes_cpp talker
- 打开第二个终端,启动 listener node:
ros2 run demo_nodes_cpp listener
- 使用以下命令打开 rqt_graph:
ros2 run rqt_graph rqt_graph
可以看到 talker 和 listener 通过 /chatter 这个 topic 建立通信。node 正在向 topic 发布数据,并且该 node 订阅了该 topic 以接收数据。
rqt_graph 的突出显示功能在检查具有许多 node 和 topic 以多种不同方式连接的更复杂的系统时非常有用。

2.2 查看 topic 列表
在新终端中运行以下命令将返回系统中当前活动的所有 topic 的列表:
ros2 topic list
重要:使用 -t 参数可以在括号中附加 topic 类型:
ros2 topic list -t
输出示例:
/chatter [std_msgs/msg/String]
/parameter_events [rcl_interfaces/msg/ParameterEvent]
/rosout [rcl_interfaces/msg/Log]
topic 类型是本文档的重要内容,后续对 topic 的命令行应用都基于类型进行。
2.3 查看 topic 信息
topic 不必只是一对一的交流;它们可以是一对多、多对一或多对多。通过以下命令来查看当前订阅数量:
ros2 topic info /chatter
返回示例:
Type: std_msgs/msg/String
Publisher count: 1
Subscription count: 1
2.4 查看 topic 数据
使用以下命令查看正在发布的 topic 数据:
ros2 topic echo <topic_name>
例如:
ros2 topic echo /chatter
注意 topic 名称前要加斜杠。

现在返回 rqt_graph 并取消选中 “debug” 框,可以见到新增的订阅 /_ros2cli_100752,也就是刚才我们通过命令行命令 echo 创建的 node。

2.5 查看接口/数据结构
在前面运行过了 ros2 topic list -t 后,得知了 /chatter 的接口为 [std_msgs/msg/String]。
运行以下命令查看接口定义:
ros2 interface show std_msgs/msg/String
返回:
# This was originally provided as an example message.
# It is deprecated as of Foxy
# It is recommended to create your own semantically meaningful message.
# However if you would like to continue using this please use the equivalent in example_msgs.
string data
可以得知为字符串数据结构,字段为 data。
2.6 发布 topic 消息
得知消息结构后,通过以下命令可以直接从终端发送命令数据到 topic 中:
ros2 topic pub <topic_name> <msg_type> '<args>'
<args> 是要传递给 topic 的实际数据,采用正确的数据结构。如上 interface 为 string data 时,data 就是构建 YAML 字符串的 key。
如下几种方式都可以发布:
- 构建 YAML 字符串发布:
ros2 topic pub /chatter std_msgs/msg/String "{data: 'Hello from manual pub.'}"
可以看到 subscriber node 同时收到了两个 node 的信息。


- 发布空数据:
ros2 topic pub /chatter std_msgs/msg/String
因为很少会使用到手动 pub 消息,其他两种自动构建数据结构并发布的方式暂时不考虑。
消息的时间戳
当发布带时间戳的消息时,pub 有两种方法可以自动填充当前时间。对于带有 std_msgs/msg/Header 的消息,可以将 header 字段设置为 auto 来填充 stamp 字段。
ros2 topic pub /chatter std_msgs/msg/String "{header: \"auto\", data: 'Hello from manual pub.'}"
此时会报错,因为 std_msgs/msg/String 类型没有 header 字段。
2.7 查询 topic 发布频率
使用以下命令来得知对应 topic 的发布频率:
ros2 topic hz <topic>
例如:
ros2 topic hz /chatter
在检测后会返回:
average rate: 1.000
min: 1.000s max: 1.000s std dev: 0.00021s window: 3
2.8 查询 topic 带宽
使用以下命令查询 topic 的带宽使用情况:
ros2 topic bw <topic>
例如:
ros2 topic bw /chatter
输出示例:
Subscribed to [/chatter]
49 B/s from 2 messages
Message size mean: 28 B min: 28 B max: 28 B
39 B/s from 3 messages
Message size mean: 28 B min: 28 B max: 28 B
返回带宽利用率和发布到 topic 的消息数量。
2.9 查询指定类型的 topic
列出给定类型的可用 topic 列表:
ros2 topic find <topic_type>
根据前文可以得知,topic_type 为 ros2 topic list -t 返回的括号中的内容,例如 std_msgs/msg/String。
执行:
ros2 topic find std_msgs/msg/String
输出:
/chatter
3. 总结
node 通过 topic 发布信息,允许任意数量的其他 node 订阅和访问该信息。笔记中使用 rqt_graph 和命令行工具检查了 topic 上多个 node 之间的连接。由此,可以初步理解数据如何在 ROS 2 系统中移动。
4. 参考文档
理解 ROS 2 的 Services, Params 和 Actions
1. 理解 services
services 是 ROS 图中节点通信的另一种方法。services 基于调用和响应模型,而不是主题的pub-sub模型。虽然主题允许节点订阅数据流并获取持续更新,但 services 仅在 client 专门调用时才提供数据。
节点可以使用 ROS 2 中的 services 进行通信。与主题(一种单向通信模式,其中节点发布可供一个或多个订阅者使用的信息)不同,services 是一种请求/响应模式,其中 client 向提供 services node发出请求,services 处理该请求并生成响应。


1.1 查看 ROS 2 当前 services
通过 ros2 service list 返回系统中当前活动的所有 services 的列表。
在两个终端内分别运行 subscriber 和 publisher node:
ros2 run demo_nodes_cpp talker
ros2 run demo_nodes_cpp listener
执行 ros2 service list,返回:
$ ros2 service list
/listener/describe_parameters
/listener/get_parameter_types
/listener/get_parameters
/listener/get_type_description
/listener/list_parameters
/listener/set_parameters
/listener/set_parameters_atomically
/rqt_gui_py_node_103317/describe_parameters
/rqt_gui_py_node_103317/get_parameter_types
/rqt_gui_py_node_103317/get_parameters
/rqt_gui_py_node_103317/get_type_description
/rqt_gui_py_node_103317/list_parameters
/rqt_gui_py_node_103317/set_parameters
/rqt_gui_py_node_103317/set_parameters_atomically
/talker/describe_parameters
/talker/get_parameter_types
/talker/get_parameters
/talker/get_type_description
/talker/list_parameters
/talker/set_parameters
/talker/set_parameters_atomically
可以观察到节点中有相同名称的多个服务,ROS 2 的大部分节点都有这些基础设施服务。
1.2 查看 ROS 2 services 类型
服务具有描述服务的请求和响应数据的结构的类型。服务类型的定义与主题类型类似,不同之处在于服务类型有两部分:一个用于请求的消息,另一个用于响应。
查看 talker 的 services 类型:
ros2 service type /talker/set_parameters
返回:
rcl_interfaces/srv/SetParameters
也可以通过在 services 列表中增加 -t 参数来直接显示所有当前 services 对应的类型:
ros2 service list -t
返回:
/listener/describe_parameters [rcl_interfaces/srv/DescribeParameters]
/listener/get_parameter_types [rcl_interfaces/srv/GetParameterTypes]
/listener/get_parameters [rcl_interfaces/srv/GetParameters]
/listener/get_type_description [type_description_interfaces/srv/GetTypeDescription]
/listener/list_parameters [rcl_interfaces/srv/ListParameters]
/listener/set_parameters [rcl_interfaces/srv/SetParameters]
/listener/set_parameters_atomically [rcl_interfaces/srv/SetParametersAtomically]
/rqt_gui_py_node_103317/describe_parameters [rcl_interfaces/srv/DescribeParameters]
/rqt_gui_py_node_103317/get_parameter_types [rcl_interfaces/srv/GetParameterTypes]
/rqt_gui_py_node_103317/get_parameters [rcl_interfaces/srv/GetParameters]
/rqt_gui_py_node_103317/get_type_description [type_description_interfaces/srv/GetTypeDescription]
/rqt_gui_py_node_103317/list_parameters [rcl_interfaces/srv/ListParameters]
/rqt_gui_py_node_103317/set_parameters [rcl_interfaces/srv/SetParameters]
/rqt_gui_py_node_103317/set_parameters_atomically [rcl_interfaces/srv/SetParametersAtomically]
/talker/describe_parameters [rcl_interfaces/srv/DescribeParameters]
/talker/get_parameter_types [rcl_interfaces/srv/GetParameterTypes]
/talker/get_parameters [rcl_interfaces/srv/GetParameters]
/talker/get_type_description [type_description_interfaces/srv/GetTypeDescription]
/talker/list_parameters [rcl_interfaces/srv/ListParameters]
/talker/set_parameters [rcl_interfaces/srv/SetParameters]
/talker/set_parameters_atomically [rcl_interfaces/srv/SetParametersAtomically]
1.3 查看 ROS 2 services 信息
ros2 service info <service_name>
返回 services 类型以及 services clients 和服务器的计数。
ros2 service info /talker/set_parameters
返回:
Type: rcl_interfaces/srv/SetParameters
Clients count: 0
Services count: 1
1.4 查询指定类型的 services
ros2 service find <type_name>
例如:
ros2 service find rcl_interfaces/srv/DescribeParameters
返回:
/listener/describe_parameters
/rqt_gui_py_node_103317/describe_parameters
/talker/describe_parameters
1.5 查看 services 的接口/协议
与 topic 的接口查询一样,只是查询主体换成了services 类型。例如:
ros2 interface show rcl_interfaces/srv/DescribeParameters
返回:
# A list of parameters of which to get the descriptor.
string[] names
---
# A list of the descriptors of all parameters requested in the same order
# as they were requested. This list has the same length as the list of
# parameters requested.
ParameterDescriptor[] descriptors
string name
uint8 type
string description
#
string additional_constraints
bool read_only false
bool dynamic_typing false
#
FloatingPointRange[<=1] floating_point_range
float64 from_value
float64 to_value
#
#
#
#
float64 step
IntegerRange[<=1] integer_range
int64 from_value
int64 to_value
#
#
#
uint64 step
--- 分隔符上面是请求结构,即调用 services 需要输入的参数,下面是响应结构,即 services 返回的数据结构。注意:同一个 services 类型使用相同的数据结构/协议。
1.6 ROS 2 services 调用
从上文已经得知了调用 services 所需的数据结构,现在可以通过以下命令来调用 services:
ros2 service call <service_name> <service_type> <arguments>
这里尝试调用没有参数的 services:
ros2 service call /talker/list_parameters rcl_interfaces/srv/ListParameters
返回:
waiting for service to become available...
requester: making request: rcl_interfaces.srv.ListParameters_Request(prefixes=[], depth=0)
response:
rcl_interfaces.srv.ListParameters_Response(result=rcl_interfaces.msg.ListParametersResult(names=['qos_overrides./parameter_events.publisher.depth', 'qos_overrides./parameter_events.publisher.durability', 'qos_overrides./parameter_events.publisher.history', 'qos_overrides./parameter_events.publisher.reliability', 'start_type_description_service', 'use_sim_time'], prefixes=['qos_overrides./parameter_events.publisher']))
列出了当前节点拥有的参数。
1.7 ROS 2 services echo
查看 services clients 和 services 服务器之间的数据通信,使用命令 echo 对应的 services:
ros2 service echo <service_name | service_type> <arguments>
echo service_name 或者 service_type 都可以。
ros2 service echo 依赖于 services clients 和 services 服务器的 services 自省功能,该功能默认是禁用的。要启用它,用户必须在创建 services clients 或服务器后调用 configure_introspection。
启动 services 自省演示:
ros2 launch demo_nodes_cpp introspect_services_launch.py
然后打开一个新的终端,启用 services 自省:
ros2 param set /introspection_service service_configure_introspection contents
ros2 param set /introspection_client client_configure_introspection contents
在新终端内,继续执行:
ros2 service echo --flow-style /add_two_ints
可以看到 introspection_client 和 introspection_service 的通信情况,REQUEST_SENT,REQUEST_RECEIVED,RESPONSE_SENT,RESPONSE_RECEIVED 都被展示出来了:
---
info:
event_type: REQUEST_SENT
stamp:
sec: 1762498810
nanosec: 268090535
client_gid: [1, 15, 178, 36, 79, 84, 235, 99, 0, 0, 0, 0, 0, 0, 21, 3]
sequence_number: 387
request: [{a: 2, b: 3}]
response: []
---
info:
event_type: REQUEST_RECEIVED
stamp:
sec: 1762498810
nanosec: 268466526
client_gid: [1, 15, 178, 36, 79, 84, 235, 99, 0, 0, 0, 0, 0, 0, 20, 4]
sequence_number: 387
request: [{a: 2, b: 3}]
response: []
---
info:
event_type: RESPONSE_SENT
stamp:
sec: 1762498810
nanosec: 268538042
client_gid: [1, 15, 178, 36, 79, 84, 235, 99, 0, 0, 0, 0, 0, 0, 20, 4]
sequence_number: 387
request: []
response: [{sum: 5}]
---
info:
event_type: RESPONSE_RECEIVED
stamp:
sec: 1762498810
nanosec: 268637789
client_gid: [1, 15, 178, 36, 79, 84, 235, 99, 0, 0, 0, 0, 0, 0, 21, 3]
sequence_number: 387
request: []
response: [{sum: 5}]
---
2. 理解参数
参数就是 node 的配置,node 将参数存储为不同的数据类型,ROS 2 每个 node 都维护自己的参数。
节点使用参数来定义其默认配置值。您可以从命令行获取和设置参数值。您还可以将参数设置保存到文件中,以便在将来的会话中重新加载它们。
2.1 查看 ROS 2 的参数列表
启动 subscriber 和 publisher node:
ros2 run demo_nodes_cpp talker
ros2 run demo_nodes_cpp listener
查看参数列表:
ros2 param list
返回示例:
/introspection_client:
client_configure_introspection
qos_overrides./parameter_events.publisher.depth
qos_overrides./parameter_events.publisher.durability
qos_overrides./parameter_events.publisher.history
qos_overrides./parameter_events.publisher.reliability
start_type_description_service
use_sim_time
/introspection_service:
qos_overrides./parameter_events.publisher.depth
qos_overrides./parameter_events.publisher.durability
qos_overrides./parameter_events.publisher.history
qos_overrides./parameter_events.publisher.reliability
service_configure_introspection
start_type_description_service
use_sim_time
/listener:
start_type_description_service
use_sim_time
/talker:
qos_overrides./parameter_events.publisher.depth
qos_overrides./parameter_events.publisher.durability
qos_overrides./parameter_events.publisher.history
qos_overrides./parameter_events.publisher.reliability
start_type_description_service
use_sim_time
可以看到节点的 namespace 和其参数,注意:每个 node 都有 use_sim_time。
2.2 查看参数类型
ros2 param get <node_name> <parameter_name>
返回类型和当前值。查看 start_type_description_service 的当前值和类型:
ros2 param get /listener start_type_description_service
返回:
Boolean value is: True
2.3 修改参数
ros2 param set <node_name> <parameter_name> <value>
尝试修改 listener 为 false:
ros2 param set /listener start_type_description_service False
返回:
Setting parameter failed: Trying to set a read-only parameter: start_type_description_service.
传参成功了,但是因为这个参数是只读的,所以无法修改。
2.4 导出 ROS 2 参数
ros2 param dump <node_name>
运行:
ros2 param dump /talker
返回:
/talker:
ros__parameters:
qos_overrides:
/parameter_events:
publisher:
depth: 1000
durability: volatile
history: keep_last
reliability: reliable
start_type_description_service: true
use_sim_time: false
默认将在命令行打印,也可以通过以下命令指定输出文件到当前终端的工作目录:
ros2 param dump /talker > talker.yaml
2.5 加载 ROS 2 参数
使用命令加载参数文件到运行中的 node:
ros2 param load <node_name> <parameter_file>
例如:
ros2 param load /talker talker.yaml
返回:
Set parameter qos_overrides./parameter_events.publisher.depth failed: parameter 'qos_overrides./parameter_events.publisher.depth' cannot be set because it is read-only
Set parameter qos_overrides./parameter_events.publisher.durability failed: parameter 'qos_overrides./parameter_events.publisher.durability' cannot be set because it is read-only
Set parameter qos_overrides./parameter_events.publisher.history failed: parameter 'qos_overrides./parameter_events.publisher.history' cannot be set because it is read-only
Set parameter qos_overrides./parameter_events.publisher.reliability failed: parameter 'qos_overrides./parameter_events.publisher.reliability' cannot be set because it is read-only
Set parameter start_type_description_service failed: parameter 'start_type_description_service' cannot be set because it is read-only
Set parameter use_sim_time successful
可以看到,所有的参数都被尝试设置了,仅 use_sim_time 这个非 read-only 的参数覆写成功了。只读参数只能在启动时修改,而不能在启动后修改,这就是为什么 “qos_overrides” 参数会出现一些警告。
2.6 node 启动时加载参数
ros2 run demo_nodes_cpp talker --ros-args --params-file talker.yaml
命令行不会有额外打印信息,但是 read-only 的参数此时会生效。
3. 理解 action
动作(Actions)是 ROS 2 中的通信类型之一,用于长时间运行的任务。它们由三个部分组成:目标(goal)、反馈(feedback)和结果(result)。
action 基于主题和 services 构建。它们的功能类似于 services,但 action 可以被取消。它们还提供稳定的反馈,这与返回单个响应的 services 不同。

如图所示,action 使用 client-server 模型,与 pub sub 模型类似。action client node 将信息发送到 action server node,然后 server node 处理并返回结果。
仔细看图,client 先发一个 goal request 到 server,得到 server 的 response 后,client 发送 result request 到 server,此时 server 通过 feedback topic 与 client 保持连接,同步状态等,直到处理完成后,通过 result response 返回处理后的信息给 client。这个架构比仅用 topic 或者 services 都要复杂,但是强大、更加现代化,对复杂系统兼容性强,易于管理。
3.1 使用 action
打开两个终端,分别运行:
ros2 run turtlesim turtlesim_node
ros2 run turtlesim turtle_teleop_key
启动控制 node 后,看到提示信息:Use g|b|v|c|d|e|r|t keys to rotate to absolute orientations. 'f' to cancel a rotation.
其中 g|b|v|c|d|e|r|t 围绕键盘的 f 按键形成一个圆圈,按下对应方向的按键即命令乌龟转向对应的方向,比如按 t,是让乌龟朝向右上方。
按下 t 后,node 窗口会打印:
[INFO] [1762503823.706663289] [turtlesim]: Rotation goal completed successfully
如果在转向的过程中按下另一个方向,会打印:
[WARN] [1762503902.170788364] [turtlesim]: Rotation goal received before a previous goal finished. Aborting previous goal.
该 action 服务器选择中止第一个目标,因为它有了一个新目标。它可以选择其他目标,例如拒绝新目标或在第一个目标完成后执行第二个目标。
通过 ros2 node info /turtlesim 可以发现返回值中存在:
Service Clients:
Action Servers:
/turtle1/rotate_absolute: turtlesim/action/RotateAbsolute
Action Clients:
可以得知这是基于 action 实现的复杂功能,而不是每个使用了 action 的 node 就天然具备的功能。
3.2 查看 ROS 2 action 列表
ros2 action list
返回:
/turtle1/rotate_absolute
和其他的 list 命令一样,可以通过 -t 来查看 action 的类型:
ros2 action list -t
返回:
/turtle1/rotate_absolute [turtlesim/action/RotateAbsolute]
3.3 查看 ROS 2 action 类型
ros2 action type <action>
例如:
ros2 action type /turtle1/rotate_absolute
返回:
turtlesim/action/RotateAbsolute
3.4 查看 ROS 2 action 信息
ros2 action info <action>
例如:
ros2 action info /turtle1/rotate_absolute
返回:
Action: /turtle1/rotate_absolute
Action clients: 1
/teleop_turtle
Action servers: 1
/turtlesim
可以看到 action clients 和 servers 都直接打印出来了。
3.5 查看 ROS 2 action 的接口
ros2 interface show <action_type>
例如:
ros2 interface show turtlesim/action/RotateAbsolute
返回:
# The desired heading in radians
float32 theta
---
# The angular displacement in radians to the starting position
float32 delta
---
# The remaining rotation in radians
float32 remaining
第一部分(第一个 --- 上方)是 goal 的结构,第二部分(第一个 --- 和第二个 --- 之间)是 result 的结构,最后一部分(第二个 --- 下方)是 feedback 的结构,如上图所示。
3.6 ROS 2 action 发送 goal
ros2 action send_goal <action_name> <action_type> <values>
<values> 需要是 YAML 格式。在终端输入:
ros2 action send_goal /turtle1/rotate_absolute turtlesim/action/RotateAbsolute "{theta: -1.57}" --feedback
可以看到海龟开始旋转。返回:
Waiting for an action server to become available...
Sending goal:
theta: -1.57
Goal accepted with ID: e6092c831f994afda92f0086f220da27
Feedback:
remaining: -3.1268222332000732
Feedback:
remaining: -3.1108222007751465
...
Result:
delta: 3.1200008392333984
Goal finished with status: SUCCEEDED
Feedback 展示的是剩余的弧度,直到完成。action client 通过 send goal 到 action server 来实现对海龟的旋转。
4. 总结
本文介绍了 ROS 2 中三种重要的通信和配置机制:
服务(Services):基于请求/响应模型的通信方式,适用于需要即时响应的操作。服务允许客户端向服务器发送请求并接收响应,与主题的单向通信不同,服务提供了双向通信能力。
参数(Parameters):节点的配置值,用于定义节点的默认行为。参数可以在运行时查询和修改(非只读参数),也可以保存到文件中以便在将来的会话中重新加载。只读参数只能在节点启动时设置。
动作(Actions):用于长时间运行任务的通信机制,由目标、反馈和结果三部分组成。动作基于主题和服务构建,提供了可取消的任务执行和定期反馈功能,非常适合需要长时间运行且需要进度更新的任务,如机器人导航。
机器人系统可能会使用 action 进行导航。action 目标可以告诉机器人前往某个位置。当机器人导航到该位置时,它可以沿途发送更新(即反馈),然后在到达目的地后发送最终结果消息。
通过理解这三种机制,可以更好地设计和实现 ROS 2 机器人系统,选择合适的通信方式来处理不同的任务需求。