ROS2---rosbag2记录和回放话题、服务和动作数据

一、rosbag2概述

1.1 设计目标

rosbag2是ROS 1中rosbag工具的完全重写版本,于ROS 2 Crystal版本首次发布。其设计目标是解决rosbag1在大规模数据处理、多语言支持、可扩展性和可靠性方面的局限性:

  • 模块化与插件化:将存储、序列化、压缩等功能解耦为独立插件
  • 序列化无关性:支持多种序列化格式(CDR、Protobuf、JSON等)
  • 高性能:针对高带宽传感器数据(如激光雷达、相机)优化
  • 可靠性:提供数据完整性保证和损坏恢复机制
  • 跨平台与多语言:支持C++、Python、Rust、Go等多种语言
  • 向后兼容:支持读取ROS 1的.bag文件

1.2 rosbag2与rosbag1的核心区别

特性 rosbag1 rosbag2
架构 单体设计 三层模块化插件架构
存储格式 自定义二进制流(.bag) 插件化存储(SQLite3、MCAP等)
序列化 仅支持ROS 1消息格式 序列化无关,支持多种格式
压缩 仅支持BZ2 支持ZSTD、LZ4等多种压缩算法
随机访问 差(需从头扫描) 优秀(数据库索引或MCAP索引)
数据完整性 无内置校验 支持CRC校验和事务机制
多语言支持 C++、Python C++、Python、Rust、Go、TypeScript等
服务/动作录制 不支持 支持服务和动作的录制与回放

二、rosbag2架构

rosbag2采用三层模块化架构设计,从下到上依次为:存储API层、核心API层和命令行接口层。

2.1 三层架构

  1. 存储API层(rosbag2_storage)

    • 完全ROS 2无关,仅处理二进制数据和通用元信息
    • 定义了BaseReaderInterfaceBaseWriterInterface两个核心接口
    • 所有存储格式都通过实现这两个接口以插件形式提供
    • 支持动态加载不同的存储插件
  2. 核心API层(rosbag2_cpp、rosbag2_py)

    • 负责ROS 2消息的序列化和反序列化
    • 提供ReaderWriterInfo等核心类
    • 实现了消息缓存、时间管理、事件回调等高级功能
    • 提供C++和Python两种语言的API
  3. 传输层(rosbag2_transport)

    • 负责与ROS 2中间件交互
    • 提供PlayerRecorder类,实现话题的订阅和发布
    • 处理QoS策略匹配和覆盖
    • 支持可组合节点和进程内通信
  4. 命令行接口层(ros2bag)

    • 提供用户友好的命令行工具ros2 bag
    • 实现了record、play、info、convert等常用命令
    • 基于Python的VerbExtension机制扩展新命令

2.2 主要包结构

rosbag2项目由多个功能独立的包组成:

  • rosbag2:元包,依赖所有核心包
  • rosbag2_storage:存储插件接口定义
  • rosbag2_storage_default_plugins:默认存储插件(SQLite3)
  • rosbag2_storage_mcap:MCAP存储插件
  • rosbag2_cpp:C++核心API
  • rosbag2_py:Python核心API
  • rosbag2_transport:ROS 2传输层实现
  • rosbag2_compression:压缩插件接口
  • rosbag2_compression_zstd:ZSTD压缩插件
  • rosbag2_interfaces:服务和消息定义
  • rosbag2_performance_benchmarking:性能基准测试工具

三、rosbag2存储格式

rosbag2采用插件化存储架构,支持多种存储格式。不同格式在性能、可靠性、可移植性和工具支持方面各有优劣。

3.1 SQLite3格式(.db3)

SQLite3是ROS 2 Humble及之前版本的默认存储格式,采用.db3+.yaml的组合形式。

数据库结构

SQLite3存储格式使用三个主要表:

表名 字段 作用
messages id INTEGER, topic_id INTEGER, timestamp INTEGER, data BLOB 存储所有消息的时间戳和序列化数据
topics id INTEGER, name TEXT, type TEXT, serialization_format TEXT 记录话题的元数据(名称、类型、序列化格式)
schema schema TEXT 存储数据库版本信息

