3. 数据采集与存储格式:ROS Bag、HDF5、Mcap、自定义二进制格式、数据压缩策略

做多传感器融合,第一步不是算法,不是标定,而是——把数据存下来。

这话听起来简单,但我见过太多团队在数据回放阶段翻车。传感器一开,数据哗哗地来,结果存盘格式没选好,回放时要么卡死,要么丢帧,要么文件大到没法拷贝。嗯,今天我们就来聊聊数据存储这件事。

3.1 ROS Bag:最熟悉的陌生人

ROS Bag 应该是大家最常用的格式了。说白了,它就是 ROS 消息的“录像机”。你发布什么话题,它就录什么话题。

核心特点:

  • 原生支持 ROS 消息类型
  • 时间戳自动记录
  • 支持多话题并行录制
  • 可以用 rosbag play 直接回放

我个人习惯用 rosbag record -a 来录全部话题。但这里有个坑——如果你传感器多,比如 4 个摄像头加 1 个激光雷达,不加压缩的话,一分钟就能吃掉几个 G。

我曾经踩过的坑:

有一次录了半小时的城区道路数据,结果文件 120 多 G。拷贝到工作站花了快两小时。后来我改用 rosbag record --lz4 压缩录制,文件直接缩到 30G,而且解压速度很快。

ROS Bag 的局限也很明显:它不是为大规模数据设计的。如果你要做深度学习训练,每次都要从 bag 里解包,效率很低。

3.2 HDF5:科学计算的利器

HDF5 是我做科研项目时接触的格式。它本质上是一个“文件系统里的文件系统”。你可以把多维数组、图像、点云都塞进去,还能建立目录结构。

为什么推荐它?

  • 支持分块存储:你可以只读取某个时间段的点云,不用加载整个文件
  • 自带压缩:gzip、szip 随便选
  • 跨语言:Python、C++、MATLAB 都能读

举个例子,我存激光雷达点云时,会这样组织:

/sensor/lidar/timestamps
/sensor/lidar/points
/sensor/camera/image_raw
/sensor/camera/timestamps

这样回放时,我可以只加载 /sensor/lidar/points 这个数据集,不用管其他传感器。你想想看,如果数据量大了,这种按需加载的能力有多重要。

小技巧:

HDF5 的 chunk size 要设置合理。我一般把 chunk 设成 1 秒的数据量。这样既保证随机访问速度,又不会让 chunk 太大导致内存爆炸。

3.3 MCAP:新一代的存储格式

MCAP 是最近几年火起来的格式。它有点像 ROS Bag 的升级版,但更现代、更高效。

我最早接触 MCAP 是在一个自动驾驶项目里。当时团队嫌弃 ROS Bag 太大、太慢,就试了试 MCAP。结果发现:

  • 同样的数据,MCAP 文件比 ROS Bag 小 30% 左右
  • 随机访问速度快了不止一个数量级
  • 支持流式写入,不会因为意外断电导致整个文件损坏

MCAP 的核心设计思路是“记录 + 索引”。它把数据分成一个个记录块,然后在文件末尾建立索引。这样你回放时,可以直接跳到任意时间点,不用从头扫描。

适用场景:

  • 大规模数据采集(比如车队每天跑几百 G 数据)
  • 需要频繁随机访问的离线分析
  • 跨平台、跨语言的数据交换

3.4 自定义二进制格式:极致性能

说实话,大部分场景下,ROS Bag 或 MCAP 就够了。但如果你追求极致性能,或者有特殊需求,那就得自己动手了。

我做过一个项目,需要实时回放 128 线激光雷达的数据。ROS Bag 根本扛不住,因为它的序列化开销太大了。后来我写了一个自定义格式:

// 文件头
struct Header {
    uint32_t magic;       // 0xDEADBEEF
    uint32_t version;     // 1
    uint64_t timestamp;   // 起始时间
    uint32_t channel_count; // 传感器数量
};

// 数据包
struct Packet {
    uint64_t timestamp;   // 时间戳
    uint8_t channel_id;   // 传感器 ID
    uint32_t data_size;   // 数据长度
    uint8_t data[];       // 原始数据
};

这种格式的好处是:

  • 没有序列化开销,直接内存映射
  • 可以零拷贝读取
  • 文件结构简单,容易调试

注意:

自定义格式的维护成本很高。你想想看,如果团队里有人改了数据结构,但忘了更新解析代码,那整个数据就废了。我建议只在性能瓶颈明显时采用这种方式。

3.5 数据压缩策略

数据压缩不是可选项,而是必选项。尤其是多传感器系统,数据量动不动就上 G。

我常用的压缩策略分三种:

压缩方式 适用场景 压缩比 速度
LZ4 实时录制、回放 2:1 ~ 3:1 极快
Zstd 离线存储、归档 3:1 ~ 5:1 较快
JPEG/PNG 图像数据 10:1 ~ 50:1 取决于编码器

我个人习惯:

  • 录制时用 LZ4,保证不丢帧
  • 归档时用 Zstd,追求存储效率
  • 图像数据单独压缩,不用通用压缩器

避坑指南:

我曾经试过用 gzip 压缩点云数据,结果压缩率只有 1.5:1,还特别慢。后来换成 Zstd,压缩率到了 3:1,速度还快了一倍。所以,选对压缩器很重要。

3.6 知识体系总览

下面这张图是我自己总结的,帮你快速理清思路:

多传感器数据存储格式选择 数据存储格式 ROS Bag HDF5 MCAP 自定义二进制 原生ROS支持 简单易用 文件较大 科学计算 多维数组 按需加载 高性能 随机访问 流式写入 极致性能 零拷贝 维护成本高 数据压缩策略 LZ4 - 实时录制 Zstd - 离线归档 JPEG/PNG - 图像 选择建议:实时用LZ4,归档用Zstd,图像单独压缩

这张图把四种存储格式和三种压缩策略串起来了。你从上往下看,先选格式,再选压缩方式。嗯,这样思路就清晰多了。

最后说一句:没有完美的格式,只有最适合你场景的格式。我建议你根据数据量、访问模式、团队技术栈来综合选择。别盲目追求新技术,也别死守着老格式不放。

可可精品资料库