☰
FAST-LIO核心解析:紧耦合激光惯性SLAM的滤波与增量数据结构
2026/10/26 12:29:37 网站建设 项目流程

做激光 SLAM 的同行应该都体会过那种感觉:场景一复杂,点云配准就开始飘,里程计漂移慢慢积累,地图越建越糊。我早期调过不少基于特征匹配的方案,角点、平面点、强度特征层层筛选,最后效果还是看场景脸色。直到把目光转向紧耦合的激光惯性方案,才真正找回那种"稳定"的感觉。FAST-LIO 系列就是这条路上绕不开的开源标杆,也是不少进入这个领域的人第一个认认真真啃下来的工业级算法。

这系列方法解决的本质问题其实很朴素:单靠激光雷达做里程计,在快速旋转、缺乏几何特征的环境里容易翻车,单靠 IMU 积分又扛不住长时间漂移。FAST-LIO 把两者的优势拧在一起,用紧耦合的方式实时估计状态,既保留激光的精度,又吸收 IMU 的高频运动信息。更关键的是,从第一代到第二代,配准环节从特征点匹配改成了基于原始点云的 ikd-Tree 增量管理,整体鲁棒性和效率都有了质的提升。

如果你刚入门激光惯性 SLAM,或者已经调过别的方案想换条路,这篇文章值得花十分钟把它背后的设计逻辑理顺。我会从融合架构、滤波原理、数据结构、工程实现四个角度拆开讲,最后附上我自己跑实验时积累的调参经验和排查思路。不保证看完你就能手写一套,但至少能让后续读源码、改参数都轻松很多。

1. 为什么紧耦合是这条路的胜负手

1.1 激光雷达里程计的三座大山

先说激光雷达单独做里程计的情况。最常见的是帧间配准:拿当前帧点云和上一帧点云做 ICP 或 NDT,算相对位姿变换再累加下去。理论上很自然,实际跑起来却有三个老大难问题。

第一是运动畸变。机械式激光雷达是逐点扫描的,一帧点云里不同点对应的时间戳并不相同。如果设备在扫描过程中出现明显旋转或平移,直接把这帧当作刚性整体去配准,结果就自带畸变。解决办法是"去畸变",但去畸变本身需要一个运动先验——通常来自 IMU 积分或匀速模型。先验不准,畸变就去除不干净,配准精度跟着掉。

第二是退化场景。想象一条狭长走廊或者一面没有特征的空白墙,点云在某个方向上几乎没有几何约束。此时帧间配准在沿走廊方向上的位移估计会变得非常敏感,俗称退化。没有外部约束,误差就在这里悄悄积累,等机器人走出走廊,轨迹已经偏出去不少。

第三是高频运动。手持设备快速甩一下,或者机器人急转弯,帧间位移可能很大,配准容易陷入局部极小值。扫描周期如果是 100ms,这 100ms 内的运动全靠配准自己去猜,猜错了就发散。

这些问题单独拿出来都能对付,叠加起来就非常棘手。所以后来大家普遍引入 IMU。IMU 以 200Hz 甚至更高频率输出加速度和角速度,短时间内积分得到的姿态增量非常平滑,正好填补激光帧之间的空白,也给去畸变和配准提供高质量的初始值。

1.2 松耦合和紧耦合的分水岭

怎么把激光和 IMU 结合起来,行业里有两种路线。松耦合的做法是各算各的:IMU 自己跑一段积分,激光自己跑一段点云配准,最后用某种方式把两个独立的结果融合起来,比如做一次优化或者滤波。这种路线实现简单,模块可以各自替换,但缺点也很明显——两边都没有利用对方的原始观测。IMU 没有用点云校正累积误差,激光也没有利用 IMU 的预测去约束配准搜索范围。误差是"求和"的关系,而不是"互相约束"的关系。