配套的YAML文件保存了ROS环境参数,包括ROS版本、消息定义哈希值等。

优缺点分析

优点

  • 成熟稳定,SQLite数据库本身经过广泛测试
  • 优秀的随机访问性能,支持SQL查询
  • 内置事务机制,提高数据完整性
  • 工具支持广泛,可使用任何SQLite客户端查看数据

缺点

  • 写入性能相对较低,因为每次插入都需要更新索引
  • 不是纯追加写入,系统崩溃时可能损坏数据库
  • 不支持自包含的消息定义,需要ROS环境才能解析
  • 压缩效率不高

自包含:纯基础类型、不引用任何外部消息的 .msg,在哪都能解析

性能调优

SQLite3存储插件支持通过--storage-config-file选项进行深度调优:

yaml 复制代码
write:
  pragmas:
    - "journal_mode = MEMORY"
    - "synchronous = OFF"
    - "schema.cache_size = 1000"
    - "schema.page_size = 4096"
  • journal_mode = MEMORY:将日志保存在内存中,大幅提高写入速度,但崩溃时可能丢失数据
  • synchronous = OFF:关闭同步写入,提高性能但降低可靠性
  • cache_size:设置数据库缓存大小,单位为页
  • page_size:设置数据库页大小,通常与磁盘块大小匹配

3.2 MCAP格式(.mcap)

MCAP(Modular Container for Asynchronous Pub/Sub messages)是由Foxglove公司开发的新一代机器人数据容器格式,从ROS 2 Iron版本开始成为默认存储格式。

核心特性
  • 纯追加写入:所有数据按顺序追加到文件末尾,系统崩溃时最多丢失最后一条消息
  • 自包含:文件中包含所有消息的schema定义,无需ROS环境即可解析
  • 分块存储:将消息分块存储,支持高效的随机访问和增量读取
  • 内置压缩:支持LZ4和ZSTD两种压缩算法,可在块级别进行压缩
  • 多语言支持:提供C++、Python、Rust、Go、TypeScript等多种语言的库
  • 索引优化:包含消息索引、块索引和元数据索引,支持快速跳转和过滤
预设配置文件

MCAP存储插件提供了多个预设配置文件,针对不同使用场景优化:

  1. fastwrite :最高写入吞吐量,适用于资源受限的机器人

    复制代码
    noChunking: true
    noSummaryCRC: true
    noMessageIndex: true

noChunking = 不分块传输,指一整个消息作为单个数据包发送,不切割成多个小分片

"不拆包,整包发",小消息用noChunking 更快,大消息用它必丢包

  1. zstd_fast:平衡写入速度和压缩比

    复制代码
    compression: "Zstd"
    compressionLevel: "Fastest"
    noChunkCRC: true
  2. zstd_small:最高压缩比,适用于长期存储

    复制代码
    compression: "Zstd"
    compressionLevel: "Slowest"
与SQLite3的性能对比

根据官方基准测试,MCAP在大多数场景下都优于SQLite3:

  • 写入吞吐量提高20-50%
  • 读取速度提高30-100%
  • 压缩后的文件大小减少15-30%
  • 系统崩溃时的数据丢失风险显著降低

3.3 其他存储格式

  • rosbag1 :通过rosbag2_storage_rosbag1插件支持读取ROS 1的.bag文件
  • CSV:用于简单数据导出和分析
  • JSON:用于与Web应用集成

四、rosbag2命令行工具

rosbag2提供了功能丰富的命令行工具ros2 bag,是日常开发中最常用的接口。

4.1 基本命令

1. 录制数据(record)
bash 复制代码
# 录制所有话题
ros2 bag record -a

# 录制指定话题
ros2 bag record /chatter /turtle1/cmd_vel

