Skip to main content

录制与回放数据教程

目标: 录制发布在话题、服务和动作上的数据,以便随时回放和检查。

教程级别: 初学者

时间: 30 分钟

背景

ros2 bag 是一个命令行工具,用于录制 ROS 2 系统中的话题、服务和动作上发布的数据。它累积任何数量的话题、服务和动作上传递的数据,并将其保存在一个数据库中。之后你可以回放这些数据以重现测试和实验的结果。录制话题、服务和动作也是分享你的工作并允许他人再现的好方法。

准备工作

你应该已经作为常规 ROS 2 设置的一部分安装了 ros2 bag。如果需要安装 ROS 2,请参阅 安装指南

本教程讨论了之前教程中涵盖的概念,如 节点话题服务动作 。我们还使用了 turtlesim 包 (Package) 、服务自省(Service Introspection) 和 动作自省 (Action Introspection)。

一如既往,不要忘记在 每次打开新终端时配置 ROS 2 环境

管理话题数据

1. 设置

你将在turtlesim系统中录制键盘输入,以便稍后保存和回放,所以首先启动 /turtlesim/teleop_turtle 节点。

打开一个新的终端并运行:

ros2 run turtlesim turtlesim_node

再打开另一个终端并运行:

 ros2 run turtlesim turtle_teleop_key

我们也可以创建一个新目录来存储我们的录音,这是一个良好的实践:

mkdir bag_files
cd bag_files

2. 选择一个话题

ros2 bag 可以从发布到话题的消息中记录数据。要查看系统的主题列表,请打开一个新的终端并运行以下命令:

ros2 topic list

你会看到类似下面的输出:

/parameter_events
/rosout
/turtle1/cmd_vel
/turtle1/color_sensor
/turtle1/pose

在话题教程中,我们了解到 /turtle_teleop 节点在 /turtle1/cmd_vel 主题上发布命令,使乌龟在 turtlesim 中移动。

要查看 /turtle1/cmd_vel 发布的数据,运行以下命令:

 ros2 topic echo /turtle1/cmd_vel

开始时不会显示任何内容,因为 teleop 没有发布数据。返回到运行 teleop 的终端并激活它。使用箭头键移动乌龟,你会看到数据在运行 ros2 topic echo 的终端上发布。

linear:
x: 2.0
y: 0.0
z: 0.0
angular:
x: 0.0
y: 0.0
z: 0.0
---
tip

刚刚监控的是 /turtle1/cmd_vel 话题的信息。现在我们再试验一下小乌龟的姿态的话题,即:

/turtle1/pose

3. 录制话题

3.1 录制单个话题

要录制发布到某个话题的数据,使用以下命令语法:

ros2 bag record --topics <topic_name>

在选择的话题上运行此命令之前,打开一个新的终端并进入之前创建的 bag_files 目录,因为 rosbag 文件将保存在运行它的目录中。

运行命令:

ros2 bag record --topics /turtle1/cmd_vel

现在 ros2 bag 正在录制发布在 /turtle1/cmd_vel 话题上的数据。返回到 teleop 终端并再次移动乌龟。移动方式不重要,但尝试制作一个可识别的模式,以便稍后回放数据时可以看到。

Ctrl-C 停止录制。

数据将累积在一个新的包目录中,名称模式为 rosbag2_year_month_day-hour_minute_second。该目录将包含一个 metadata.yaml 文件以及记录格式的包文件。

3.2 录制多个话题

你还可以录制多个话题,并更改 ros2 bag 保存到的包目录名称。

运行以下命令:

ros2 bag record -o subset --topics /turtle1/cmd_vel /turtle1/pose

-o 选项允许你为包目录选择一个独特的名称。在这种情况下,subset 就是包目录的名称。

要一次录制多个话题,只需在 --topics 后列出每个话题,用空格分隔。在这种情况下,上面的命令输出确认两个话题都在被录制。

你可以移动乌龟并在完成后按 Ctrl-C

note

还有一个你可以添加到命令中的选项 -a,它会录制系统上的所有话题。

3.3 将录制分成多个文件

你还可以根据录制持续时间或文件大小将录制分成多个文件:

  • -d <max_bag_duration> 确保每个文件仅持续 <max_bag_duration> 秒,然后开始写入新文件。
  • 或者 -b <max_bag_size> 确保每个文件的文件大小不超过 <max_bag_size> 字节。这可以防止出现过大且笨重的文件大小,并保护在某些时候录制操作变得损坏时不会丢失所有数据。

至少运行以下命令 15 秒钟,允许写入三个 5 秒钟的包文件:

ros2 bag record -o subset_split -d 5 --topics /turtle1/cmd_vel /turtle1/pose

