资讯动态

LOAM激光SLAM精读:原理、模块拆解与复现避坑指南

发布时间:2026/10/22 1:26:25 来源:尧图企业网站定制
如果只能从激光SLAM的经典论文里挑一篇精读我会毫不犹豫选LOAM这篇。它在2014年发表的时候没有用特别花哨的数学模型却把“实时”和“低漂移”这两个互相拉扯的目标漂亮地解开了一个高频里程计负责快速递推一个低频建图负责全局纠偏。即便放到现在市面上大多数激光雷达SLAM方案依然能从这个架构里找到影子。这篇博文就是我个人的论文阅读笔记把LOAM的原理、模块设计和复现时的常见坑拆开来讲适合刚接触激光SLAM的研究生以及准备在机器人上落地激光定位的工程师。1. 为什么LOAM是激光SLAM绕不开的必读论文1.1 论文要解决的核心矛盾要做激光雷达的实时定位与建图第一反应往往是“把所有点云配准到一张全局地图上”精度高但计算量巨大。而另一种极端做法是只做相邻两帧的匹配速度快但误差会随帧数累积漂移。LOAM这篇论文的核心贡献不是提出了某种新的点云配准算法而是重新回答了“这个问题的结构应该是什么”。它把整个任务拆成了两个并行模块。第一个模块叫里程计以较高的频率运行只做相邻扫描之间的匹配每帧只提取少量特征点参与计算保证实时输出位姿增量。第二个模块叫建图以较低的频率运行把当前帧和已经累积出来的局部地图做配准得到更精确的全局位姿并用这个结果反过来修正里程计的低频漂移。这个拆法的巧妙之处在于它并没有指望一个模块同时满足“快”和“准”而是让快模块保证不间断输出让准模块在后台慢慢纠偏。就像你开车时用手机导航里程表随时都在更新但只有经过路口修正点系统才知道之前到底偏了多少。论文用一套非常轻量的特征提取和匹配方法让两个模块都在CPU上实时跑通这在当时的计算条件下是很有代表性的工程判断。1.2 一种简单但影响深远的架构观里程计与建图的分工很多刚读论文的人会纠结于公式推导和参数细节但我建议先把架构吃透。LOAM实际上确立了一个后来被反复使用的范式高频估计负责“递推”低频优化负责“纠偏”。递推模块的精度不一定高但必须稳定、必须每时每刻都有输出纠偏模块的精度要高但可以慢甚至可以滞后几个周期再回填结果。这种思想在后来的不少雷达方案里都有体现。有的把建图频率从低频提到中频有的在里程计阶段引入多传感器融合但主干逻辑基本都保留了“先快速计算、后精细修正”的分工。理解了这一点再看后续各种系统的模块图你会觉得它们长得像同一个家族的产品。所以我把这篇论文定位为“定调之作”。它的数学门槛并不高真正难的是理解设计者为什么这样切分问题。把这个逻辑想通后面的特征提取、畸变补偿、优化求解都只是实现细节。2. 特征提取一个光滑度公式如何决定整个系统的上限2.1 点云如何组织扫描线、邻域与局部光滑度LOAM的输入是来自多线激光雷达的点云。每条扫描线在水平方向扫过一圈不同扫描线对应不同的垂直角度。一帧点云其实是由几十条这样的环形扫描线组成的。论文不做聚类不做地面分割而是直接利用扫描线的邻域关系去判断每个点的局部几何形态。对每一个点取它所在扫描线上前后各若干个点作为一个邻域集合。论文里通常取前后各5个点共10个点。然后计算这个点的光滑度也就是邻居点相对于它的偏离程度公式可以写成c (1/|S|) * || Σ_{j∈S, j≠i} (X_j − X_i) ||其中S是当前点所在的邻域点集X是点的三维坐标。这个值的含义很直观如果当前点落在一段平滑的墙面上邻居点和它的位置差方向各不相同向量求和后会相互抵消c值就小如果当前点正好在墙角或物体边缘邻居点大多落在它的同一侧求和后的向量长度会明显偏大c值就大。这个计算非常轻量但它抓住了激光点云的局部几何本质。c值大的点大概率是角点、边缘点c值小的点大概率落在平面或平滑曲面上。很多后来的系统会把“光滑度”这个指标换成更复杂的局部曲率或协方差特征但基本思路仍是同一个——用邻域几何来判断点的“角色”。2.2 角点与平面点的筛选策略拿到每个点的c值之后LOAM并不是直接挑c值最大的点作为角点、最小的作为平面点而是先做了一步空间分区。它把一帧扫描分成四个子区域每个子区域里再分别挑选角点和平面点。为什么要分区如果全帧只按c值排序取前几名特征点会全部聚集在几何结构最复杂的区域——比如一片灌木丛、一堆杂物旁边而空旷区域一个特征都没有。那样的话后续配准在空旷方向上就几乎没有任何约束系统很容易漂移。分区挑选相当于强行让特征在四个象限方向上尽量分散。角点按每区最多2个、平面点按每区最多4个来取这样一帧特征点数量就被控制在一个很小的规模内既保证了计算速度也保证了基本覆盖。这里还有一个很实用的细节特征点之间不能扎堆。如果一条扫描线上相邻好几个点都被选成角点它们的约束信息高度重复对位姿求解的贡献很小反而增加计算量。所以实际实现里通常会对候选特征点做去重或非极大值抑制保证选出来的点之间有足够的间隔。2.3 容易被忽略的边界点剔除论文里花了篇幅讲一类需要剔除的点位于遮挡边界处的点。什么叫遮挡边界你可以想象站在一堵墙前面墙前面还放着一个箱子。激光扫描到箱子边缘时一部分光线打在箱子上另一部分打在箱子后面的墙上。箱子的边缘点和墙上的邻近点虽然在同一帧里相邻但它们的深度差距会非常大。这种深度跳变区域对配准非常不友好。因为下一次扫描时只要雷达位置稍微动一点点原本可见的墙面点可能就被箱子完全挡住或者原本的边界点突然变成墙面正常点。特征点的对应关系会瞬间失效直接导致匹配出现大的残差。LOAM的做法是在提取特征之前检查当前点与相邻点的深度差如果深度差超过一定阈值就把这类点直接剔除。同理每条扫描线的起始和结束位置附近由于激光点云通常存在不规则性也属于低质量候选点同样要去掉。我读这段时的感受是这一条看似小小的预处理规则实际对系统鲁棒性的影响非常大。很多复现版本为了让调试简单省略了边界点剔除结果特征提取的质量在复杂场景中明显下降。论文的篇幅分配很有意思特意把这些“脏点”处理写进了算法流程说明作者在真实数据上吃过亏。3. 高频里程计帧间配准、运动补偿与LM求解的细节3.1 最早处理运动畸变的模块之一时间插值补偿激光雷达扫描一帧需要一定时间。在这段时间里雷达本身可能已经移动了一段距离所以一帧里的每个点其实对应着不同的时刻。如果一个点云的坐标都放在同一个扫描周期起始时刻的坐标系下就要做运动补偿否则后续配准会看到扭曲的点云。LOAM假设在一个扫描周期内平台的运动速度基本恒定。这样当前帧内任意一个点的时间戳都可以换算成在整个扫描周期里的时间比例。里程计模块先用上一帧的位姿估计和匀速运动假设推算出当前帧可能的运动速度然后对每个点按时间比例做旋转和平移的线性插值把点补偿到帧起始时刻。这个操作类似相机的卷帘快门校正。旋转插值看起来比位移插值复杂一些如果直接对旋转矩阵做线性插值矩阵会失去正交性所以必须对旋转的轴角表示做线性插值再重新指数化成旋转矩阵。社区里有些简化实现用四元数球面插值来处理效果也可以。需要注意的是一旦平台运动剧烈匀速假设就不好用了补偿会残留误差。所以在快速旋转的场景里要么提高里程计运行频率要么用IMU提供更准确的帧内姿态变化。3.2 对应点关联从点到线、点到面的约束构建补偿完畸变之后当前帧的特征点需要和上一帧的特征点找对应关系。这一步是scan-to-scan匹配的核心。对于当前帧的一个角点先在上一帧的角点集合里找到最近邻点j然后在j所在扫描线的邻近扫描线上找另一个距离最近的角点l。j和l在上一帧中被认为同属于一条空间直线当前角点到这条直线的距离就构成一个约束。这里强调“不同扫描线”是因为同一扫描线上的两个点对直线的约束区分度不够容易出现退化。对于当前帧的一个平面点先在上一帧的平面点集合里找最近邻点j再在同一扫描线附近找次近邻l再在相邻扫描线找另一个点m。j、l、m三点构成一个空间平面当前平面点到这个平面的距离就构成另一个约束。挑选三点时同样要刻意避免三点共线否则平面约束不成立。这里能明显看出特征提取的质量直接决定了配准的可靠性。上一帧的特征点如果不干净找出来的线或面本身就不准后面再怎么优化都是白费。3.3 最小二乘求解与位姿更新有了角点和平面点的对应关系整个问题就变成了最小化两类距离残差的非线性最小二乘问题。角点贡献点到线的残差平面点贡献点到面的残差两者加权叠加在一起用列文伯格-马夸尔特迭代求解。论文里对旋转部分用欧拉角参数化对平移部分直接用三维坐标差。优化过程中需要用到残差对位姿参数的雅可比矩阵这部分推导比较繁琐但很机械。实际实现时很多开源代码会选择通用优化库来自动求导省去手推雅可比的麻烦但理解残差形态仍然很重要。还有一个容易被忽略的实现细节为了保证平面约束的稳定性可以分两次迭代。第一轮只使用平面点约束估计一次位姿增量用来粗对齐第二轮再把角点和平面点一起用上做精确求解。粗对齐可以先把较大的平移误差压缩掉避免角点约束在大误差状态下给出误导。里程计模块的输出是当前帧相对于上一帧的相对运动它的频率可以到10赫兹左右完全可以作为实时位姿源。但它的问题在于帧间匹配的误差会一帧一帧积累时间一长就会偏离全局真值。所以它只是整个系统的一半另一半看建图。4. 低频建图scan-to-map如何把漂移按回全局坐标4.1 为什么建图必须低频运行建图模块做的事本质上和里程计一模一样也是通过特征点的点到线、点到面残差去做配准。区别在于里程计是和上一帧匹配而建图是和累积的历史地图匹配。和历史地图匹配意味着搜索范围更大、候选点更多、拟合出来的线和面更可靠所以精度更高但计算量也大幅上涨。如果建图也跑到10赫兹CPU会扛不住。而且从系统收益来看根本没有必要里程计已经用高频输出了中低精度的位姿建图只需要以更低的频率比如1赫兹做一次全局纠偏把累积的漂移按回正确轨道上。低频带来的延迟在绝大多数机器人场景里是可以接受的。有些人在复现时会尝试把建图频率调到5赫兹甚至更高结果发现地图规模和计算耗时都在涨而定位精度提升有限。这其实说明频率不是越高越好关键看纠偏是否有新的、可靠的全局信息可用来修正现有轨迹。4.2 地图的表示与更新策略建图模块维护的不是一片原始点云堆积而是把特征点分成了两类地图角点地图和平面点地图。每次配准完成后新一帧的角点特征和平面点特征会被分别加入到对应地图里并通过降采样控制地图规模。如果地图无限增长后面每一次配准都会越来越慢所以必须做体素化或距离截断。一种常见的工程做法是只保留当前位置周围一定范围的地图特征点超出范围的历史点会被丢弃。这样既保证了局部地图的精度又把计算量控制在恒定水平上。这个思想后来在很多系统里被进一步演化为局部地图加关键帧管理的方式。在配准时当前帧的角点会在角点地图里搜索若干个最近邻。如果这些最近邻点被判断为大致呈线性分布就用它们拟合出一个空间直线方向让当前角点到这条拟合线的距离作为残差。平面点则在平面地图里搜索更多最近邻通过主成分分析判断这些邻居是否近似分布在一个平面上然后计算点到拟合平面的距离。和里程计模块相比建图模块拟合线和面时使用的邻居点更多拟合精度更高同时搜索范围更大能抵抗更大的初始误差。这就是为什么它的配准结果可以反过来修正里程计。4.3 里程计与建图的协作闭环系统的整体协作流程是这样的里程计跑到某一帧时会输出一个高频位姿这个位姿被当作建图模块的初值。建图模块拿到初值后在局部地图中做精细化配准得到当前帧在世界坐标系下的更精确位姿。之后系统把精确位姿与里程计推算位姿之间的差异作为修正量反馈给里程计的下一次计算或者直接将精确位姿作为后续里程计递推的新起点。这种双向反馈形成的闭环是LOAM的核心魅力所在。里程计如果没有建图纠偏会很快漂移建图如果没有里程计给初值就不得不在全图空间里做全局搜索速度和鲁棒性都会下降。两者互补才让系统在实时性和精度之间取得了平衡。论文里建图模块最终输出的是一个特征点地图而不是完整的环境表面模型。但对大多数定位和导航需求来说特征地图已经足够。如果你需要的是可被占用栅格地图直接使用的数据还需要在地图生成阶段做进一步处理这是LOAM原本没有涉及的工程问题。5. 复现LOAM时最容易踩的坑从时间同步到退化场景5.1 时间戳与外参点云“重影”的第一嫌疑复现LOAM时最容易遇到的现象是静态场景下点云出现重影或双重轮廓。这个问题的大部分原因都不在算法本身而在输入数据时间戳不干净或者外参不准。雷达给的每个点通常都有对应的精确时间戳但如果数据是在采集过程中被转发或缓冲过时间关系就可能错位。LOAM的运动补偿模块对时间关系非常敏感时间一错补偿就等于白做。我自己调试时用过一种很笨但有效的办法让雷达在静止环境中采集一圈点云然后检查同一帧内同一面墙上的点是否平整。如果墙面在补偿后还是扭曲的基本可以确定是时间同步出了问题。外参的问题通常出现在把雷达安装在移动平台上之后。安装位置的三维平移和三个旋转角哪怕偏了一点都会被运动补偿放大。解决方法是做一次外参标定不要让雷达与平台的相对位姿靠“量尺子”去猜。这一步做得越准后面的位姿精度越省心。5.2 特征数量与分布调参不止是改一个上限很多复现版本把每区最多两个角点、四个平面点的参数直接搬过来不管自己的场景和雷达线数是否合适。实际中16线雷达和64线雷达的特征提取表现差异很大。16线雷达的点云稀疏直线和平面拟合的稳定性天然弱一些需要适当提高邻域搜索范围或允许更多候选点64线雷达点云密但若特征不加以稀疏化计算时间又会迅速上升。我建议调试时把特征点的空间分布可视化出来而不是只看数量。理想状况下四周不同方向上都有一定数量的角点和平面点而不是挤在一个方向。如果发现某一片区域的特征数常年为零就要考虑是不是分区策略或距离阈值设置把远处的点都滤掉了。远处点虽然稀疏但在开阔环境里往往是唯一可用的约束来源一味滤掉会削弱系统的方向观测能力。5.3 退化场景让系统承认“我不知道”很长一段场景的走廊、四周完全空旷的停车场、又长又直且没有特征的隧道——这类场景里不是算法崩了而是几何结构本身缺少约束。沿走廊方向看前后移动时点云的形状几乎没有变化里程计和建图都无法提供有效的位移约束系统就只能在无根据的假设下“猜”。论文对退化问题没有做专门处理因为当年的场景评测主要面向道路环境地面、路沿和建筑立面还能提供不少约束。但到了真实部署尤其是园区和室内环境退化几乎是必然面对的。一个实用的做法是在优化完成后检查当前约束矩阵的最小奇异值。如果某个方向的约束极弱就把对应方向上的位姿修正量压小宁可让结果保守一点也不要让一个大错误跳出来。5.4 代码阅读顺序按模块拆不要从头啃第一次读LOAM源码时如果从第一行顺序读到最后大概率会很快迷失在一堆坐标变换和回调函数里。我自己的经验是先跑通一个现成开源版本用回放数据把激光点云、提取出的角点平面点、里程计轨迹、全局地图依次可视化建立直观印象。然后把代码按三个模块拆开特征提取、里程计较准、建图匹配。先只读特征提取部分看它输出了什么换几组参数观察变化再读里程计部分重点看畸变补偿和LM优化最后读建图部分看局部地图如何更新和配准。每读一个模块就回到论文对应章节对着看。论文里的符号和代码变量通常能一一对应这种对照阅读比单纯看代码效率高得多。代码阅读能力允许的话可以对比一下原版实现和社区用优化库重写的版本。两者高层逻辑一致但后者的数值求解部分更易读适合用来理解残差和雅可比的结构原版实现则能看到作者在内存管理、数据组织上的原始设计。两相对照很多疑惑会迎刃而解。6. 精度评估与选型认知论文数字之外的思考6.1 实验指标怎么读平移误差和旋转误差的含义论文在公开自动驾驶数据集上给出了系统的误差统计主要看两类指标平移漂移和旋转漂移。平移漂移通常是每行驶一段距离后估计轨迹与真实轨迹之间的偏差旋转漂移则是姿态角随时间累积的偏差。读这些指标时要注意一个前提误差是和场景几何强相关的。同样一套雷达、同样一套参数在结构丰富的城区和一片空地跑出来的结果可能差一个数量级。所以论文里的数字只能作为参考标杆不能当作你换到自己的场景也能复现的数字。更合理的做法是把自己拿到的数据也用同样的指标跑一遍对比的是“和论文结果处于同一量级”而不是“逐位相等”。另一个需要注意的问题是误差来源有很多层。有雷达测距本身的噪声有特征提取选点不准引入的误差有运动补偿残余畸变也有优化陷入局部极小的可能。如果最终误差偏大要逐层排查而不能一上来就怀疑配准算法本身。6.2 影响精度的因素按权重排个序结合我的实际体验影响这类激光SLAM系统最终精度的因素按重要性大致可以这样排影响因素影响方式应对思路场景几何结构决定约束是否充足特征是否丰富场景检测、退化感知与处理运动强度决定帧间畸变和初值质量提高频率、引入IMU辅助初值点云质量与线数决定线面拟合稳定性选择合适雷达调邻域参数时间同步与外参决定输入数据是否自洽做好标定校验时间戳特征提取参数决定约束的数量与空间分布可视化调试按场景调分区把场景几何放在第一位是因为这是硬件之外的硬约束。特征再多、参数调得再好在退化场景里也很难靠纯几何方法撒开手跑。所以选型时不要只看算法的纸面精度还要看你的实际工作环境是什么样。6.3 LOAM的思想如何延续到后来的激光SLAM系统读完LOAM再去看后面几年的激光SLAM进展会越来越清晰地看到一条主线大部分系统的改进点并不在“能否实时”这个问题上因为LOAM已经给出了答案。后来者做的事基本都是把某个模块强化了。有的系统专门做地面分割和物体聚类来提高特征提取的语义纯度有的把建图和回环检测接在一起试图消除长时间运行后的全局漂移有的把雷达和惯性测量信息紧耦合让运动补偿和初值估计在剧烈运动下依然稳定有的把整个问题放进因子图框架把多帧状态和传感器观测统一优化。但无论怎么改“高频里程计加低频建图”的分层逻辑依然是很多方案默认的系统底座。所以在实际选型时我对团队的建议是如果需求是一个基础可用的实时激光定位建图系统而且计算资源有限LOAM的框架到目前为止仍然足够作为起点。它不依赖GPU不依赖昂贵的传感器融合方案代码工程化难度也可控。先在这个框架里跑通再加上场景退化处理或其他传感器数据会比一开始就奔着复杂方案去要好得多。我个人的体会是LOAM最值得学的不是哪个公式、哪个参数而是那种“把大问题拆成两个可独立运行的小问题”的系统观。论文里所有的数学细节几乎都是为这个系统观服务的。如果你准备深入激光SLAM我建议把它当成第一篇精读论文读的时候把流程图留在手边每看到一个变量就回到代码里找对应实现等你把特征提取、里程计、建图这三个模块在代码里完整走通一遍再回头看论文你会理解当年作者为什么做这些选择。

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价 →
↑