录制与回放数据教程
目标: 录制发布在话题、服务和动作上的数据,以便随时回放和检查。
教程级别: 初学者
时间: 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
---
刚刚监控的是 /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。
还有一个你可以添加到命令中的选项 -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.mcap、subset_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/pose 的 Count 值超过 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_vel 和 subset_pose 录制,播放同步以复制原始消息顺序。如果使用,可选参数 --message-order {received,sent} 决定消息是根据接收还是发布的时间排序(默认为接收)。这也适用于播放单个包。
管理服务数据
1. 设置
你将录制 introspection_client 和 introspection_service 之间的服务数据,然后稍后显示和回放相同的数据。为了在服务客户端和服务之间录制服务数据,必须在节点上启用 Service Introspection。
让我们启动 introspection_client 和 introspection_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_client 和 fibonacci_action_server 之间的动作数据,然后稍后显示和回放相同的数据。为了在动作客户端和服务器之间录制动作数据,必须在节点上启用 Action Introspection。
让我们启动 fibonacci_action_client 和 fibonacci_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