3、数据采集基础:传感器数据采集原理与格式
好,咱们进入实战环节的第一个硬核模块——数据采集。
说实话,很多做算法的朋友容易忽略这一步。他们觉得数据嘛,拿来用就行了。但我得说句实在话:数据采集的质量,直接决定了你后面所有工作的天花板。你模型再牛,输入的是垃圾,输出也只会是垃圾。
这一章,咱们就聊聊三种最常用的传感器:相机、激光雷达、IMU。我会结合我踩过的坑,把它们的原理、数据格式、以及怎么存怎么传,一次性讲清楚。
3.1 相机:最直观的“眼睛”
相机采集的是图像数据。说白了,就是把三维世界投影到二维平面上。
这里有个关键点:相机采集的不是“照片”,而是“光强分布”。每个像素点记录的是该位置接收到的光子数量。
3.1.1 相机的工作原理
我简单说一下流程:
- 镜头:把光线聚焦到传感器上
- 传感器(CMOS/CCD):把光信号转成电信号
- ADC(模数转换器):把模拟电信号转成数字值
- ISP(图像信号处理器):做白平衡、去噪、色彩校正等处理
嗯,这里要注意:ISP处理后的图像,其实已经“失真”了。如果你做的是高精度视觉测量,我建议你尽量拿原始RAW数据。我在做自动驾驶项目时就吃过这个亏——用了ISP处理后的图像做标定,结果精度一直上不去,后来换成RAW数据才搞定。
3.1.2 相机数据格式
常见的格式有这些:
| 格式 | 说明 | 典型场景 |
|---|---|---|
| RAW | 传感器原始数据,未处理 | 高精度标定、专业摄影 |
| YUV | 亮度+色度分离存储 | 视频编码、嵌入式设备 |
| RGB/BGR | 最常见的彩色图像格式 | 通用视觉算法 |
| JPEG/PNG | 压缩格式,有损/无损 | 存储、传输 |
3.2 激光雷达:精准的“尺子”
激光雷达,简称LiDAR。它不像相机那样“看”颜色,而是直接测量距离。
原理其实很简单:发射激光束,测量反射回来的时间。光速是已知的,时间差一算,距离就出来了。
3.2.1 激光雷达的类型
- 机械式:旋转扫描,360度视野。Velodyne是代表。缺点是贵、有机械磨损
- 固态式:没有旋转部件,靠相控阵或MEMS镜片扫描。成本低,但视场角小
- 混合固态:介于两者之间,目前主流方案
我个人习惯用机械式做高精度地图采集,固态式做量产车。为什么?机械式精度高,但寿命短;固态式寿命长,但视野受限。没有完美的方案,只有适合的方案。
3.2.2 点云数据格式
激光雷达采集的数据叫“点云”。每个点包含:
- xyz坐标:三维空间位置
- intensity(强度):反射回来的光强,可以区分不同材质
- ring(环号):属于哪条扫描线
- timestamp(时间戳):每个点的精确时间
避坑指南:我曾经遇到过一个问题——激光雷达的点云时间戳不准确。后来发现是驱动里用了系统时间,而系统时间被NTP同步时跳变了。解决方案是:用激光雷达硬件提供的PPS信号做时间同步,或者用GPS的PTP协议。
3.3 IMU:感知“姿态”的陀螺仪
IMU(惯性测量单元)包含加速度计和陀螺仪。加速度计测线加速度,陀螺仪测角速度。
说白了,IMU就是告诉你“我现在在怎么动”。但它有个致命问题:漂移。
3.3.1 IMU的误差来源
- 零偏:静止时输出不为0
- 噪声:随机波动
- 温漂:温度变化导致参数变化
- 尺度因子误差:输出值与真实值的比例偏差
你想想看,加速度计测的是加速度,你要得到位置,得积分两次。积分一次,误差累积一次。所以纯IMU定位,几秒钟就飘得没边了。
3.4 数据格式与协议
数据采回来了,怎么存?怎么传?这里介绍两种最主流的格式。
3.4.1 ROS Bag
ROS(机器人操作系统)的Bag文件,是机器人领域的事实标准。
它的核心思想是:把不同话题(topic)的数据按时间戳存到一起。
# 录制bag
rosbag record /camera/image_raw /lidar/points /imu/data
# 回放bag
rosbag play 2024-01-15-10-30-00.bag
# 查看bag信息
rosbag info 2024-01-15-10-30-00.bag
Bag的好处是:
- 时间同步:所有数据按时间戳对齐
- 多传感器:一个文件包含所有数据
- 可回放:像放录像一样回放数据
但Bag也有缺点:文件体积大,不支持随机访问。你想查第1000帧的数据,得从头读到第1000帧。
3.4.2 HDF5
HDF5是科学计算领域常用的格式。它比Bag更灵活,支持:
- 分层结构:像文件夹一样组织数据
- 随机访问:直接读取任意位置的数据
- 压缩:内置压缩算法,节省空间
- 并行I/O:多线程同时读写
import h5py
import numpy as np
# 写入HDF5
with h5py.File('sensor_data.h5', 'w') as f:
# 创建组
camera_group = f.create_group('camera')
lidar_group = f.create_group('lidar')
# 写入数据
camera_group.create_dataset('image_0001', data=image_data)
camera_group.create_dataset('timestamp', data=timestamps)
lidar_group.create_dataset('point_cloud_0001', data=point_cloud)
lidar_group.create_dataset('intensity', data=intensity_data)
# 读取HDF5
with h5py.File('sensor_data.h5', 'r') as f:
image = f['camera/image_0001'][:]
points = f['lidar/point_cloud_0001'][:]
3.5 时间同步:被忽视的关键
最后,我必须强调一个容易被忽视的问题——时间同步。
相机、激光雷达、IMU各自有自己的时钟。如果不做同步,你拿到的数据就是“错位的”。比如相机拍到一辆车在位置A,激光雷达却认为它在位置B。
解决方案:
- 硬件同步:用GPS的PPS信号给所有传感器提供统一时钟
- 软件同步:用NTP或PTP协议做网络时间同步
- 后处理同步:采集时记录每个数据的时间戳,事后做插值对齐
好了,这一章的内容就到这里。数据采集是基础中的基础,别嫌烦,把这一步做扎实了,后面的路会顺很多。