完成后按 :kbd:Ctrl-C。你应该会找到一个 subset_split 目录,里面有这些文件:subset_split_0.mcapsubset_split_1.mcap 等等。

4. 检查话题数据

你可以通过运行以下命令查看有关录制的详细信息:

ros2 bag info <bag_name>

subset 包录制上运行此命令将返回以下信息列表:

Files:             subset_0.mcap
Bag size: 299.1 KiB
Storage id: mcap
ROS Distro: kilted
Duration: 57.649063878s
Start: Mar 24 2026 14:56:15.167369708 (1774335375.167369708)
End: Mar 24 2026 14:57:12.816433586 (1774335432.816433586)
Messages: 4030
Topic information: Topic: /turtle1/cmd_vel | Type: geometry_msgs/msg/Twist | Count: 426 | Serialization Format: cdr
Topic: /turtle1/pose | Type: turtlesim_msgs/msg/Pose | Count: 3604 | Serialization Format: cdr
Services: 0
Service information:
Actions: 0
Action information:

或者,你也可以对单个文件调用 ros2 bag info,例如 subset_split/subset_split_0.mcap,它只会显示该部分录制的信息;在这种情况下,前 5 秒。

5. 回放话题数据

5.1 回放单个包

在回放包之前,在运行 teleop 的终端中输入 :kbd:Ctrl-C。然后确保你的 turtlesim 窗口可见,以便你可以看到包文件的实际效果。

输入命令:

ros2 bag play subset

你的乌龟将遵循你在录制时输入的相同路径(尽管不是 100% 完全相同;turtlesim 对系统计时的小变化很敏感)。

因为 subset 文件记录了 /turtle1/pose 话题,即使你没有移动,ros2 bag play 命令也不会退出,只要你运行了 turtlesim。

这是因为只要 /turtlesim 节点处于活动状态,它就会定期在 /turtle1/pose 话题上发布数据。你可能已经在上面的 ros2 bag info 示例结果中注意到,/turtle1/cmd_vel 话题的 Count 信息只有 426;这是我们录制时按下箭头键的次数。

请注意,/turtle1/poseCount 值超过 3000;在我们录制期间,该话题上发布了 3000 次数据。

要了解位置数据发布的频率,你可以运行以下命令:

ros2 topic hz /turtle1/pose

5.2 回放多个包

有时,将所需的录制话题拆分到多个录制中是有意义的,这是一种分配录制工作负载的方式。例如,我们可以分别将 /turtle1/cmd_vel/turtle1/pose 各自录制到它们自己的包中。

创建两个终端实例。在第一个终端中,运行以下命令:

ros2 bag record -o subset_cmd_vel --topics /turtle1/cmd_vel

在第二个终端中,运行以下命令:

ros2 bag record -o subset_pose --topics /turtle1/pose

像之前一样移动乌龟,然后在完成后按 Ctrl-C 结束两个录制。

要让这两个录制同时播放并保持正确的时机,调用 ros2 bag play 并为每个要包括的包使用 -i <bag_name>。在这种情况下,运行:

ros2 bag play -i subset_cmd_vel -i subset_pose

这将一起播放 subset_cmd_velsubset_pose 录制,播放同步以复制原始消息顺序。如果使用,可选参数 --message-order {received,sent} 决定消息是根据接收还是发布的时间排序(默认为接收)。这也适用于播放单个包。

管理服务数据

1. 设置

你将录制 introspection_clientintrospection_service 之间的服务数据,然后稍后显示和回放相同的数据。为了在服务客户端和服务之间录制服务数据,必须在节点上启用 Service Introspection

让我们启动 introspection_clientintrospection_service 节点并启用 Service Introspection

打开一个新的终端并运行 introspection_service,启用 Service Introspection

ros2 run demo_nodes_cpp introspection_service --ros-args -p service_configure_introspection:=contents

再打开另一个终端并运行 introspection_client,启用 Service Introspection

ros2 run demo_nodes_cpp introspection_client --ros-args -p client_configure_introspection:=contents

2. 检查服务可用性

ros2 bag 只能从可用的服务中录制数据。要查看系统的服务列表,请打开一个新的终端并运行以下命令:

ros2 service list

要检查是否在客户端和服务上启用了 Service Introspection,运行以下命令:

ros2 service echo --flow-style /add_two_ints

你应该能看到服务通信。

3. 录制服务

要录制服务数据,支持以下选项。服务数据可以与话题同时录制。

要录制特定服务:

ros2 bag record --service <service_names>

要录制所有服务:

ros2 bag record --all-services

运行命令:

