ros2 bag 详解

一.命令行详解

ros2 bag 是一个命令行工具,用于记录系统中发布的主题数据。它积累传递给任意数量主题的数据,并将其保存在数据库中。然后可以重放数据以再现测试和实验的结果。记录主题也是分享你的工作并让别人重新创造它的好方法。

1.ros2 bag record

ros2 bag record 

在对选定的主题运行此命令之前,打开一个新的终端并移动到前面创建的 bag_files 目录中,因为 rosbag 文件将保存在运行它的目录中。

ros2 bag record /turtle1/cmd_vel

您将在终端中看到以下消息(日期和时间将会不同):

[INFO] [rosbag2_storage]: Opened database 'rosbag2_2019_10_11-05_18_45'.
[INFO] [rosbag2_transport]: Listening for topics...
[INFO] [rosbag2_transport]: Subscribed to topic '/turtle1/cmd_vel'
[INFO] [rosbag2_transport]: All requested topics are subscribed. Stopping discovery...

记录多个主题

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

-o 选项允许您为您的包文件选择一个唯一的名称。下面的字符串(在本例中是 subset)是文件名。

要一次记录多个主题,只需用空格分开列出每个主题。

您将看到以下消息,确认正在记录这两个主题。

[INFO] [rosbag2_storage]: Opened database 'subset'.
[INFO] [rosbag2_transport]: Listening for topics...
[INFO] [rosbag2_transport]: Subscribed to topic '/turtle1/cmd_vel'
[INFO] [rosbag2_transport]: Subscribed to topic '/turtle1/pose'
[INFO] [rosbag2_transport]: All requested topics are subscribed. Stopping discovery...

您可以向命令添加另一个选项 -a,它记录系统上的所有主题。

ros2 bag info

ros2 bag info subset

Files:             subset.db3
Bag size:          228.5 KiB
Storage id:        sqlite3
Duration:          48.47s
Start:             Oct 11 2019 06:09:09.12 (1570799349.12)
End                Oct 11 2019 06:09:57.60 (1570799397.60)
Messages:          3013
Topic information: Topic: /turtle1/cmd_vel | Type: geometry_msgs/msg/Twist | Count: 9 | Serialization Format: cdr
                 Topic: /turtle1/pose | Type: turtlesim/msg/Pose | Count: 3004 | Serialization Format: cdr

2. ros2 bag play

ros2 bag play subset

终端将返回消息:

[INFO] [rosbag2_storage]: Opened database 'subset'.

 播放选项

1 倍速播放 -r

-r选项可以修改播放速率,比如 -r 值,比如 -r 10,就是10倍速,十倍速播放话题

ros2 bag play rosbag2_2021_10_03-15_31_41_0.db3 -r 10

2 -l 循环播放

单曲循环就是它了

3 播放单个话题

ros2 bag play rosbag2_2021_10_03-15_31_41_0.db3 --topics /sexy_girl

二.源码分析

rosbag2_transport

recorder.cpp

Recorder::Recorder()

Recorder::record()

Writer::open()

get_requested_or_available_topics()

subscribe_topics()

create_topic()

create_subscription() -->创建订阅者订阅消息

  1. 创建订阅者:auto subscription = this->create_generic_subscription(topic_name, topic_type, qos, [capture list](callback function)) 这一行代码通过调用Recorder对象的create_generic_subscription方法创建了一个订阅者实例。这个方法需要传递话题名称、类型、QoS策略以及一个回调函数。

  2. 回调函数:当话题有新消息到达时,这个匿名lambda表达式就会被调用。在这个函数体内,首先创建了一个rosbag2_storage::SerializedBagMessage类型的共享指针bag_message,用于存储即将被写入到rosbag文件中的数据。

  3. 消息处理:接下来,代码将接收到的消息(message)转换成rosbag2_storage::SerializedBagMessage格式,并设置了消息的时间戳和主题名。这里需要注意的是,*bag_message->serialized_data = message->release_rcl_serialized_message();这行代码实际上把message的所有权转移到了bag_message中,并且使用自定义的删除器来确保资源被正确释放。

  4. 写入rosbag:如果bag_message->time_stamp大于0(通常表示消息具有有效的时间戳),那么它会被写入到由writer_成员变量指定的rosbag文件中。

起两个异步线程:

Recorder::topics_discovery() 不断服务发现然后去订阅topic

Recorder::write_metadata() 这个函数会在rosbag记录开始之前或结束之后被调用,以确保元数据准确地反映了rosbag文件的状态。这个函数可能涉及到创建一个包含上述信息的结构体或字典,并将其序列化后写入rosbag文件的一个特定部分。这样做使得rosbag文件不仅包含了实际的消息数据,还有足够的上下文信息供其他工具或程序理解和使用这些数据。

古月居 - ROS机器人知识分享社区

序列化和反序列化是编程领域中常见的概念,它们主要用于处理数据的存储和传输。下面是对这两个概念的基本解释及其主要区别的概述。

**序列化**(Serialization)是指将数据结构或对象状态转换为可以存储或传输的一系列字节流的过程。序列化的主要用途有:
- 存储对象的状态,以便以后恢复。
- 通过网络传输对象,实现远程过程调用(RPC)。
- 将对象的状态保存到数据库中。

**反序列化**(Deserialization)则是序列化的逆过程,即将序列化后的字节流还原成原来的数据结构或对象状态。反序列化通常用于:
- 从磁盘读取序列化的对象状态,并恢复为内存中的对象。
- 接收通过网络传来的序列化对象,并将其转换回对象形式。
- 从数据库读取序列化的对象状态,并重建对象。

两者之间的主要区别在于操作的方向性和目的:
- 序列化是从复杂的数据结构转换为简单的字节流。
- 反序列化是从简单的字节流恢复为复杂的数据结构。

在实际应用中,序列化和反序列化经常一起使用,以确保数据能够在不同的系统之间正确地传递并且能够准确地恢复其原始状态。不同的编程语言和框架提供了多种序列化协议,例如JSON、XML、Protocol Buffers等,每种协议都有其特点和适用场景。

player.cpp

初始化play node

在循环中读取每条消息并反序列化

void Player::play_messages_from_queue()

{

playing_messages_from_queue_ = true;

// Note: We need to use message_queue_.peek() instead of message_queue_.try_dequeue(message)

// to support play_next() API logic.

rosbag2_storage::SerializedBagMessageSharedPtr * message_ptr = peek_next_message_from_queue();

while (message_ptr != nullptr && rclcpp::ok()) {

{

rosbag2_storage::SerializedBagMessageSharedPtr message = *message_ptr;

你可能感兴趣的:(c++)