车一进隧道,GNSS信号瞬间归零,车道线也因为反光变得时有时无。这时候系统如果只靠惯性积分推算位置,三秒钟后车身横向误差就能到半米,再过一个路口,整条定位轨迹可能已经偏到隔壁车道去了。这种场景,做自动驾驶定位的人一定不陌生。而SLAM技术框架,恰恰是解决这种“无外部信号依赖”问题的关键:它不需要卫星、不需要基站,只靠车上的传感器,就能在未知环境里同时解决“我在哪”和“周围长什么样”两个问题。
这篇文章我想从工程视角,把SLAM技术框架和自动驾驶定位方案完整梳理一遍。不论你是刚接触机器人定位的学生,还是在车规项目里被“地库定位漂移”折磨的工程师,这篇内容都能给你一个可以直接上手的知识框架:先拆SLAM的内部模块,再谈传感器选型和多传感器融合,然后把自动驾驶场景下“怎么把SLAM用稳”的工程经验摊开讲,最后附上开源框架、公共数据集和避坑清单。
1. SLAM技术框架:同步定位与建图到底是怎么跑起来的
1.1 定位与建图,为什么非绑定不可
SLAM的全称是Simultaneous Localization and Mapping,中文叫同步定位与建图。字面意思很直白:一边定位,一边建图。但很多人刚接触时会困惑,定位和建图明明是两件事,为什么要放在同一个框架里解决?
原因在于两者是相互依赖的。定位需要一个“参考系”,如果你手里没有环境地图,那“我在哪”就只能靠相对运动来推算,误差会像滚雪球一样越滚越大。反过来,建图也需要知道传感器在每个时刻的位置,否则点云或图像投到全局坐标时会对不齐,地图就是糊的。这就好比一个人蒙着眼睛在陌生的商场里走:他想知道自己走到了哪里,但手里没有导购图;他想画一张导购图,但不知道自己的每一步落在哪。SLAM的思路是把这两个问题放在同一个状态估计里同步求解,用“刚才的匹配结果”修正当前位姿,再用“当前的位姿”更新地图,迭代推进。
理解这个耦合关系特别重要,因为很多工程问题的根源就在这。比如松耦合方案里,定位模块和建图模块各跑各的,一旦坐标系没对齐或者时间没同步,地图就会出现重影和错位,而不是像紧耦合那样通过联合优化把误差压到最小。
1.2 前端里程计:帧与帧之间如何算出相对运动
SLAM框架的第一个核心模块是前端里程计,它的任务很纯粹:基于连续两帧或多帧传感器数据,估算传感器在这段时间内的相对运动。
视觉SLAM里,前端主流分成特征点法和直接法。特征点法先提取ORB、SIFT这类特征点,再通过描述子匹配找到两帧之间的对应关系,最后用对极几何或PnP解算相对位姿。它的优点是稳定、对光照变化相对鲁棒,缺点是在纹理稀疏的环境里容易跟丢。直接法不去提取特征,而是假设同一个空间点的像素亮度在帧间不变,通过最小化光度误差来求位姿,在弱纹理场景下表现更好,但对光照变化很敏感,而且对初值要求高。
激光SLAM里,前端通常做帧间配准。最常用的是ICP(迭代最近点)和NDT(正态分布变换)两类方法。ICP直接搜索最近邻点求刚体变换,收敛精度高但容易陷入局部极值,对初始位姿要求高。NDT先把点云栅格化,计算每个栅格内的正态分布,再通过最大化点落在目标分布上的概率求位姿,稳定性和速度都更适合工程落地。实测下来,在园区低速场景里,NDT在大部分情况下都能跑到毫米级精度,但遇到长走廊、空旷广场这类几何退化环境时,两个方向上的约束会明显不足,就必须靠IMU和其他传感器补位。
1.3 后端优化:从卡尔曼滤波到因子图
前端里程计给的是相邻两帧之间的“小增量”,但如果只把这些增量累加起来,误差会不断累积,最终轨迹完全漂走。后端的职责就是把这些有噪声的观测放到一个全局优化问题里,得到一致性好得多的轨迹和地图。
早期方案以扩展卡尔曼滤波(EKF)为主,它假设系统状态服从高斯分布,通过预测和更新两步递推。EKF在小场景、单传感器场景下够用,但它的线性化误差会随着系统非线性增强而变大,而且每次更新都要维护协方差矩阵,传感器一多计算量就爆炸。
现代SLAM基本都转向了图优化,也就是把位姿和路标点当成图的节点,把观测约束当成图的边,通过最小二乘来调整节点使得所有边的残差最小。再往上一层,因子图进一步把问题结构化:每个因子代表一类观测的概率约束,通过增量平滑与求积(iSAM2)可以做到只更新受影响的局部区域,很适合自动驾驶这种需要长时间运行、传感器类型多的场景。你在LIO-SAM、ORB-SLAM3这些开源框架里看到的“后端”,基本都是因子图优化的变体。
1.4 回环检测与建图:把“想起来过这里”变成全局一致
只有前端和后端,轨迹和地图仍然会有缓慢的累积漂移。回环检测解决的就是“认出曾经到过的地方”,然后把这个闭环约束加入到后端优化里,一次性把累积误差拉回来。
视觉SLAM最经典的做法是用词袋模型,也就是把图像中提取到的特征描述子聚成一个个“视觉单词”,再用单词的分布直方图来检索相似帧。激光SLAM则常用基于描述子的方法,比如Scan Context,把一帧激光扫描编码为矩阵,通过矩阵相似度快速找候选回环。找到候选之后,还要做几何校验:用ICP或PnP算出相对位姿,如果残差够小、内点数够多,才判定为真正回环。
建图模块则是把优化后的位姿和传感器观测投影到全局坐标系,生成可供下游使用的产物。激光SLAM一般输出点云地图,视觉SLAM会生成稀疏路标点图或稠密深度图,再往上还有栅格地图、拓扑地图和语义地图。有一点值得注意,在做自动驾驶定位时,我们往往不是在实时建图,而是预先用高精度传感器建好先验地图,再把建图模块“下线”,让实时SLAM专注于定位本身。
2. 传感器选型与多传感器融合定位方案
2.1 激光SLAM路线:精度高、但怕材质和天气
激光SLAM是目前自动驾驶和高精度定位落地最稳的路线,核心原因是激光雷达直接测量三维几何,不受环境纹理影响,精度高且稳定。机械式激光雷达能扫一圈360度,点云密度高,但体积大、成本高;固态激光雷达和补盲雷达体积小、可靠性高,但视场角受限,通常在车头、车尾和两侧布置多台互补。
框架方面,LOAM系算法奠定了“特征提取+帧间匹配+局部地图优化”的基本范式,腿边沿点和平面点被提取出来做几何约束,计算效率很高。后来的LEGO-LOAM对它做了轻量化和地面约束优化,LIO-SAM则把IMU预积分和回环检测加进来,形成了更完整的系统。FAST-LIO2是近几年的热门方案,它把直接法配准和迭代误差状态卡尔曼滤波融合在一起,计算量小、精度高,不需要显式提取特征,在嵌入式平台上也能跑得很流畅。
但激光SLAM有两大软肋。第一,对材质敏感:深色车漆、玻璃幕墙、金属反光面会吸收或散射激光,点云直接缺一块。第二,在雨雾天气下,雨滴和雾气会产生大量噪声点,如果不做强滤波,匹配精度会显著下降。这些短板决定了激光方案必须结合IMU和视觉来兜底,而不是单打独斗。
2.2 视觉SLAM路线:信息丰富、但短板也明显
视觉SLAM的优势是信息维度高,能看到颜色、纹理、文字、路牌这些几何之外的特征,而且摄像头成本低。ORB-SLAM系列是特征点法的代表,ORB-SLAM3已经支持单目、双目和RGB-D,还加入了多地图系统,在视觉SLAM领域属于标杆。VINS-Mono和VINS-Fusion则是视觉与IMU紧耦合的经典,前者单目视觉加IMU,后者支持双目和GPS融合。
视觉方案在室内、纹理丰富、光照稳定的环境里表现不错,但一上自动驾驶实车,短板立刻暴露出来:逆光时过曝,夜间噪点激增,雨天挡风玻璃起雾,隧道内亮度突变导致跟踪丢失。纯视觉SLAM做自动驾驶定位目前还不算稳健,更常见的用法是视觉与激光、高精地图配合,做语义特征匹配和车道线确认。
2.3 多传感器融合的两种耦合方式与工程常态
实际自动驾驶定位必须多传感器融合,这里先分清两种耦合方式。
松耦合是各个传感器先各自求出位姿或观测,再送入融合模块做加权或滤波。优点是模块独立性好、便于调试和故障隔离,缺点是各模块的协方差建模比较粗糙,信息利用不充分。紧耦合则是把原始观测(点云、像素、IMU读数)直接丢进同一个状态估计器里联合优化,精度上限更高,但一个传感器出问题可能会污染整个状态估计。工程上,LIO-SAM、FAST-LIO2都是典型的紧耦合激光-惯性系统,VINS-Fusion是典型的视觉-惯性紧耦合。
在工程常态里,我见得最多的组合方式是:GNSS/INS组合导航提供全局参考,激光惯性SLAM提供局部高精度位姿,视觉提供语义特征和车道线修正,轮速计提供短时退化兜底。这些定位源通过误差状态卡尔曼滤波或因子图优化融合,同时输出协方差、匹配残差、GNSS观测质量等指标,供上层做定位置信度评估和仲裁。
3. 自动驾驶场景下的定位方案实践
3.1 自动驾驶为什么不能只靠一套SLAM
很多初学者会有个疑问:既然SLAM能在未知环境里定位建图,那自动驾驶直接上一套激光SLAM不就行了?答案是:不行,至少量产车不行。
原因有三。第一,SLAM的定位精度高度依赖环境退化程度,在空旷广场、长隧道、雪地这类几何退化场景里,激光SLAM的横向和高度约束会退化,轨迹很容易漂移。第二,SLAM没有全局修正能力,回环检测在车辆沿一条路直行几公里的场景里几乎用不上,累积误差会一路增长。第三,自动驾驶定位关乎功能安全,单个算法输出无法满足“可控、可监控、可降级”的要求,必须有多源冗余和残差监测机制。所以自动驾驶定位方案的标准形态是:先验地图局部化+多源融合+退化检测与降级,SLAM在这里面扮演的是“局部高精度相对定位引擎”,而不是“万能的全局定位器”。
3.2 先验高精地图+实时SLAM:车道级定位落地思路
量产自动驾驶在L2+到L4阶段,主流做法是“高精地图先验+实时观测匹配”。先利用采集车把车道线、杆柱、路沿、交通标志等要素做成矢量地图和点云底图,然后在车辆运行时,用实时激光点云或视觉特征与底图做匹配,得到车辆在车道中的精确位置。
这里的匹配算法和SLAM里的帧图配准完全同源。点云底图一般用NDT做帧图配准,视觉底图则用特征匹配或语义特征匹配(比如用分割模型提取杆柱、路牌等稳定地标,再与地图要素关联)。NDT匹配的精度和稳定性很依赖底图质量和初值:底图有分层或重影,匹配结果就会出现周期性偏差;初值差太远,NDT可能收敛到错误位置上,所以匹配前必须用GNSS/DR给出一个“够好的初值”。
另外要强调一下,高精地图本身就有一个“鲜度”问题。道路施工、临时围挡、新划的标线都会让底图和现实不一致,所以定位系统需要实时检测“地图与观测的残差突变”,一旦发现局部地图过时,要能自动降低该区域地图匹配的权重,切换到以实时SLAM为主。
3.3 GNSS/IMU/轮速/SLAM的组合与降级逻辑
一套完整的车规级定位方案,通常由以下定位源组成:
- GNSS RTK:提供厘米级绝对位置,但容易受遮挡、多径和电磁干扰影响
- IMU:提供高频(100-200Hz)的角速度和加速度,短时精度高,长时间会漂移
- 轮速计:提供车速和基于差速的航迹推算,依赖轮胎状态,但打滑时误差大
- 激光SLAM:提供局部坐标系下厘米级相对位姿,退化场景会漂移
- 视觉定位:提供语义特征和车道级修正,对光照和纹理敏感
融合时通常采用误差状态卡尔曼滤波(ESKF)或因子图。ESKF把IMU作为运动预测核心,把其他定位源作为量测更新,状态量是位置误差、速度误差、姿态误差、零偏等。ESKF的关键在于噪声矩阵调优:GNSS噪声定得太小,遮挡时输出会剧烈跳变;SLAM噪声定得太大,融合轨迹会跟着IMU漂。工程上几乎都是先把各定位源离线录包,用真值数据统计误差分布,再反推噪声参数。
降级逻辑是定位方案里最容易被低估的一环。我的建议是画一张定位源可用性状态机:正常状态下GNSS+SLAM+IMU全开,进入隧道或地库后把GNSS权重直接关闭,切换为SLAM+IMU+轮速,再当SLAM匹配残差持续增大时,触发“盲推模式”并提醒上层限制速度,避免把错误定位传给规划控制。
3.4 功能安全视角下的定位冗余设计
把定位放在功能安全的视角里看,真正重要的不是单一传感器有多准,而是“当某个传感器出错时,系统能不能及时知道并安全接管”。定位系统在设计阶段就要做FMEA(失效模式与影响分析)和冗余仲裁。
常见做法是双通道异构冗余。比如主通道用“GNSS+IMU+激光SLAM”,备份通道用“视觉定位+轮速推算+IMU航迹推算”,两条通道独立输出,监控模块实时比较两者的偏差。偏差超过阈值时,系统判定定位异常,进入最小风险策略。还有一类做法是在同一通道内部做一致性检测,比如NDT匹配残差突变、GNSS载波相位跳变、IMU零偏漂移超限,这些信号在输出最终位姿前就被标记为异常。
4. 工程落地中的大坑与排查实录
4.1 坐标系统一、外参标定和时间同步,任何一项错了都白搭
我见过很多算法本身没问题、但效果一塌糊涂的项目,几乎有一半问题出在数据链路上。第一是坐标系。GNSS输出的是经纬度椭球坐标,IMU输出的是机体坐标,激光雷达是传感器坐标,摄像头是像素坐标,车辆规划用的是车身坐标系。任何一个外参标定错了角度或平移量,融合出来的轨迹就会表现出“固定方向的系统性偏差”——这种现象单看某一帧数据根本发现不了,只有跑完一整圈做闭环误差分析才能看出来。
第二是时间同步。IMU通常是200Hz,激光雷达是10Hz,相机是30Hz,如果每个传感器各自带一个本地时钟,没有同步,那“同一时刻”的观测实际上差了少则几毫秒、多则几十毫秒。在车辆高速行驶时,几十毫秒意味着几十厘米的位置偏差,融合结果必然漂。成熟的方案是硬件上用PTP或GPS秒脉冲对齐时钟,软件上各传感器消息打上统一的系统时间戳,并在融合时做时间插值对齐。
第三是雷达点云的运动畸变。激光雷达扫描一帧点云需要时间,如果车辆在运动,同一帧里不同角度点的采集时刻并不同,直接拿整帧点云做匹配会产生“点云变形”。要么在驱动层利用IMU去掉畸变,要么在融合里对每帧点云单独标记时间戳。
4.2 回环检测失效与地图错位的典型场景
回环检测在自动驾驶场景里比在室内机器人场景里难得多。室内场景墙壁纹理丰富,绕一圈回来很容易用词袋模型命中回环;但在高速公路上,两边几乎都是相似的护栏和植被,视觉词袋检索出的候选帧大量是“看起来像但并不是同一个地方”,误检率会非常高。激光Scan Context在长直隧道中也会出现“只要是隧道就都长一样”的问题。
回环一旦误检,后端优化的图里就会加入一条错误的闭环边,地图直接被拉变形,且很难自动恢复。在实际项目中,回环候选必须过一遍严格的几何校验+PnP/NDT配准+残差检测,最好再用地磁、GNSS轨迹距离做粗筛,只保留“空间距离足够近”的候选,误检概率会下降一个量级。另外,回环检测的触发频率也要控住,不要每帧都检测,避免把计算浪费在无效搜索上。
4.3 参数调优心得:NDT分辨率、地图分辨率、预积分频率
做工程最怕的是“框架是开源的,效果却不是开源的”,很多效果差异来自参数细节。
NDT分辨率是激光定位里最关键的参数。分辨率设太小,每个栅格里点云太少,分布估计不稳定,匹配容易跳变;分辨率设太大,精度变差,定位误差可能从厘米级退化到分米级。通常的做法是在目标场景里扫一遍不同分辨率(例如1.0m、1.5m、2.0m)做对比,看匹配残差和轨迹平滑度,再选定最稳的一组。我实测下来,园区场景速腾16线雷达用1.5m到2.0m的分辨率比较稳,128线雷达用1.0m到1.5m。
地图分辨率同理。建图时点云地图的体素分辨率越高,细节越丰富,但存储量和检索量也越大,而且对点云噪声越敏感。更合理的做法是分层建图:全局用低分辨率做粗定位,局部用高分辨率做精匹配。
IMU预积分频率和采样时间也要对齐。IMU数据如果做预积分时不考虑零偏随时间变化,长时间运行后轨迹会有一个缓慢的旋转漂移。调参时记得开启在线估计零偏,而不是只用标定出来的固定值。
4.4 定位问题排查速查表
| 现象 | 可能原因 | 排查手段 |
|---|---|---|
| 轨迹整体偏向一侧 | 外参标定偏差或IMU安装角误差 | 记录直线行驶数据,对比GNSS与SLAM轨迹的横向偏差规律 |
| 静止时定位仍在漂 | IMU零偏未标定或滤波噪声参数过小 | 静止采集十分钟,估计角速度零偏和加速度零偏 |
| 地图出现重影 | 建图时回环边错误或点云源时间戳不一致 | 检查回环检测的几何校验流程,确认传感器时间同步 |
| 过隧道后定位跳变 | GNSS重新捕获时的模糊度初始化未收敛 | 增加GNSS稳定判断,要求连续多帧载波相位固定后再进入融合 |
| 雨天点云匹配差 | 雨雾产生噪声点、地面积水反光 | 增加点云去噪滤波,降低NDT中噪声敏感参数,结合视觉语义特征 |
| 视觉跟踪频繁丢失 | 逆光、暗光或运动模糊 | 检查自动曝光和快门参数,必要时用HDR模式和卷帘快门校正 |
5. 开源框架、数据集与入门路线
5.1 值得动手跑一遍的开源SLAM框架
| 框架 | 传感器配置 | 特点 | 适合场景 |
|---|---|---|---|
| LIO-SAM | 激光雷达+IMU+GPS | 紧耦合图优化,支持回环,代码清晰 | 自动驾驶实车、机器人园区 |
| FAST-LIO2 | 激光雷达+IMU | 直接法配准,计算高效,嵌入式友好 | 无人机、小型机器人、低成本车辆 |
| ORB-SLAM3 | 单目/双目/RGB-D+IMU | 视觉SLAM标杆,多地图系统 | 室内、视觉/惯性融合教学 |
| VINS-Fusion | 双目/单目+IMU+GPS | 视觉-惯性紧耦合,支持全局融合 | 视觉定位、无人机、低速车辆 |
| Cartographer | 激光+IMU | 2D/3D建图,回环检测成熟 | 室内服务机器人、园区配送车 |
如果你想做自动驾驶定位方向,我建议从LIO-SAM入门,因为它自上而下涵盖了一个完整激光SLAM系统的各个模块,代码不算太复杂,社区资料也多。有了基础之后再去啃FAST-LIO2,看它怎么把迭代滤波和直接法结合,对理解“紧耦合”会有质的提升。
5.2 自动驾驶SLAM常用数据集对比
| 数据集 | 传感器配置 | 适合方向 | 注意事项 |
|---|---|---|---|
| KITTI | 双目、64线激光、GNSS/IMU真值 | 视觉/激光SLAM评测 | 场景较老,城市道路,缺少雨雾等恶劣天气 |
| nuScenes | 激光、相机、毫米波雷达、IMU | 多传感器融合、自动驾驶感知定位 | 标注丰富,1000个场景,规模大 |
| Waymo Open Dataset | 5个激光+5个相机 | 高精度激光SLAM和感知 | 数据量大,需要申请审核 |
| Oxford RobotCar | 双目、激光、GNSS/IMU | 长期场景、季节变化影响 | 包含下雨、夜晚、冬季等多种天气 |
| M2DGR | 地面机器人多传感器 | 地库、园区激光/视觉融合 | 国内团队制作,包含地库等退化场景 |
用数据集做评测时有个容易踩的坑:数据集自带真值通常来自高精度组合导航,本身也有漂移,评价定位算法时最好不要只看绝对误差,还要看轨迹的平滑度和闭环误差。另外很多公开数据集没有做传感器时间戳同步,跑融合算法前需要先预处理对齐。
5.3 从入门到上手的学习路径
入门阶段先把《视觉SLAM十四讲》啃透,这本书把李群李代数、状态估计、图优化这些核心数学讲得很接地气,配合代码实践,是建立SLAM脑图的最好方式。学完后再把你的知识迁移到激光SLAM,看LIO-SAM的源码,重点理解IMU预积分、因子图构建和回环检测三个模块。
之后做一个“正经项目”:用自己手里的或租用的设备,在某一个园区或地库里采集一组数据,录制bag包,用LIO-SAM建图,再用NDT做实时定位,最后把GNSS融合进去,观察各个场景下定位误差的变化。这个流程比看十篇论文都管用,因为你在真实数据上会遇到建图重影、时间戳错乱、参数不收敛、地图退化等各种文档里不会写的问题,而这些才是工程面试里最常被问到的内容。
个人最后分享一个实实在在的经验:调试定位系统,一定要先保证“数据链路干净”,再谈算法。录包前先检查时间戳是否同步、IMU零偏是否标定、外参是否最新,能省掉后续一半的“灵异问题”。然后离线跑框架、画轨迹、看残差,确认没有系统性问题之后,再上真车实时试——千万不要一上来就在线反复试错,那样你只会得到一堆无法复现的玄学数据。定位是一个把脏数据变成干净状态估计的过程,数据不好,算法救不回来。