第三章 传感器与数据预处理:激光雷达、毫米波雷达、相机数据特点、数据对齐与时间戳同步、坐标变换
各位同学,欢迎来到第三章。这一章我们聊聊传感器的“脾气”。
做轨迹预测,说白了就是让车“看懂”周围世界。但车没有眼睛,它靠的是传感器。激光雷达、毫米波雷达、相机——这三兄弟各有各的性子。你得摸透它们,才能用好数据。
我个人习惯把传感器比作三种人:
激光雷达像个严谨的测绘员,精度高但怕雨雾;
毫米波雷达像个固执的老兵,测距准但看不清细节;
相机呢,像个画家,色彩丰富但容易受光线影响。
嗯,咱们一个一个来拆解。
3.1 激光雷达数据特点
激光雷达(LiDAR)发射激光束,测量反射时间。它直接给你三维点云——一堆(x, y, z)坐标点。
核心特点:
- 精度高:厘米级测距,我见过最好的能达到±2cm。
- 稀疏性:线数越多点越密。16线雷达在100米外,一个目标可能只有几个点。
- 无纹理:点云只有几何信息,没有颜色。你分得清红绿灯和路灯杆吗?光靠点云不行。
- 受天气影响大:雨、雾、雪会让激光散射。我在项目中遇到过暴雨天,点云直接变成“雪花屏”。
避坑指南:我曾经在高速项目里,用32线雷达检测远处的小轿车。结果发现,80米外的车只有3-4个点。做聚类时,这些点很容易被当成噪声滤掉。后来我调整了聚类半径参数,才把召回率提上来。
3.2 毫米波雷达数据特点
毫米波雷达用电磁波,波长在毫米级。它不靠光,所以不怕雨雾。
核心特点:
- 测距远:一般能到200米以上,高端雷达能到300米。
- 直接测速:利用多普勒效应,直接输出目标的速度。这点激光雷达做不到。
- 角度分辨率低:这是硬伤。普通雷达角度分辨率只有几度,目标稍微靠近就分不清。
- 数据稀疏:输出的是目标列表,不是点云。每个目标有距离、速度、角度,但没形状。
你想想看,毫米波雷达告诉你“前方50米有个目标,速度10m/s”。但它说不清那是轿车还是摩托车。这就得靠其他传感器来补。
我的经验:毫米波雷达的“虚警”问题很常见。路边的金属护栏、隧道墙壁,都可能被误报成目标。我一般会加一个“静止目标置信度”过滤,把静止目标先筛一遍。
3.3 相机数据特点
相机嘛,大家都熟悉。它输出图像,有颜色、有纹理。
核心特点:
- 信息丰富:能识别车道线、交通标志、行人姿态。这些是激光雷达和雷达做不到的。
- 无直接深度:单目相机没有距离信息。你得靠视觉测距或双目立体匹配来估算。
- 受光照影响大:逆光、夜间、隧道出入口,图像质量会急剧下降。
- 帧率高:一般30fps,高的能到60fps。但处理起来也费算力。
说白了,相机是“最像人眼”的传感器,但它缺少深度。所以自动驾驶里,相机通常和激光雷达或毫米波雷达做融合。
注意:相机标定很重要。内参、外参稍微偏一点,投影到点云上的位置就错位了。我见过一个团队,因为相机标定板没放平,导致整个融合结果偏移了半米。嗯,这种低级错误千万别犯。
3.4 数据对齐与时间戳同步
传感器数据来了,但它们是“各说各话”。激光雷达10Hz,相机30Hz,毫米波雷达20Hz。时间戳对不上,融合就是笑话。
为什么需要同步?
假设激光雷达在t1时刻扫到一个障碍物,相机在t2时刻拍到同一位置。如果t1和t2相差100ms,而车在高速行驶,那障碍物的位置已经变了。你拿t1的点云去投影t2的图像,结果就是错位。
同步方法:
- 硬件同步:用GPS的PPS信号或IEEE 1588协议,给所有传感器打上统一的时间戳。这是最可靠的方式。
- 软件同步:如果硬件不支持,就用插值。比如激光雷达帧在t1,相机帧在t2,你根据时间差做线性插值,估算t1时刻的相机数据。
- 时间戳对齐:找到最近邻的时间戳对。比如激光雷达10Hz(每100ms一帧),相机30Hz(每33ms一帧),你找时间差最小的那一对。
避坑指南:我曾经在项目中只用软件同步,结果发现时间戳漂移越来越严重。后来查出来,是系统时钟没有用NTP同步。从那以后,我坚持硬件同步为主,软件同步为辅。
3.5 坐标变换
每个传感器都有自己的坐标系。激光雷达的坐标系原点在车顶,相机的坐标系在挡风玻璃后,毫米波雷达的坐标系在前保险杠。你得把它们统一到同一个坐标系下。
常见的坐标系:
- 传感器坐标系:每个传感器自己的局部坐标系。
- 车辆坐标系:通常以车辆后轴中心为原点,x轴向前,y轴向左,z轴向上。
- 世界坐标系:全局坐标系,比如UTM坐标系。
变换流程:
- 标定每个传感器相对于车辆坐标系的外参(旋转矩阵R和平移向量t)。
- 将传感器数据从传感器坐标系变换到车辆坐标系。
- 如果需要,再从车辆坐标系变换到世界坐标系。
举个例子,激光雷达点云从激光雷达坐标系变换到车辆坐标系:
# 伪代码示例
def transform_lidar_to_vehicle(points, R, t):
"""
points: Nx3 的点云数组
R: 3x3 旋转矩阵
t: 3x1 平移向量
"""
# 先旋转,再平移
transformed = np.dot(points, R.T) + t
return transformed
我的习惯:我一般会用齐次坐标来写变换,这样旋转和平移可以合并成一个4x4矩阵。代码更简洁,也更容易调试。
3.6 实战:多传感器融合前的数据预处理
好了,理论讲完了。咱们看看实际怎么做。
步骤一:时间戳同步
假设你有一个激光雷达帧(时间戳t_l)和一个相机帧(时间戳t_c)。如果|t_l - t_c| < 10ms,就认为它们是同步的。否则,丢弃或插值。
步骤二:坐标变换
把激光雷达点云从激光雷达坐标系变换到相机坐标系。然后投影到图像平面,看看点云和图像是否对齐。
# 点云投影到图像
def project_points_to_image(points_3d, K, R_cam, t_cam):
"""
points_3d: 在车辆坐标系下的3D点
K: 相机内参矩阵
R_cam, t_cam: 相机相对于车辆坐标系的外参
"""
# 变换到相机坐标系
points_cam = np.dot(R_cam, points_3d.T).T + t_cam
# 投影到图像平面
points_2d = np.dot(K, points_cam.T).T
points_2d = points_2d[:, :2] / points_2d[:, 2:3]
return points_2d
步骤三:数据过滤
去掉无效数据。比如激光雷达的远距离噪点、毫米波雷达的静止虚警、相机的过曝区域。
注意:数据过滤要谨慎。我曾经因为过滤太狠,把一辆停在路边的车给滤掉了。结果规划模块以为前方无障碍,直接加速...嗯,后来我加了一个“低置信度保留”策略。
3.7 总结
这一章我们聊了三种传感器的特点、时间同步和坐标变换。说白了,传感器数据预处理就是“对齐”和“统一”。对齐时间,统一坐标系。
我个人觉得,这部分工作虽然枯燥,但特别重要。数据质量决定了上层算法的上限。你想想看,如果输入的数据都是错的,那轨迹预测再牛也没用。
下一章,我们会讲如何用这些预处理后的数据做目标检测和跟踪。到时候,你会发现今天的功夫没有白费。
一句话记住本章:传感器数据预处理,就是让不同“语言”的传感器,用同一个“时钟”和同一个“坐标系”说话。