紧耦合则完全相反。IMU 的测量直接参与状态预测,激光雷达的原始点云反过来约束状态更新,整个过程在统一的概率框架下完成。FAST-LIO 走的是这条路:IMU 预积分作为先验,激光点到局部地图表面的距离作为观测约束,在一个滤波迭代里同时修正位置、姿态、速度、陀螺零偏和加计零偏。好处是任何一个信息源出问题,另一个都能兜底,系统整体强度比松耦合高很多。

但紧耦合的工程代价也摆在明面上:状态维度上来了,计算耦合度高了,实时性不好保证。FAST-LIO 的巧妙之处在于用迭代误差状态卡尔曼滤波框架,把高维状态估计拆成"高频低维的状态传播 + 低频高维的观测更新",既维持了紧耦合精度,又压低了计算开销,能在一台普通工控机上实时跑。这个设计思路值得单独拆开讲。

1.3 它在哪些场景真正闪光

讲完原理差异,聊一点实战使用感受。FAST-LIO 系列最适合的场景是那些"激光觉得晕、IMU 觉得漂"的地方:AGV 在仓库里高速穿梭时的快速转向、无人机在植被稀疏的野外低空飞行、手持设备在电梯口来回走动。这些场景的共同点是运动剧烈或环境几何约束不足,纯激光和纯惯性单独都扛不住,紧耦合就体现出优势。

举个例子,我做过一个模拟项目X,设备要在地下停车场快速绕桩,纯激光方案一到急转弯就飘,点云配准直接跳到错误位姿。切到 FAST-LIO 之后,IMU 先把转弯期间的姿态变化顶住了,激光再用停稳后的观测把位置拉回来,整个绕桩过程轨迹平滑很多。这种体验上的差距,不是在参数表里能直接看出来的,只有跑过对比才知道。

相反,如果你的机器人永远在平坦开阔、特征丰富的场景里慢速直线行驶,FAST-LIO 的优势体现得并不明显,甚至因为滤波框架引入的调参项,反而觉得麻烦。它在复杂运动状态下的鲁棒性,才是它真正的价值所在。

2. 核心滤波框架:迭代误差状态卡尔曼滤波

2.1 为什么要用误差状态而不是直接滤波全状态

卡尔曼滤波大家都很熟,但直接拿旋转矩阵当滤波状态会碰到数学上的大麻烦:旋转矩阵属于特殊正交群,加法运算不封闭。两个旋转矩阵加起来大概率不是一个合法旋转,四元数也有归一化的约束。为了绕过这个问题,滤波理论里引入了一个经典技巧——不直接给全状态建模,而是给状态的"误差"建模。

系统状态 x 可以拆成名义状态 x_nom 和误差状态 δx 两部分。名义状态由 IMU 积分推进,误差状态才走卡尔曼滤波的预测和更新流程。因为误差状态是小量,旋转误差可以用三维向量近似,加法、数乘这些操作都封闭,数学处理变得非常舒服。等卡尔曼更新算完,再把误差补偿回名义状态,就得到最终估计。

可以用一个生活里的类比来理解。你开车导航,导航屏幕上那条绿线是名义状态,来自地图数据和惯导推算;而真实车辆位置和绿线之间的偏差,就是误差状态。你不需要每次重画整条路,只需要修正偏差量,偏差修正好了,绿线自然就贴近真实位置。FAST-LIO 的滤波过程就是不断修正偏差,最后叠加回名义轨迹。

FAST-LIO 把整个思路用得很极致。状态向量包含位置 3 维、速度 3 维、姿态 3 维(误差部分)、陀螺零偏 3 维、加计零偏 3 维,总共 15 维。误差状态同样 15 维。名义状态用 IMU 的高频数据不断推进,误差状态用激光点云的观测来修正。两者各司其职,组成了整套系统的骨架。

2.2 状态传播:IMU 高频积分

在激光帧间隔内,IMU 数据源源不断进来,系统对每个 IMU 测量执行一次状态传播。位置更新是 v·dt 积分,速度更新是 R·a·dt 积分,姿态更新是角速度叉乘后的积分。零偏部分按随机游走模型处理,误差状态的协方差也会同步传播。

这段伪代码基本反映了传播的核心逻辑:

