2、坐标系与投影基础:相机坐标系、激光雷达坐标系、IMU坐标系、自车坐标系、坐标系之间的转换关系
做BEV融合,说白了就是解决一个问题:不同传感器看到的世界,怎么对齐到同一个“地图”上?
我刚开始接触多传感器融合时,踩过一个坑——激光雷达点云投影到图像上,怎么都对不准。后来发现,不是算法错了,是坐标系标定参数给反了。嗯,从那以后,我养成了一个习惯:动手之前,先把坐标系捋清楚。
这一章,我们就来拆解BEV空间融合中最核心的坐标系基础。你想想看,摄像头、激光雷达、IMU、自车,每个传感器都有自己的“小世界”,我们要做的,就是把这些小世界统一到自车坐标系下,再投影到BEV视角。
2.1 四大坐标系,各自扮演什么角色?
先给个全景图。BEV融合中,我们打交道最多的就是这四个坐标系:
| 坐标系 | 原点位置 | 轴定义(常见约定) | 典型用途 |
|---|---|---|---|
| 相机坐标系 | 相机光心 | Z轴指向车辆前方,X轴向右,Y轴向下 | 图像特征提取、2D检测 |
| 激光雷达坐标系 | 激光雷达中心 | X轴指向车辆前方,Y轴向左,Z轴向上 | 点云感知、3D目标检测 |
| IMU坐标系 | IMU芯片中心 | X轴指向车辆前方,Y轴向右,Z轴向上 | 姿态估计、位姿推算 |
| 自车坐标系 | 后轴中心(或车辆质心) | X轴指向车辆前方,Y轴向左,Z轴向上 | BEV空间统一表示 |
核心原则:所有传感器数据,最终都要转换到自车坐标系下,才能进行BEV空间融合。这是铁律。
2.2 相机坐标系:从像素到空间的桥梁
相机坐标系,我个人觉得是四个坐标系里最“绕”的。因为它涉及从3D世界到2D图像的投影,中间还夹着一个图像坐标系。
先看相机坐标系本身。它的原点在光心,Z轴指向车辆前方。注意,这里的Z轴方向和激光雷达的Z轴方向可能不同——激光雷达的Z轴是朝上的。
相机坐标系下的一个3D点 (X_c, Y_c, Z_c),要投影到图像上,需要经过两步:
- 归一化平面投影: (x, y) = (X_c / Z_c, Y_c / Z_c)
- 像素坐标转换: (u, v) = (f_x * x + c_x, f_y * y + c_y)
写成矩阵形式就是:
s * [u, v, 1]^T = K * [R | t] * [X_w, Y_w, Z_w, 1]^T
其中K是内参矩阵,[R|t]是外参矩阵。
我的经验:在实际项目中,我习惯把相机外参直接标定到自车坐标系下,而不是先标到激光雷达再转。少一次转换,少一次误差累积。
2.3 激光雷达坐标系:点云的“老家”
激光雷达坐标系相对直观。它的原点在激光雷达的旋转中心,X轴指向车辆前方,Y轴向左,Z轴向上。
每个激光点,在激光雷达坐标系下表示为 (X_l, Y_l, Z_l)。这个坐标直接来自激光雷达的测距和角度信息。
我记得有一次,项目里用的激光雷达是32线的,点云密度不高。做BEV投影时,如果坐标系转换参数有0.1度的偏差,远处的点就会偏出好几个像素。所以,激光雷达到自车坐标系的标定,精度要求非常高。
转换公式很简单:
P_ego = R_lidar_to_ego * P_lidar + T_lidar_to_ego
其中R是旋转矩阵,T是平移向量。
注意:不同厂家的激光雷达,坐标系定义可能不同。比如有些厂家把Y轴定义为向右。拿到传感器数据后,第一件事就是确认坐标系定义文档。
2.4 IMU坐标系:姿态的“感知器”
IMU坐标系,说白了就是加速度计和陀螺仪的“参考系”。它的原点在IMU芯片的物理中心。
IMU不直接提供位置信息,它提供的是加速度和角速度。通过积分,我们可以得到姿态(roll, pitch, yaw)和速度。
在BEV融合中,IMU的主要作用是:
- 提供高频的姿态信息,用于补偿帧间运动
- 辅助激光雷达和相机的联合标定
- 在GPS信号弱时,提供短时的位姿推算
IMU坐标系到自车坐标系的转换,通常是一个固定的旋转。因为IMU在车上的安装位置是固定的。
避坑指南:我曾经遇到过IMU和自车坐标系的Y轴方向相反的情况。如果直接使用IMU的yaw角,会导致车辆转弯时BEV地图旋转方向错误。解决办法是:在标定文件中明确记录IMU到自车坐标系的旋转矩阵。
2.5 自车坐标系:BEV空间的“锚点”
自车坐标系,是所有传感器数据最终要汇聚的地方。它的原点通常选在后轴中心在地面的投影点,X轴指向车辆前方,Y轴向左,Z轴向上。
为什么选后轴中心?因为车辆运动时,后轴中心基本没有侧向滑动,适合作为运动基准。
在BEV融合中,自车坐标系下的点 (X_e, Y_e, Z_e) 可以直接投影到BEV俯视图上:
BEV_x = X_e / resolution + offset_x
BEV_y = Y_e / resolution + offset_y
其中resolution是BEV网格的分辨率,比如0.1米/像素。
2.6 坐标系转换:从分散到统一
好了,现在四个坐标系都介绍完了。关键问题来了:怎么把相机、激光雷达、IMU的数据都转到自车坐标系下?
转换流程是这样的:
- 相机 → 自车: 通过相机外参(旋转+平移),将相机坐标系下的3D点转到自车坐标系
- 激光雷达 → 自车: 通过激光雷达外参,将点云转到自车坐标系
- IMU → 自车: 通过IMU外参,将IMU的姿态数据转到自车坐标系
写成代码就是:
def transform_point(point, source_to_ego):
"""
point: 源坐标系下的3D点 (3,)
source_to_ego: 4x4 变换矩阵
"""
point_h = np.append(point, 1) # 齐次坐标
point_ego_h = source_to_ego @ point_h
return point_ego_h[:3]
我的习惯:我会把所有外参都存成4x4的齐次变换矩阵。这样,无论从哪个坐标系转到自车坐标系,都是一次矩阵乘法,代码非常统一。
2.7 实战中的坐标系标定流程
在实际项目中,坐标系标定通常分两步走:
| 步骤 | 内容 | 工具/方法 |
|---|---|---|
| 1. 内参标定 | 标定相机内参(焦距、畸变系数等) | 棋盘格标定板 + OpenCV |
| 2. 外参标定 | 标定各传感器到自车坐标系的变换 | 标定场、手动测量、联合优化 |
外参标定是最容易出问题的环节。我建议:
- 先在标定场里用已知标志物做粗标定
- 再用多帧数据做联合优化,精调参数
- 最后用实际场景验证——比如把激光雷达点云投影到图像上,看边缘是否对齐
警告:车辆行驶过程中,传感器可能会因为振动而发生微小的位移。所以,定期重新标定是必要的。我见过一个项目,因为一次追尾事故导致激光雷达支架变形,标定参数失效,整个感知系统直接“瞎”了。
2.8 总结:坐标系是BEV融合的“地基”
这一章的内容,说白了就是一件事:把不同传感器的数据,统一到同一个空间参考系下。
你想想看,如果坐标系转换错了,后面的BEV特征融合、目标检测,全都是空中楼阁。所以,我每次开始一个新项目,都会花至少一周时间做标定验证。
下一章,我们会进入BEV空间融合的核心——如何把图像特征和点云特征投影到BEV网格上。到时候,坐标系转换的知识会直接派上用场。
嗯,坐标系基础就讲到这里。有什么问题,欢迎在课程群里讨论。