rosbag info可快速检查bag文件结构,输出topics、message类型、时间范围及记录条数,重点核对type字段是否与代码订阅类型一致,避免c++解析时因schema不匹配崩溃。

用 rosbag 命令行工具快速检查 bag 文件结构
ROS 的 .bag 文件本质是序列化数据容器,不直接可读;想确认它是否能被解析、含哪些 topic 和 message 类型,最省事的是先用官方命令行工具探查。这步能避免后续 C++ 解析时因 schema 不匹配而崩溃。
-
rosbag info <filename.bag></filename.bag>:输出 topics、message 类型、时间范围、记录条数,重点看Type字段是否和你代码中订阅的类型一致(比如sensor_msgs/Image而不是std_msgs/String) -
rosbag show <filename.bag></filename.bag>(ROS 1)或ros2 bag info <filename.bag></filename.bag>(ROS 2):验证 ROS 版本兼容性——ROS 1 的 bag 不能直接用 ROS 2 的rosbag2_cpp打开 - 如果报错
Unsupported bag version或Failed to open bag,基本说明版本/格式不匹配,别急着写 C++ 代码
ROS 1:用 rosbag::Bag 读取并反序列化 message
ROS 1 的 C++ API 直接暴露底层读取逻辑,但要求运行环境已 source 对应的 ROS setup.bash,且编译时链接 rosbag 和对应 message 的库(如 sensor_msgs)。
- 头文件必须包含
#include <rosbag></rosbag>和具体 message 头,例如#include <sensor_msgs></sensor_msgs> - 打开 bag 后,用
bag.readMessages()遍历,对每个rosbag::MessageInstance调用instantiate<t>()</t>反序列化,T必须和 bag 中实际 type 完全一致(大小写、命名空间都不能错) - 常见错误:
Segmentation fault多因instantiate<wrongtype>()</wrongtype>导致,或未在 CMakeLists.txt 中用find_package(sensor_msgs REQUIRED)并链接${sensor_msgs_LIBRARIES} - 示例关键片段:
rosbag::Bag bag;
bag.open("test.bag", rosbag::bagmode::Read);
for (rosbag::MessageInstance const m : rosbag::View(bag)) {
if (m.getTopic() == "/camera/image_raw") {
sensor_msgs::Image::ConstPtr img = m.instantiate<:image>();
if (img) { /* 处理图像数据 */ }
}
}
bag.close();
</:image>
ROS 2:用 rosbag2_cpp::Reader 读取,注意 serialization format
ROS 2 的 bag 使用 SQLite 或自定义序列化后端(如 sqlite3 或 zstd),rosbag2_cpp::Reader 默认只支持与当前 ROS 2 版本配套的 storage 插件,不自动降级兼容旧 bag。
- 初始化前必须调用
reader.open({.uri = "path/to/bag"}),URI 是目录路径(ROS 2 bag 是文件夹),不是单个 .db3 文件 - 读取前需确保已安装对应 storage 插件:比如 bag 是用
sqlite3格式录制的,就得apt install ros-<distro>-rosbag2-storage-default-plugins</distro> - 反序列化靠
converter.deserialize_ros_message(),传入serialized_message.serialized_data和目标 message 类型字符串(如"sensor_msgs/msg/Image"),注意 ROS 2 类型名带/msg/,和 ROS 1 不同 - 若出现
No converter found for serialization format 'cdr',说明 bag 用了 Fast CDR 序列化但没启用对应插件,需安装ros-<distro>-rosbag2-transport</distro>并确认RMW_IMPLEMENTATION匹配
跨版本或无 ROS 环境下解析 bag 的现实限制
纯 C++(不依赖 ROS 运行时)解析 bag 几乎不可行:ROS 1 的 bag 依赖 boost::serialization 和 ROS 自定义 typekit;ROS 2 的 bag 依赖 rcpputils、rosbag2_storage 和 RMW 层的序列化逻辑。强行剥离会导致大量 symbol 缺失或 ABI 不兼容。
- 真正轻量级需求(如只提取 header 时间戳或 topic 名),可用 Python +
rosbag/rosbag2_py提前转换为 CSV 或 JSON,再由 C++ 读文本 - 若必须 C++ 原生处理,唯一可行路径是把 ROS 1/2 的 bag 读取逻辑作为子模块集成进项目,并接受其构建依赖(CMake + pkg-config + ROS install space)
- 最容易被忽略的一点:bag 文件里的 message definition(.msg)必须和解析时链接的 message 库版本严格一致,哪怕字段顺序差一个,
instantiate就会返回空指针,且无明确错误提示
C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!