// 输入:当前状态、imu测量、dt // 输出:传播后的状态、协方差 p += v * dt; v += (R * acc - g) * dt; R = R * exp_so3(gyro * dt); bg += noise_bg; ba += noise_ba; P = F * P * F^T + Q;

这里的 exp_so3 是把角速度矢量转成旋转矩阵的指数映射,在刚体运动学里是最基础的操作。F 是误差状态的雅可比矩阵,Q 是 IMU 噪声的协方差。传播一步的计算量很小,所以能扛住 200Hz 的输入频率,而激光观测更新只有 10Hz,两者在计算量上天然拉开了层次。

这个设计背后的逻辑很直接:IMU 更新不需要复杂的观测模型,积分即可,所以它可以跑得很高频;激光观测每次要查询数据结构、拟合平面、算残差,计算重,所以只在点云帧到达时触发。两者以完全不同的频率运行,再由滤波框架统一整合,这就是"刚柔分工"的工程美感。

2.3 迭代更新:点云残差怎么进入卡尔曼框架

激光帧到达后,先把该帧内所有 IMU 数据消费完,得到先验状态和协方差。然后取出本帧点云,根据外参把每个点变换到世界坐标系。对每个点,用 ikd-Tree 在局部地图里找最近邻,拟合出一个局部平面,计算点到平面的距离作为残差。

这里需要稍微展开说说残差模型。雷达测量的本质是"激光点到环境中真实表面的距离",所以最自然的约束就是:变换后的点应该落在局部地图的表面附近。残差定义为点到最近邻平面的投影距离。平面由最近邻的若干点拟合得到,通常取三个或者五个点做最小二乘。这个模型极其朴素,但在大量点的支撑下,能形成强约束。

卡尔曼更新时,最重要的是雅可比矩阵的计算。残差对位姿的导数,决定了误差状态里每个分量该如何修正。由于残差关于姿态是非线性的,一次性线性化精度不够,所以 IESKF 要迭代:每轮用当前修正后的状态重新算残差和雅可比,再更新,直到残差变化小于阈值或达到最大迭代次数。

从数学形式上看,这一步和 Gauss-Newton 优化很像,只不过多了一个先验协方差对状态的约束。它输出的不只是一个位姿估计,还有一套完整的协方差信息,这对评估估计质量和后续对接全局优化模块都非常有用。

2.4 计算量的取舍

精度到位了,得考虑实时性。一次迭代里要对每个点查询 ikd-Tree、拟合平面、算雅可比,几万个点的计算量不能小看。FAST-LIO 的工程实现里做了几处关键取舍。一是降采样:在进入残差计算前,对点云做体素降采样,把参与计算的点数压到几千到一两万。二是过滤:距离过远的点直接跳过,不参与残差;距离太近且残差过大的点认为被动态障碍物占据,跳过。

这些取舍在论文里可能只是一段话,在实际系统里却是精度的保障。把计算资源花在最有代表性的点上,远比硬吃全部点云更加有效。我见过有人为了"追求精度"把所有点都塞进残差计算,结果 CPU 跑满,帧率掉到 3Hz,精度反而因为状态更新不及时而变差。合理降采样之后,帧率回到 10Hz,精度还提高了。这个反直觉的现象,本质上是因为滤波器的更新频率比单帧点数更重要。

3. ikd-Tree:把原始点云玩出花的数据结构

3.1 为什么第一代搞特征,第二代不搞了

第一代 FAST-LIO 需要先从点云里提取特征点,再拿特征点去和局部地图匹配。特征提取能大幅减少数据量,但缺点也明显:它只保留"尖角"和"棱边"这类信息集中的点,环境一旦缺乏明显几何变化,特征就少得可怜。而且在快速运动、点云畸变较大的情况下,特征提取的质量波动很大,等于给整个系统埋了颗雷。

第二代的思路是把"提升点的质量"改成"堆足够多的点"。不管点在几何上是否"重要",只要它能提供一个有效的点到面距离约束,就纳入计算。大片平坦地面的点约束法向方向的位移,墙角和边缘处的点约束切线方向,所有点的作用自然分工。环境的几何特征不是靠预处理显式提取的,而是靠海量点云的统计效果涌现出来的。

