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 知识体系总览
下面这张图是我自己总结的,帮你快速理清思路:
这张图把四种存储格式和三种压缩策略串起来了。你从上往下看,先选格式,再选压缩方式。嗯,这样思路就清晰多了。
最后说一句:没有完美的格式,只有最适合你场景的格式。我建议你根据数据量、访问模式、团队技术栈来综合选择。别盲目追求新技术,也别死守着老格式不放。