一、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 三层架构
-
存储API层(rosbag2_storage)
- 完全ROS 2无关,仅处理二进制数据和通用元信息
- 定义了
BaseReaderInterface和BaseWriterInterface两个核心接口 - 所有存储格式都通过实现这两个接口以插件形式提供
- 支持动态加载不同的存储插件
-
核心API层(rosbag2_cpp、rosbag2_py)
- 负责ROS 2消息的序列化和反序列化
- 提供
Reader、Writer、Info等核心类 - 实现了消息缓存、时间管理、事件回调等高级功能
- 提供C++和Python两种语言的API
-
传输层(rosbag2_transport)
- 负责与ROS 2中间件交互
- 提供
Player和Recorder类,实现话题的订阅和发布 - 处理QoS策略匹配和覆盖
- 支持可组合节点和进程内通信
-
命令行接口层(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存储插件提供了多个预设配置文件,针对不同使用场景优化:
-
fastwrite :最高写入吞吐量,适用于资源受限的机器人
noChunking: true noSummaryCRC: true noMessageIndex: true
noChunking = 不分块传输,指一整个消息作为单个数据包发送,不切割成多个小分片
"不拆包,整包发",小消息用noChunking 更快,大消息用它必丢包
-
zstd_fast:平衡写入速度和压缩比
compression: "Zstd" compressionLevel: "Fastest" noChunkCRC: true -
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包提供了更高级的Player和Recorder类,直接支持话题的订阅和发布:
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的Player和Recorder可以作为可组合节点使用,从而利用进程内通信提高性能:
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的Recorder和Player节点提供了丰富的服务接口,支持远程控制:
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的Reader和Writer支持事件回调机制,可以在特定事件发生时执行自定义代码:
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 = MEMORY和synchronous = OFF提高写入速度 - MCAP :根据场景选择合适的预设(
fastwrite、zstd_fast、zstd_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可以满足从简单调试到大规模数据采集的各种需求。
在实际应用中,建议:
- 优先使用MCAP格式,它在性能、可靠性和可移植性方面都优于SQLite3
- 根据场景选择合适的存储预设和压缩策略
- 使用可组合节点和进程内通信提高性能
- 定期备份重要数据,并掌握数据恢复方法
- 利用第三方工具进行数据可视化和分析