这个转变有点像摄影里"拍糊了靠堆帧降噪"的思路。单张照片噪点大,就多拍几张取平均,把随机噪声抹平。原始点云里单个点可能有噪声,但成千上万个点共同约束同一个平面时,统计特性就会把噪声抑制下去。特征提取相当于信任一小部分精选点,而直配准相当于信任整个群体的统计规律。

3.2 普通 kd-Tree 扛不住动态地图

代价很快就来了:点云的量级完全不一样了。每帧几万到几十万个点,局部地图里存了几百万个点,每个点都要在局部地图里找最近邻。这个时候空间索引结构就是性能的生死线。

普通 kd-Tree 建树快、查询也快,但有一个致命弱点:不支持动态更新。一旦地图里有新点进来或者旧点被剔除,树就局部失效。最省事的办法是定期重建整棵树,而重建一棵几百万节点的 kd-Tree 动辄几百毫秒,在实时系统里根本没法接受。我见过不少人在工程里为了躲开这个坑,把地图窗口设得非常小,结果又引入了历史约束不足的问题。

你可以把 kd-Tree 想象成一本纸质图书馆目录卡片。查找一本书很快,但每天有新书入库、旧书下架,目录就得从头重新编一遍。图书馆规模小还能忍,几百万册的书,编一次就得半天。ikd-Tree 做的改进,相当于给目录系统加了可插拔的活页和索引标记,新书来了直接插进对应分类,旧书先标个"已移除",攒一批再统一整理。

3.3 ikd-Tree 的增量更新策略

ikd-Tree 把这个问题解决得很优雅。它的全称是 incremental kd-Tree,增量式 kd 树。和普通 kd-Tree 最大的区别是支持局部更新:插入新点只影响树中的局部路径,删除旧点也是局部操作,不需要整棵树推倒重建。

实现上,树的每个节点保存了额外的统计信息,例如以该节点为根的子树包含的点数和包围盒范围。插入时沿着树路径向下走,找到合适的位置挂上去;删除时不物理移除节点,而是先打上"待删除"标记,等这个节点管理的无效点比例超过阈值后,再触发一次真正的空间分割和清理。这个"延迟删除"的策略非常妙,把高频小量更新转化成了低频批量整理,均摊开销很低。

ikd-Tree 还实现了增量下采样。局部地图添加新点前,先用体素网格做一次滤波,保证点密度不会无限膨胀。滤波结果增量地反映到树结构里,不需要重建整棵树,只需要遍历受影响的分支。靠着这套机制,局部地图的体量能维持在一个可控范围,查询效率不会随着运行时间急剧劣化。

3.4 和其他数据结构的对比

聊到数据结构,免不了要和其他方案做对比。下面这个表是我根据实际使用体会整理的。

结构查询速度动态更新适用场景
普通 kd-Tree快不支持静态地图配准
体素栅格地图较快支持占位栅格地图
ikd-Tree快支持增量SLAM 局部地图
八叉树中支持三维占位地图

ikd-Tree 不是万能的。它的优势集中在"点的集合动态变化但总量可控"的场景,也就是 SLAM 的局部地图管理。如果你只需要一个静态全局地图,普通 kd-Tree 反而更简单,维护成本更低。选择数据结构永远要跟着使用场景走,而不是追逐最花哨的选项。

4. 系统工作流程与实现细节盘点

4.1 一条完整消息流的主干

FAST-LIO 系统的主循环可以按五步来理解。

  1. 等待 IMU 数据,同步判断最新一帧激光点云的时间戳。
  2. 用激光帧时间戳内覆盖的 IMU 数据做状态传播。
  3. 对该帧点云做去畸变和时间对齐。
  4. 用当前状态作为初值,进行 IESKF 迭代更新。
  5. 配准成功后,将新点插入 ikd-Tree 并淘汰无效旧点。

