第一章:坐标系与标定基础
各位同学,欢迎来到《自动驾驶感知系统从零搭建指南》。我是你们这门课的老司机。
今天咱们聊点最基础,但也最要命的东西——坐标系和标定。
你想想看,一辆车在路上跑,它得知道自己在哪里,周围的车在哪里,摄像头拍到的画面里那个行人到底在哪个位置。这些信息怎么串起来?靠的就是坐标系之间的转换。说白了,就是给每个物体都贴上一个精确的「空间坐标标签」。
1.1 世界坐标系:给地球贴个网格
世界坐标系,你可以把它想象成一个巨大的三维网格,覆盖在整个地球上。这个网格是固定的,不会因为车动了就跟着跑。
我习惯用东北天坐标系(ENU)作为世界坐标系。X轴指向东,Y轴指向北,Z轴指向天空。为什么这么选?因为直观。你站在路边,往东走就是X正方向,往北走就是Y正方向,跳起来就是Z正方向。
关键点:世界坐标系是所有坐标系的「最终参照物」。不管你的车怎么动,相机怎么转,最后都要统一到世界坐标系下说话。
举个例子。我在做高精地图项目时,地图上的每个车道线点,存的都是世界坐标。车跑起来后,实时定位自己的世界坐标,然后去地图里查前方路况。如果坐标系对不上,那后果...嗯,你懂的。
1.2 车辆坐标系:车就是宇宙中心
车辆坐标系是跟着车走的。一般定义:
- X轴:车头方向(前进方向)
- Y轴:车身左侧方向
- Z轴:车顶方向(垂直向上)
原点通常放在后轴中心,或者车辆质心。我个人建议放在后轴中心,因为车辆运动学模型用这个原点算起来最方便。
车辆坐标系有什么用?
比如你的车检测到前方20米有个障碍物。这个「前方20米」就是在车辆坐标系下说的。如果车转了弯,这个障碍物在车辆坐标系下的坐标会变,但在世界坐标系下的坐标其实没变。
小技巧:写代码时,我习惯把车辆坐标系的数据先存一份原始值,再去做转换。万一转换出错了,还能回头查原始数据。这个习惯救过我不少次。
1.3 相机坐标系:摄像头看世界的方式
相机坐标系的原点在相机光心,Z轴指向镜头前方(也就是拍摄方向),X轴向右,Y轴向下。
等等,为什么Y轴是向下的?
因为图像坐标系的原点在左上角,Y轴向下。为了和图像坐标系保持一致,相机坐标系也这么定了。你想想看,如果相机坐标系的Y轴向上,图像坐标系的Y轴向下,每次转换都要取反,多麻烦。
相机坐标系里,一个物体的坐标是 (Xc, Yc, Zc)。Zc就是物体到相机的深度距离。这个深度值怎么来?可以用双目视觉,也可以用激光雷达,或者用单目深度估计。后面章节我会详细讲。
注意:相机坐标系和图像坐标系之间的转换,涉及内参矩阵。内参标定不准,后面所有计算都是错的。我曾经见过一个团队,标定板打印尺寸写错了,结果内参偏了5%,整个感知系统全废了。这种坑,踩一次就够了。
1.4 图像坐标系:像素的世界
图像坐标系就是你在屏幕上看到的那个二维网格。原点在左上角,u轴向右,v轴向下。单位是像素。
一个像素点 (u, v) 对应相机坐标系里的某条射线。具体是哪条射线?需要内参矩阵来算。
内参矩阵长这样:
K = [fx, 0, cx]
[ 0, fy, cy]
[ 0, 0, 1]
其中 fx, fy 是焦距(像素单位),cx, cy 是光心在图像上的位置。
这个矩阵的作用,就是把相机坐标系里的点 (Xc, Yc, Zc) 投影到图像上:
u = fx * Xc / Zc + cx
v = fy * Yc / Zc + cy
说白了,就是三维到二维的映射。这个映射关系,是相机标定要解决的核心问题。
1.5 传感器内参和外参标定
标定分两种:内参标定和外参标定。
内参标定
内参是传感器「自己」的参数。比如相机的焦距、畸变系数;激光雷达的扫描角度、距离偏移量。
内参标定怎么做?
拿相机来说,你打印一张棋盘格标定板,从不同角度拍20-30张照片。然后用OpenCV的 calibrateCamera() 函数算内参。我一般会多拍几张,把标定板放在画面的各个角落,尤其是边缘。因为边缘的畸变最明显,多拍几张能提高标定精度。
我的经验:标定板一定要平整。我曾经用一张海报当标定板,结果海报有点皱,标出来的内参全是歪的。后来换了亚克力板做的标定板,一次搞定。别在这种地方省钱。
外参标定
外参是传感器之间的「相对位置和朝向」。比如相机装在车上,它相对于车辆坐标系的位置和旋转角度,就是外参。
外参标定更麻烦。因为你要让两个传感器「看到」同一个物体,然后算它们之间的变换矩阵。
常用的方法:
- 手动测量:用尺子量位置,用量角器量角度。精度一般,但简单粗暴。
- 目标物标定:放一个标定板或者标定杆,让两个传感器同时采集数据,然后优化求解外参。
- 在线标定:车跑起来后,用SLAM或者结构光的方法实时估计外参。这个比较高级,后面章节会细讲。
避坑指南:我曾经做过一个项目,激光雷达和相机的外参标定差了2厘米。结果在30米外,投影误差放大了将近半米。行人检测直接漏检。所以外参标定,毫米级的精度都不够,得往亚毫米级去抠。
1.6 坐标系转换:把一切串起来
现在我们有四个坐标系了。怎么把它们串起来?
一个典型的流程是这样的:
- 相机拍到图像,得到像素坐标 (u, v)
- 用内参矩阵,把像素坐标转成相机坐标 (Xc, Yc, Zc)
- 用外参矩阵,把相机坐标转成车辆坐标 (Xv, Yv, Zv)
- 用车辆定位信息,把车辆坐标转成世界坐标 (Xw, Yw, Zw)
每一步都是一个矩阵乘法。公式长这样:
Pw = R_v2w * (R_c2v * (K_inv * p_img) + T_c2v) + T_v2w
看着复杂?其实拆开看就是:
- 先把像素点反投影到相机坐标系
- 再转到车辆坐标系
- 最后转到世界坐标系
每一步的矩阵,都是标定出来的。所以我说,标定是感知系统的地基。地基不稳,楼盖得再高也得塌。
1.7 本章小结
这一章我们聊了:
- 世界坐标系:固定的大地网格
- 车辆坐标系:跟着车跑的坐标系
- 相机坐标系:摄像头视角下的三维空间
- 图像坐标系:像素的二维世界
- 内参标定:传感器自己的参数
- 外参标定:传感器之间的相对关系
这些概念,后面每一章都会用到。别急着一口气全记住,先有个印象就行。等后面做实际项目时,你会慢慢理解它们有多重要。
下一章,咱们聊聊相机模型和成像原理。到时候我会带你们手撕投影矩阵,把今天讲的这些坐标系转换,用代码实现一遍。
下课。