ros2 bag record --service /add_two_ints

现在 ros2 bag 正在录制发布在 /add_two_ints 服务上的服务数据。要在终端中停止录制,请按 Ctrl-C

数据将累积在一个新的包目录中,名称模式为 rosbag2_year_month_day-hour_minute_second。该目录将包含一个 metadata.yaml 文件以及记录格式的包文件。

4. 检查服务数据

你可以通过运行以下命令查看有关录制的详细信息:

ros2 bag info <bag_file_name>

5. 回放服务数据

在回放包文件之前,在运行 introspection_client 的终端中按 Ctrl-C。当 introspection_client 停止运行时,introspection_service 也会停止打印结果,因为没有传入请求。

从包文件回放服务数据将开始向 introspection_service 发送请求。

输入命令:

ros2 bag play --publish-service-requests <bag_file_name>

你的 introspection_service 终端将再次开始打印以下服务消息:

[INFO] [1713997478.090466075] [introspection_service]: Incoming request
a: 2 b: 3

这是因为 ros2 bag play 将包文件中的服务请求数据发送到 /add_two_ints 服务。

我们还可以在 ros2 bag play 回放时内省服务通信以验证 introspection_service

ros2 bag play 之前运行此命令以查看 introspection_service

ros2 service echo --flow-style /add_two_ints

你可以看到来自包文件的服务请求和来自 introspection_service 的服务响应。

管理动作数据

1. 设置

你将录制 fibonacci_action_clientfibonacci_action_server 之间的动作数据,然后稍后显示和回放相同的数据。为了在动作客户端和服务器之间录制动作数据,必须在节点上启用 Action Introspection

让我们启动 fibonacci_action_clientfibonacci_action_server 节点并启用 Action Introspection

打开一个新的终端并运行 fibonacci_action_server,启用 Action Introspection

ros2 run action_tutorials_py fibonacci_action_server --ros-args -p action_server_configure_introspection:=contents

再打开另一个终端并运行 fibonacci_action_client,启用 Action Introspection

ros2 run action_tutorials_cpp fibonacci_action_client --ros-args -p action_client_configure_introspection:=contents

2. 检查动作可用性

ros2 bag 只能从可用的动作中录制数据。要查看系统的动作列表,请打开一个新的终端并运行以下命令:

ros2 action list

要检查是否在动作上启用了 Action Introspection,运行以下命令:

ros2 action echo --flow-style /fibonacci

3. 录制动作

要录制动作数据,支持以下选项。动作数据可以与话题和服务同时录制。

要录制特定动作:

ros2 bag record --action <action_names>

要录制所有动作:

ros2 bag record --all-actions

运行命令:

ros2 bag record --action /fibonacci

现在 ros2 bag 正在录制 /fibonacci 动作的目标、结果和反馈数据。要在终端中停止录制,请按 Ctrl-C

数据将累积在一个新的包目录中,名称模式为 rosbag2_year_month_day-hour_minute_second。该目录将包含一个 metadata.yaml 文件以及记录格式的包文件。

4. 检查动作数据

你可以通过运行以下命令查看有关录制的详细信息:

ros2 bag info <bag_file_name>

5. 回放动作数据

在回放包文件之前,在运行 fibonacci_action_client 的终端中按 Ctrl-C。当 fibonacci_action_client 停止运行时,fibonacci_action_server 也会停止打印结果,因为没有传入请求。

从包文件回放动作数据将开始向 fibonacci_action_server 发送请求。

输入命令:

ros2 bag play --send-actions-as-client <bag_file_name>

你的 fibonacci_action_server 终端将再次开始打印以下服务消息:

[INFO] [1744953720.815577088] [fibonacci_action_server]: Executing goal...
[INFO] [1744953720.815927050] [fibonacci_action_server]: Feedback: array('i', [0, 1, 1])
...

这是因为 ros2 bag play 将包文件中的动作目标请求数据发送到 /fibonacci 动作。

我们还可以在 ros2 bag play 回放时内省动作通信以验证 fibonacci_action_server

ros2 bag play 之前运行此命令以查看 fibonacci_action_server。你可以看到来自包文件的动作目标请求和来自 fibonacci_action_server 的服务响应。

总结

你可以使用 ros2 bag 命令录制 ROS 2 系统中传递的话题、服务和动作上的数据。无论你是与他人分享你的工作还是内省自己的实验,都是一个很好的工具。

下一步

你已经完成了“初学者:CLI 工具”教程!在下一节,我们将综合运用目前已经学到的所有关于 ROS2 基本 CLI 命令的知识,实现一个局域网聊天工具(广播通信、点对点通信)。

vim:filetype=markdown