这个顺序有很强的前后依赖。先传播后配准,意味着配准是在一个高质量的先验附近做局部搜索,而非从零开始匹配。这跟人摸黑走路的逻辑一样:先凭感觉估算自己走了多远,再伸手去确认墙壁位置。先有这个直觉,触摸才高效;没有直觉,每个点都要盲目试探。

从代码层面看,消息同步是一个容易被低估的环节。IMU 和激光数据通过不同话题到达,时间戳对齐如果不仔细,会出现激光帧里混入"未来时刻"的 IMU 数据。这类 bug 通常不会立即报错,而是表现为偶发性的状态跳动,非常难查。我的经验是在回调入口加一层时间戳校验,确保所有进入滤波器的数据时间戳单调递增。

4.2 去畸变的工程细节

机械式激光雷达的每个点时间不同,去畸变需要把每个点转换到同一时刻。FAST-LIO 的做法是把激光帧内的 IMU 测量分成两段,用断点插值的方法,为每个点的采集时刻生成对应位姿。这样即便扫描过程中设备旋转很快,参与残差的点仍认为来自同一刚性时刻。

这里有个容易踩坑的地方:不同雷达的时间戳定义五花八门。有的驱动把时间戳设成扫描开始时间,有的是点的实际采集时间,还有的是帧结束时间。如果对时间戳含义理解错了,快速运动时点云会整体错位,表现就是"点云拖尾"或者"双重轮廓"。排查路由时我建议先确认时间戳单位,再检查雷达坐标系和 IMU 坐标系的外参,一组一组校准,不要上来就调滤波参数。

另外值得一提的是,去畸变的质量直接取决于 IMU 激励是否充分。如果系统一直匀速直线运动,IMU 积分很难暴露陀螺零偏的问题;一旦出现急转或急停,零偏误差就会被放大,去畸变结果出现肉眼可见的偏差。所以在标定 IMU 噪声参数时,一定要采集包含充分角速度激励的数据,这是保证去畸变质量的前提。

4.3 退化检测与可信度评估

IESKF 的信息矩阵里其实隐含了每个方向的可观测性。如果某个方向上缺乏有效点云约束,对应方向的协方差就不会缩小,状态估计的不确定性就会维持在一个较高水平。FAST-LIO 系列虽然没有把退化检测做成显式的接口,但协方差信息天然存在于框架内部,下游模块可以直接读取来做健康监测。

我在实际项目里会把协方差的最大特征值作为"健康分数"的一部分。当它超过某个阈值时,就降低该时刻位姿在后续任务中的权重。这个技巧不花什么计算量,却能让整个系统对异常情况有预警能力,算是对算法本身非常好的补充使用方式。

具体操作上,可以从滤波器里抽取向后验协方差矩阵,对平移和旋转分块分别做特征分解。平移方向的退化表现为对应特征值偏大,旋转方向的退化同理。这个维度上的问题,下游任务往往并不关心,但作为开发调试的辅助指标非常有用,尤其是对比不同参数组合时,"哪个方向更不自信"能帮你快速定位环境中的薄弱约束所在。

4.4 局部地图滑动窗口管理

局部地图不是无限累积的。FAST-LIO 会以当前估计位置为中心,维护一个立方体或球体范围的活跃点集。超出范围的点会从 ikd-Tree 中删除,保持搜索空间的高效性。新点来自配准后的雷达视场,先经过体素下采样,再插入树中。

这种滑动窗口和增量树组合的实质,是把"全局一致的建图"降级为"局部一致的状态估计"。FAST-LIO 本体输出的核心是高频里程计状态,不是全局地图。如果项目需要全局建图,通常要再叠加一个位姿图优化线程,利用关键帧和闭环检测生成全局一致的结果。很多刚入手的人容易忽略这一点,把 FAST-LIO 当成"能直接输出全局地图的完整建图系统",结果对接不上需求,浪费时间。

5. 实测调参经验与常见坑

5.1 开跑前一定要检查的四件事

我踩过的坑里,有一大半都发生在真正调参之前。