# 录制所有话题并排除指定话题
ros2 bag record -a -e /camera/* /lidar/*

# 使用正则表达式匹配话题
ros2 bag record -e "/sensor/(.*)"

# 指定输出目录和存储格式
ros2 bag record -o my_bag -s mcap /chatter
2. 回放数据(play)
bash 复制代码
# 回放指定bag
ros2 bag play my_bag/

# 以2倍速回放
ros2 bag play -r 2 my_bag/

# 从指定时间开始回放(秒)
ros2 bag play --start 10 my_bag/

# 回放指定时长(秒)
ros2 bag play --duration 30 my_bag/

# 循环回放
ros2 bag play -l my_bag/

# 暂停开始,按空格键继续
ros2 bag play --pause my_bag/
3. 查看bag信息(info)
bash 复制代码
# 查看基本信息
ros2 bag info my_bag/

# 查看详细信息,包括消息统计
ros2 bag info -v my_bag/
4. 转换格式(convert)
bash 复制代码
# 将SQLite3格式转换为MCAP格式
ros2 bag convert -i my_bag.db3 -o output_bag -s mcap

# 使用配置文件进行转换
ros2 bag convert -i input_bag -o convert.yaml

转换配置文件示例:

yaml 复制代码
output_bags:
  - uri: compressed_bag
    storage_id: mcap
    storage_preset_profile: zstd_small
    topics: [/chatter, /turtle1/cmd_vel]
5. 重建索引(reindex)

当bag文件损坏或索引丢失时,可以使用reindex命令重建索引:

bash 复制代码
ros2 bag reindex my_bag/

4.2 高级选项

1. 分片录制

当录制大量数据时,可以将bag文件分片存储:

bash 复制代码
# 按大小分片(单位:字节)
ros2 bag record -a -b 104857600  # 每100MB分片

# 按时间分片(单位:秒)
ros2 bag record -a -d 3600  # 每小时分片

# 同时按大小和时间分片,先到先触发
ros2 bag record -a -b 104857600 -d 3600
2. 压缩录制

rosbag2支持两种压缩模式:文件级压缩和消息级压缩:

bash 复制代码
# 文件级压缩(整个文件压缩)
ros2 bag record -a --compression-mode file --compression-format zstd

# 消息级压缩(每条消息单独压缩)
ros2 bag record -a --compression-mode message --compression-format zstd

注意:文件级压缩的压缩比更高,但读取时需要解压整个文件;消息级压缩的随机访问性能更好,但压缩比略低。

3. QoS策略覆盖

由于ROS 2引入了QoS策略,rosbag2在录制和回放时需要考虑QoS兼容性。可以通过YAML文件覆盖默认的QoS策略:

yaml 复制代码
# qos_overrides.yaml
/chatter:
  reliability: reliable
  durability: transient_local
  history: keep_last
  depth: 10

/turtle1/cmd_vel:
  reliability: best_effort
  durability: volatile

使用方法:

bash 复制代码
ros2 bag record --qos-profile-overrides-path qos_overrides.yaml /chatter /turtle1/cmd_vel
4. 键盘控制

在回放过程中,可以使用以下键盘快捷键控制播放:

  • 空格键:暂停/继续
  • 右箭头:快进1秒
  • 左箭头:快退1秒
  • 上箭头:增加播放速度
  • 下箭头:降低播放速度
  • s:单步播放(播放下一条消息)
  • q:退出

4.3 服务与动作录制

从ROS 2 Humble版本开始,rosbag2支持录制和回放服务和动作:

bash 复制代码
# 录制所有服务和动作
ros2 bag record --all-topics --all-services --all-actions

# 录制指定服务
ros2 bag record --services /add_two_ints

# 录制指定动作
ros2 bag record --actions /fibonacci

五、rosbag2编程接口

rosbag2提供了C++和Python两种语言的API,允许开发者在自己的节点中集成录制和回放功能。

5.1 C++ API

1. 基本写入示例
cpp 复制代码
#include <rclcpp/rclcpp.hpp>
#include <rosbag2_cpp/writer.hpp>
#include <std_msgs/msg/string.hpp>

class SimpleBagRecorder : public rclcpp::Node
{
public:
  SimpleBagRecorder() : Node("simple_bag_recorder")
  {
    // 创建writer对象
    writer_ = std::make_unique<rosbag2_cpp::Writer>();
    
    // 打开bag文件
    writer_->open("my_bag");
    
    // 创建话题
    writer_->create_topic(
      {"/chatter", "std_msgs/msg/String", "cdr", ""});
    
    // 创建订阅者
    subscription_ = this->create_subscription<std_msgs::msg::String>(
      "/chatter", 10,
      [this](std_msgs::msg::String::UniquePtr msg) {
        // 写入消息
        writer_->write(*msg, "/chatter", this->now());
      });
  }

private:
  std::unique_ptr<rosbag2_cpp::Writer> writer_;
  rclcpp::Subscription<std_msgs::msg::String>::SharedPtr subscription_;
};

int main(int argc, char * argv[])
{
  rclcpp::init(argc, argv);
  rclcpp::spin(std::make_shared<SimpleBagRecorder>());
  rclcpp::shutdown();
  return 0;
}
2. 基本读取示例
cpp 复制代码
#include <rclcpp/rclcpp.hpp>
#include <rosbag2_cpp/reader.hpp>
#include <std_msgs/msg/string.hpp>

class SimpleBagReader : public rclcpp::Node
{
public:
  SimpleBagReader() : Node("simple_bag_reader")
  {
    // 创建reader对象
    reader_ = std::make_unique<rosbag2_cpp::Reader>();
    
    // 打开bag文件
    reader_->open("my_bag");
    
    // 创建发布者
    publisher_ = this->create_publisher<std_msgs::msg::String>("/chatter", 10);
    
    // 创建定时器,每秒读取一条消息
    timer_ = this->create_wall_timer(
      std::chrono::seconds(1),
      [this]() {
        if (reader_->has_next()) {
          auto msg = reader_->read_next();
          if (msg->topic_name == "/chatter") {
            // 反序列化消息
            auto string_msg = std::make_shared<std_msgs::msg::String>();
            rclcpp::SerializedMessage serialized_msg(*msg->serialized_data);
            rclcpp::Serialization<std_msgs::msg::String> serializer;
            serializer.deserialize_message(&serialized_msg, string_msg.get());
            
            // 发布消息
            publisher_->publish(*string_msg);
          }
        } else {
          RCLCPP_INFO(this->get_logger(), "No more messages");
          timer_->cancel();
        }
      });
  }

private:
  std::unique_ptr<rosbag2_cpp::Reader> reader_;
  rclcpp::Publisher<std_msgs::msg::String>::SharedPtr publisher_;
  rclcpp::TimerBase::SharedPtr timer_;
};

int main(int argc, char * argv[])
{
  rclcpp::init(argc, argv);
  rclcpp::spin(std::make_shared<SimpleBagReader>());
  rclcpp::shutdown();
  return 0;
}
3. 使用Player和Recorder类

rosbag2_transport包提供了更高级的PlayerRecorder类,直接支持话题的订阅和发布:

cpp 复制代码
#include <rclcpp/rclcpp.hpp>
#include <rosbag2_transport/recorder.hpp>
#include <rosbag2_transport/player.hpp>

int main(int argc, char * argv[])
{
  rclcpp::init(argc, argv);
  
  // 创建Recorder节点
  auto recorder_node = std::make_shared<rclcpp::Node>("recorder_node");
  rosbag2_transport::Recorder recorder(recorder_node);
  
  // 配置录制选项
  rosbag2_transport::RecordOptions record_options;
  record_options.topics = {"/chatter", "/turtle1/cmd_vel"};
  
  // 开始录制
  recorder.record("my_bag", record_options);
  
  // 创建Player节点
  auto player_node = std::make_shared<rclcpp::Node>("player_node");
  rosbag2_transport::Player player(player_node);
  
  // 配置播放选项
  rosbag2_transport::PlayOptions play_options;
  play_options.rate = 2.0;
  
  // 开始播放
  player.play("my_bag", play_options);
  
  rclcpp::shutdown();
  return 0;
}

5.2 Python API

1. 基本写入示例
python 复制代码
import rclpy
from rclpy.node import Node
from rosbag2_py import Writer, StorageOptions, ConverterOptions
from std_msgs.msg import String

class SimpleBagRecorder(Node):
    def __init__(self):
        super().__init__('simple_bag_recorder')
        
        # 创建writer对象
        self.writer = Writer()
        
        # 配置存储选项
        storage_options = StorageOptions(
            uri='my_bag',
            storage_id='sqlite3'
        )
        
        # 配置转换选项
        converter_options = ConverterOptions('', '')
        
        # 打开bag文件
        self.writer.open(storage_options, converter_options)
        
        # 创建话题
        self.writer.create_topic(
            '/chatter',
            'std_msgs/msg/String',
            'cdr',
            ''
        )
        
        # 创建订阅者
        self.subscription = self.create_subscription(
            String,
            '/chatter',
            self.callback,
            10
        )
    
    def callback(self, msg):
        # 写入消息
        self.writer.write(
            '/chatter',
            msg,
            self.get_clock().now().to_msg()
        )

def main(args=None):
    rclpy.init(args=args)
    node = SimpleBagRecorder()
    rclpy.spin(node)
    node.destroy_node()
    rclpy.shutdown()

if __name__ == '__main__':
    main()
2. 基本读取示例
python 复制代码
import rclpy
from rclpy.node import Node
from rosbag2_py import Reader, StorageOptions, ConverterOptions
from std_msgs.msg import String

class SimpleBagReader(Node):
    def __init__(self):
        super().__init__('simple_bag_reader')
        
        # 创建reader对象
        self.reader = Reader()
        
        # 配置存储选项
        storage_options = StorageOptions(
            uri='my_bag',
            storage_id='sqlite3'
        )
        
        # 配置转换选项
        converter_options = ConverterOptions('', '')
        
        # 打开bag文件
        self.reader.open(storage_options, converter_options)
        
        # 创建发布者
        self.publisher = self.create_publisher(String, '/chatter', 10)
        
        # 创建定时器,每秒读取一条消息
        self.timer = self.create_timer(1.0, self.timer_callback)
    
    def timer_callback(self):
        if self.reader.has_next():
            msg = self.reader.read_next()
            if msg.topic_name == '/chatter':
                # 反序列化消息
                string_msg = String()
                string_msg.deserialize(msg.serialized_data)
                
                # 发布消息
                self.publisher.publish(string_msg)
        else:
            self.get_logger().info('No more messages')
            self.timer.cancel()

def main(args=None):
    rclpy.init(args=args)
    node = SimpleBagReader()
    rclpy.spin(node)
    node.destroy_node()
    rclpy.shutdown()

if __name__ == '__main__':
    main()

5.3 可组合节点

rosbag2的PlayerRecorder可以作为可组合节点使用,从而利用进程内通信提高性能:

python 复制代码
from launch import LaunchDescription
from launch_ros.actions import ComposableNodeContainer
from launch_ros.descriptions import ComposableNode

def generate_launch_description():
    return LaunchDescription([
        ComposableNodeContainer(
            name='rosbag2_container',
            namespace='',
            package='rclcpp_components',
            executable='component_container',
            composable_node_descriptions=[
                ComposableNode(
                    package='rosbag2_transport',
                    plugin='rosbag2_transport::Recorder',
                    name='recorder',
                    parameters=[{
                        'uri': 'my_bag',
                        'topics': ['/chatter', '/turtle1/cmd_vel']
                    }]
                )
            ],
            output='screen',
        )
    ])

六、rosbag2高级功能

6.1 远程控制服务

rosbag2的RecorderPlayer节点提供了丰富的服务接口,支持远程控制:

Recorder服务
  • ~/is_paused [rosbag2_interfaces/srv/IsPaused]:查询录制是否暂停
  • ~/pause [rosbag2_interfaces/srv/Pause]:暂停录制
  • ~/resume [rosbag2_interfaces/srv/Resume]:恢复录制
  • ~/split_bagfile [rosbag2_interfaces/srv/SplitBagfile]:手动分片
  • ~/snapshot [rosbag2_interfaces/srv/Snapshot]:拍摄快照
Player服务
  • ~/is_paused [rosbag2_interfaces/srv/IsPaused]:查询播放是否暂停
  • ~/pause [rosbag2_interfaces/srv/Pause]:暂停播放
  • ~/resume [rosbag2_interfaces/srv/Resume]:恢复播放
  • ~/seek [rosbag2_interfaces/srv/Seek]:跳转到指定时间
  • ~/burst [rosbag2_interfaces/srv/Burst]:播放指定数量的消息
  • ~/get_rate [rosbag2_interfaces/srv/GetRate]:获取当前播放速度
  • ~/set_rate [rosbag2_interfaces/srv/SetRate]:设置播放速度

6.2 快照模式

快照模式允许录制最近一段时间的数据,而不是从开始一直录制到结束:

bash 复制代码
ros2 bag record --snapshot-mode --max-cache-size 100000000 /chatter

当需要保存数据时,调用~/snapshot服务:

bash 复制代码
ros2 service call /recorder/snapshot rosbag2_interfaces/srv/Snapshot

快照模式非常适合用于异常检测和故障诊断,只在发生异常时保存数据。

6.3 时间控制

rosbag2的Player支持精确的时间控制,包括:

  • 暂停/继续 :通过~/pause~/resume服务
  • 速度调整 :通过~/set_rate服务,支持0.1倍到10倍速
  • 时间跳转 :通过~/seek服务,可以跳转到任意时间点
  • 单步播放 :通过~/burst服务,播放指定数量的消息

6.4 事件回调

rosbag2的ReaderWriter支持事件回调机制,可以在特定事件发生时执行自定义代码:

cpp 复制代码
#include <rosbag2_cpp/writer.hpp>
#include <rosbag2_cpp/bag_events.hpp>

auto writer = std::make_unique<rosbag2_cpp::Writer>();

// 注册bag分片事件回调
writer->add_event_callback(
  [](const rosbag2_cpp::bag_events::BagSplitInfo & info) {
    RCLCPP_INFO(
      rclcpp::get_logger("bag_events"),
      "Bag split: %s -> %s",
      info.closed_file.c_str(),
      info.opened_file.c_str());
  },
  rosbag2_cpp::bag_events::BagEvent::WRITE_SPLIT);

七、rosbag2性能优化

rosbag2的性能直接影响机器人系统的数据采集能力,特别是在处理高带宽传感器数据时。以下是一些性能优化技巧。

7.1 存储层优化

1. 选择合适的存储格式
  • 对于大多数场景,推荐使用MCAP格式,它在写入速度、读取速度和压缩比方面都优于SQLite3
  • 如果需要使用SQLite客户端查看数据,可以继续使用SQLite3格式
  • 对于资源受限的嵌入式系统,使用MCAP的fastwrite预设
2. 调整存储配置
  • SQLite3 :使用journal_mode = MEMORYsynchronous = OFF提高写入速度
  • MCAP :根据场景选择合适的预设(fastwritezstd_fastzstd_small
  • 禁用不必要的功能,如CRC校验和消息索引(如果不需要随机访问)

7.2 传输层优化

1. 使用可组合节点

将rosbag2节点与其他节点放在同一个进程中,使用进程内通信避免数据拷贝和网络开销。

2. 启用零拷贝传输

如果使用支持零拷贝的RMW实现(如Cyclone DDS),可以启用零拷贝传输:

bash 复制代码
export RMW_IMPLEMENTATION=rmw_cyclonedds_cpp
export ROS_DISABLE_LOANED_MESSAGES=0
3. 优化QoS策略
  • 对于高频率、低优先级的数据,使用BEST_EFFORT可靠性策略
  • 对于大消息(如点云、图像),使用KEEP_LAST历史策略并设置合适的深度

7.3 缓存与队列调优

  • max_cache_size:设置消息缓存大小,建议为物理内存的30%~50%,不低于512MB
  • max_queue_size:控制待写入消息队列长度,防止OOM(内存溢出)
  • num_writer_threads:根据磁盘性能设置写入线程数,NVMe SSD可以设置为2-4
bash 复制代码
ros2 bag record -a --max-cache-size 1073741824 --max-queue-size 1000

7.4 压缩策略

  • 对于点云数据,使用ZSTD压缩,压缩级别3-6,压缩比可达3:1~5:1
  • 对于图像数据,使用PNG或ZSTD-PNG压缩,压缩比可达2:1~4:1
  • 对于IMU和TF数据,使用LZ4压缩,压缩比可达1.5:1~2:1
  • 优先使用MCAP的块级压缩,而不是rosbag2的文件级或消息级压缩

八、rosbag2常见问题

8.1 数据损坏与恢复

1. SQLite3数据库损坏

如果SQLite3数据库损坏,可以尝试以下方法恢复:

bash 复制代码
# 尝试修复数据库
sqlite3 my_bag.db3 ".recover" | sqlite3 recovered_bag.db3

# 重建索引
ros2 bag reindex recovered_bag/
2. MCAP文件损坏

MCAP采用纯追加写入设计,系统崩溃时最多丢失最后一条消息。可以使用MCAP CLI工具检查和修复:

bash 复制代码
# 检查文件完整性
mcap check my_bag.mcap

# 修复损坏的文件
mcap recover my_bag.mcap -o recovered_bag.mcap

8.2 大文件处理

  • 使用分片录制,将大文件分成多个小文件
  • 使用MCAP格式和块级压缩,提高随机访问性能
  • 使用ros2 bag convert命令过滤不需要的话题,减小文件大小
  • 使用第三方工具(如Foxglove)查看和分析大文件

8.3 跨版本兼容性

  • rosbag2文件格式在不同ROS 2版本之间基本兼容
  • 建议使用相同或更高版本的rosbag2读取旧版本录制的文件
  • 对于重要数据,建议同时保存消息定义文件
  • 使用MCAP格式可以获得更好的跨版本兼容性,因为它是自包含的

8.4 数据共享与协作

  • 使用MCAP格式分享数据,因为它是自包含的,不需要接收方有ROS环境
  • 压缩数据以减小传输大小
  • 提供bag信息文件,说明数据内容、录制时间、传感器配置等
  • 使用版本控制工具管理bag文件的元数据

九、rosbag2生态系统

9.1 第三方工具

  • Foxglove Studio:功能强大的机器人数据可视化工具,原生支持MCAP和rosbag2格式
  • PlotJuggler:实时数据可视化工具,支持导入rosbag2文件
  • MCAP CLI:MCAP格式的命令行工具,支持检查、修复、转换和合并
  • rosbags-rs:高性能的Rust库,支持读取和写入rosbag2文件

9.2 其他语言实现

  • Rust:rosbags-rs库,提供零拷贝读取和高性能写入
  • Go:mcap-go库,支持MCAP格式
  • TypeScript:@mcap/core库,支持在浏览器中读取MCAP文件
  • Python:除了官方的rosbag2_py,还有rosbags库,提供更简洁的API

总结

rosbag2是ROS 2生态系统中不可或缺的核心工具,它采用模块化插件架构,支持多种存储格式和序列化方式,提供了丰富的命令行工具和编程接口。通过合理的配置和优化,rosbag2可以满足从简单调试到大规模数据采集的各种需求。

在实际应用中,建议:

  1. 优先使用MCAP格式,它在性能、可靠性和可移植性方面都优于SQLite3
  2. 根据场景选择合适的存储预设和压缩策略
  3. 使用可组合节点和进程内通信提高性能
  4. 定期备份重要数据,并掌握数据恢复方法
  5. 利用第三方工具进行数据可视化和分析
相关推荐
行走的大喇叭7 小时前
计算机系统组成及常见概念
linux·运维·计算机网络
乐观的Terry7 小时前
用 cc-connect 将 Claude Code 接入飞书机器人
机器人·飞书
j_xxx404_7 小时前
Linux线程控制:从用户态控制到内核级克隆全链路解析
linux·运维·服务器·开发语言·c++·ai
z200509307 小时前
【linux学习】进程的概念和在linux系统下的基本实现情况01
linux·网络·学习
xwz小王子7 小时前
Nature 正刊:可穿戴膝关节机器人,重量仅为0.96 kg!让脊髓性肌萎缩症患儿重获站立能力
人工智能·机器人
一条泥憨鱼7 小时前
让AI从“死记硬背”到“开卷考试”:详解RAG技术的奥秘
人工智能·ai·语言模型·机器人·rag
铅笔小新z7 小时前
【Linux】基础IO
linux·服务器
xiaoye-duck7 小时前
【Linux:文件】Linux 动静态库详解::制作、使用、原理与实战
linux
大唐游子7 小时前
wsl安装高版本ubuntu(24.04)
linux·ubuntu