第一件事,确认外参文件。雷达坐标系到 IMU 系的平移和旋转,哪怕偏了几厘米、一度,状态估计都会有系统性偏差。如果初始外参不够准,花再多时间调滤波参数都是白费。第二件事,确认 IMU 噪声参数。随机游走和噪声密度会影响协方差传播的正确性,大多数数据集提供方都会在配置里写清楚,自采数据推荐做一次静态标定。第三件事,确认点云时间戳含义。这一点前面提过,不再展开。第四件事,确认雷达帧率与 IMU 频率的比值。常见组合是 10Hz 雷达配 200Hz IMU,这个比例下滤波更新才有足够的观测密度。

这些检查做完,再进入调参环节,问题会少很多。我做项目时见过太多人跳过这一步,结果花了一整天排查"为什么发散",最后发现只是外参的一个符号写反了。

5.2 参数速查对照表

下面是按用途整理的参数速查表,适合作为调参时候的一个参考框架。

参数类别参数名作用建议起始值
降采样体素尺寸控制点密度0.2~0.5m
去畸变时间偏移对齐传感器时间戳0 逐步试探
地图窗口局部地图范围控制滑动窗口大小略大于雷达测距
配准最大迭代次数控制 IESKF 迭代轮数3~5 次
配准残差收敛阈值判断是否停止迭代1e-3 量级
状态估计噪声密度描述 IMU 噪声参考标定结果

起始值给的是常见范围,不是死值。体素尺寸优先看环境细节密度,室外空旷环境可以放大到 0.5 米,室内走道和楼道则可以收紧到 0.2 米。最大迭代次数放太小会损失精度,放太大计算开销增长,3 到 5 次是实践中比较均衡的区间。

5.3 常见问题排查思路

跑 FAST-LIO 遇到问题,按下面的顺序排查往往最快。

现象可能原因排查方向
启动后位姿乱飞IMU 零偏未正确估计或外参标定不准检查外参,确认 IMU 噪声参数
快速运动时点云拖尾去畸变时间戳未对齐核对雷达时间戳定义
长时间运行后漂移明显地图窗口未正确淘汰旧点检查滑动窗口范围参数
配准发散初始位姿偏差过大或降采样过粗提高初始化稳定性,降低体素尺寸
CPU 占用过高点云密度过大增大体素滤波尺寸,限制配准点数

表格里每个现象背后我都碰到过具体案例。比如"配准发散",有一次是在一个极度空旷地面上的直升机起降场,点云全集中在平面上,切线方向的约束几乎为零,把体素尺寸调到 0.4 米并增加边缘点权重后,系统才稳定下来。问题诊断往往比调参本身更花心思,但一旦形成自己的排查清单,效率会快很多。

5.4 我的一些心得

最后说点真实感受。第一,不要一上来就怀疑算法本身。FAST-LIO 系列在开源 SLAM 里属于第一梯队,大部分发散问题都出在输入数据的质量上,尤其是 IMU 噪声标定和外参标定。建议上线前做一次静态数据采集,把陀螺和加计的噪声参数标准确,这个成本很低,收益却非常大。

第二,可以在不严重影响精度的前提下适当增大降采样比例。把参与残差计算的点数限制在几万以内,对精度影响往往很小,但对 CPU 的友好度提升明显。移动机器人平台上 CPU 资源普遍紧张,这个取舍非常值得做。

第三,FAST-LIO 是很好的上层建筑地基。可以在此基础上叠加闭环检测和全局位姿图优化:状态输出质量高,闭环模块的负担就小;闭环修正后的全局轨迹,也可以反过来校正局部历史点云。整套组合方案在工程项目里被验证过很多次,是我认为最值得投入时间的扩展方向。

这套系统我前前后后跑了快一年,最大的体会是:好的算法不是功能的堆砌,而是结构和数学的有机结合。紧耦合的滤波框架负责不掉精度,ikd-Tree 负责不掉速度,两者配合,才让原始点云直配准这条路线真正落地。希望这篇梳理能帮你更快抓住 FAST-LIO 的核心脉络,少走弯路。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询