FAST-LIO2激光SLAM:低算力高精度建图原理与落地实践
2026/9/7 1:47:07 网站建设 项目流程

做机器人的朋友多少都有过这种体会:算法跑通了,一上真机就卡成PPT,尤其激光SLAM这种吃算力的活。FAST-LIO2 这个名字近两年在定位建图圈子里出现频率很高,核心卖点就是“低算力跑出高精度的定位和建图”。我自己在Jetson Orin NX、甚至树莓派配合廉价激光雷达上都试过这个方案,实测下来确实稳,而且精度不输那些动辄需要GPU加速的方案。这次就用一篇拆解文章,把FAST-LIO2为什么能低算力高精度、怎么上手、有哪些坑,一次性讲清楚。

这篇内容适合谁?如果你在玩ROS机器人、做无人车/无人机导航、或者想把手头算力不高的设备变成一台能实时建图的移动机器人,FAST-LIO2基本是绕不开的一个参考方案。文章没有晦涩的数学推导,尽量用工程视角来讲,读完你至少知道它怎么工作的、怎么编译跑起来、遇到问题怎么排查,以及怎么往自己的项目里移植。

1. FAST-LIO2定位建图技术核心思路拆解

1.1 为什么“低算力高精度”这件事值得单独拿出来说

传统激光SLAM方案比如LOAM系列,流程是先提取特征点(角点、平面点),再把特征点和地图做配准。特征提取本身有计算量,而且特征质量直接决定精度,遇到走廊、空旷场地这类特征匮乏的环境,特征提不出来,定位基本就废了。FAST-LIO2的思路不同,它直接拿原始点云和局部地图做配准,省掉特征提取这一步,既降低了算力消耗,又避免了特征缺失导致的退化问题。

更关键的是,它把配准过程嵌入到迭代卡尔曼滤波框架里,状态预测由IMU完成,激光雷达只负责修正累积误差。这种结构让激光雷达不必以很高频率运行也能稳住精度,主流激光雷达10Hz输出完全够用,IMU频率哪怕只有200Hz也能跑得不错。实测在Jetson Nano这类设备上,CPU占用大概在30%到50%,对一块不到10W的开发板来说,这个表现已经很能打了。

1.2 核心技术一:直接点云配准,不提取特征

FAST-LIO2的全称里有个“direct”,意思就是直接配准。它把每一帧激光点云和全局地图的局部区域做最近邻匹配,优化位姿使得点云到地图的距离最小。这里用的地图不是体素栅格或者八叉树那种栅格化地图,而是维护了一棵增量式k-d tree,点云以原始分辨率存入,这样配准精度不会因为地图离散化而损失。

这里有个容易误会的地方:既然不提取特征,那计算量不是更大吗?实际上FAST-LIO2对每帧点云先做了体素降采样,比如设置为0.5m的体素格子,每个格子只保留一个代表性点。这样一帧几万点的点云降到了两三千点,参与配准的只有这些点,计算量自然可控。同时增量式k-d tree让地图点的插入和最近邻查询复杂度降到了对数级别,配合上“只查询当前帧附近的局部地图”的策略,效率进一步提升。

这种“降采样+局部地图+增量树”的组合,既保证了配准精度不因地图离散化而下降,又把单帧配准的计算量压到了毫秒级,是低算力高精度最核心的底气。

1.3 核心技术二:迭代误差状态卡尔曼滤波(iEKF)

FAST-LIO2的状态估计核心是迭代误差状态卡尔曼滤波,可以把它理解为“IMU负责猜,激光负责改”。每一帧激光到来之前,IMU积分预测出机器人位姿和速度;激光点云进来之后,把点云投影到预测位姿下,和地图做配准,算出残差;再用残差修正预测状态。这个过程迭代多次,直到残差收敛。

误差状态的好处是,IMU的偏置、噪声、甚至外参误差都被建模成误差状态的一部分,可以在线估计和修正。这意味着标定不太准的IMU、安装角度偏差几度,只要不太夸张,滤波过程会自动纠正一部分,这对工程部署非常友好。我在实际使用中有一块IMU安装偏了两三度,没重新标定直接跑,地图只是稍微有点倾角,定位没有发散,这就是误差状态估计在兜底。

1.4 核心技术三:增量式k-d tree与降采样策略

增量式k-d tree(ikd-Tree)是FAST-LIO2的作者Pushkar在HKU工作期间开源的一个数据结构,支持点云的动态插入、删除和最近邻搜索。它在传统k-d tree基础上加了平衡维护策略,点云更新是增量的,不需要每次重新建树。这个设计对SLAM的场景特别契合:地图不断增长,但每次只新增一小部分,查询也只关心局部,增量树让这两件事都变得很便宜。

降采样策略也很讲究。FAST-LIO2的降采样发生在两个地方:一是每帧点云进来先降采样,减少参与配准的点数;二是插入地图前再次降采样,控制地图的增长速率。这两个降采样的体素大小是独立可调的,通常会设为一致,比如都是0.5m。体素设置越小,地图细节越丰富但计算量越大;设置越大,计算量小但地图会显得“糊”。低算力场景建议从0.5m起步,再根据实际效果调。

2. 状态估计与多传感器融合设计

2.1 紧耦合框架下的IMU前置积分

FAST-LIO2采用紧耦合方式,IMU的原始测量数据直接参与状态预测,而不是像松耦合那样先单独做IMU航迹推算再和激光结果做融合。紧耦合的核心收益是IMU短时精度高、激光长时无漂移,两者互补。具体实现上,每一帧激光之间会积许多个IMU数据,预测状态及其协方差。这意味着IMU频率决定了状态预测的平滑程度。

工程上有两个IMU参数比较关键:加速度计和陀螺仪的噪声密度、随机游走。这些参数会在配置文件的imu_noise段里设置,参数偏大偏小都会影响滤波增益。我在实际测试中发现,如果IMU参数跟真实传感器差太远,会出现位姿抖动甚至发散,这时候不是算法不行,是噪声模型没填对。正规做法是查IMU芯片手册,比如BMI088的参数和MPU6050差别就很大,不能套用默认值。

2.2 激光雷达点云对齐原理

激光里程计每帧都在做同一件事:把当前帧点云变换到地图坐标系,和ikd-Tree储存的局部地图找对应点,优化变换矩阵使得点到平面/点到点的距离最小。FAST-LIO2默认用的是点到面的距离,即对每个点找到地图中邻近的几个点拟合出一个平面,计算点到平面的距离作为残差。

这个过程中有几个细节直接决定精度。第一,点云时间戳要对准,很多机械式激光雷达的点云是分角度扫描的,存在运动畸变,FAST-LIO2用IMU做去畸变,把每个点的时间偏移补偿掉。第二,外参变换(激光雷达相对IMU的位姿)影响非常大,外参不准,去畸变和地图投影都会出错,表现出来的症状是建图边缘模糊、定位漂移。建议先做离线标定,在线再让iEKF微调。

2.3 融合RTK/GNSS的工程扩展

最近在不少项目里看到有人把FAST-LIO2和RTK融合使用,这个方向很实用。FAST-LIO2本身没有内置GPS融合模块,原版主要依赖激光雷达和IMU,但它的状态估计框架留了观测更新的口子,可以通过修改代码把RTK的位姿/位置作为观测注入。网上也有不少分支做了这类工作,整体思路是在iEKF更新阶段,新增一个RTK观测方程,用RTK输出的经纬度和高度转换到局部坐标系,然后作为位置观测做一次更新。

融合RTK的场景多是室外大场景,比如园区巡检、港口AGV。FAST-LIO2负责高频短时平滑定位,RTK负责低频绝对约束,纠正长时间运行产生的累积漂移。需要提醒的是,RTK和FAST-LIO2坐标系需要对齐,一般做法是通过几个已知点做坐标转换参数求解,不然位置观测会带系统性偏差。融合后建图闭环更稳定,长距离回环漂移也小很多。

3. 实操:从源码编译到低算力设备部署

3.1 环境依赖与编译要点

FAST-LIO2官方是基于ROS1开发的,也有ROS2分支。我这边以ROS1 Noetic + Ubuntu 20.04为例,依赖项主要有:

  • ROS Noetic(ros-noetic-pcl-ros, ros-noetic-cv-bridge)
  • Eigen 3.3.7以上
  • PCL 1.10
  • 编译工具链

源码克隆之后,在src目录下执行:

catkin_make -j4

这里有个经验,如果设备内存比较小,建议用-j2或者-j1,加-DCMAKE_BUILD_TYPE=Release明确开优化。第一次编译ikd-Tree和配准部分会比较耗时,Jetson Nano上可能要二十分钟,属于正常现象。

编译中常见的坑有两类。一类是Eigen版本冲突,比如系统装了Eigen 3.3.4而代码需要3.3.7,症状是编译报找不到Eigen/src/Core/util/Macros.h,解决办法是手动安装新版Eigen到/usr/local/include/eigen3,并在CMakeLists里指定路径。另一类是PCL的VTK版本冲突,Noetic默认VTK7,一般没事,但如果装了其他版本的VTK,会报一堆链接错误,建议干净环境重装ROS。

3.2 跑通第一个建图demo的参数调整

拿到源码后,官方提供了几个示例配置,比如ouster64_mid360livox_avia这类。如果你手上的激光雷达不在列表里,需要自己写配置。核心参数就那几个:

  • common段:激光雷达类型、话题名、外参
  • preprocess段:点云去畸变开关、降采样体素大小
  • imu段:IMU话题名、噪声参数、外参
  • filter_size_surf:地图配准时的体素大小,这个参数直接影响精度和算力

我实测过用Livox Mid-360、ouster OS0-32、甚至国产16线机械雷达,都能跑通,关键就是降采样和体素参数要匹配雷达点云密度。Mid-360这类非重复扫描雷达点云分布均匀,filter_size_surf可以设0.5m;16线机械式雷达的垂直分辨率低,可以设0.3m,密一点保证配准有足够约束。

启动命令一般是先起雷达驱动和IMU驱动,再跑:

roslaunch fast_lio mapping.launch

然后播放自己的bag包:

rosbag play your_bag.bag

跑通之后保存地图有两种方式,一种是用pcl_rospointcloud_to_pcd工具订阅实时地图话题存PCD,另一种是跑完后在RVIZ里手动保存,个人推荐前者,更稳定。

3.3 低算力设备的适配策略

低算力设备上跑算法,本质是“减少每帧参与计算的点数+减少地图查询范围”。我列几个实测有效的参数组合:

参数名默认值低算力建议值说明
filter_size_surf0.50.8-1.0增大体素,减少配准点数
max_points_size10000050000限制每帧点云上限
ikdtree_removal0.20.3地图点删除半径,控制地图规模
imu_enabletruetrue低算力下IMU更重要,别关

有个容易忽略的点:点云预处理阶段如果开了运动补偿,对CPU也有开销,但这项不建议关,因为关了建图精度会明显下降。更值得优化的是雷达驱动的点云输出频率,如果在低算力设备上出现卡顿和丢帧,可以考虑把雷达驱动里的点云发布频率从20Hz降到10Hz,比如在驱动配置里设置publish_frequency: 10,效果显著。

我在Jetson Orin NX上跑Mid-360,filter_size_surf设为0.6m,CPU占用大概40%,内存1.5GB左右,长时间跑几公里不掉帧。这个数据可以作为低算力部署的参考基线。

4. 踩坑实录与问题排查技巧

4.1 常见问题速查

跑FAST-LIO2过程会碰到不少问题,很多问题现象一样但原因不同,排查起来很费时间。我把自己的踩坑经验整理成表格,先对照现象再按优先级排查:

现象可能原因排查方法
建图发散/轨迹飞掉雷达话题时间戳异常、外参错误、IMU数据时间戳跳变rostopic echo检查时间戳,用rqt_tf_tree看坐标变换
地图模糊/重影外参不准、运动畸变未补偿、降采样体素太大先做静态场景测试,确认外参,再调小filter_size_surf
CPU占用过高降采样体素太小、地图增长过快、点云频率过高htop查看线程占用,逐步调大filter_size_surf
初始化失败点云太稀疏、IMU数据异常、雷达和IMU时间同步差确认IMU话题发布频率在100Hz以上,雷达和IMU时间戳差小于10ms
跑一段时间定位漂移单激光没有回环、累积误差接RTK做位置观测,或定期回到已知起点

4.2 抖动、跳变与IMU外参的“隐形杀手”

FAST-LIO2最常见的问题不是算法本身,而是传感器“带病工作”。我遇到过一台底盘在静止时位置输出有规律抖动,排查了好久,发现是IMU的安装螺丝没拧紧,微小的机械晃动被IMU放大。这种机械层面的问题在算法上很难完全弥补,建议在装机时先把IMU固定死,最好用减震海绵垫一下,减少高频振动。

另一个隐蔽的问题是IMU外参初始化。FAST-LIO2虽然能在线估计外参误差,但那是在外参初始值“足够接近真值”的前提下。如果外参初始值偏了十几度,滤波会陷入局部最优甚至发散。我习惯先用IMU静态数据计算重力对齐,再用一段直线运动加旋转,通过连续几帧点云粗配准估算外参初始值,这样成功率会高很多。

4.3 建图精度验证方法

很多人跑完SLAM只看RVIZ里的地图“像不像”,这不够严谨。定量验证精度有一个低成本方法:在场地里放几个已知坐标的标记物,让机器人绕着场地走一圈,建图完成后在PCD地图里用CloudCompare量标记物坐标,和真值对比。这个方法能测出地图的绝对精度和相对精度,对判断参数调优方向很有帮助。

我在自己测试时,用RTK在室外场地标了6个点,FAST-LIO2建图跑完,在CloudCompare里对比,水平误差大概在10到20cm,这个精度对导航来说是够用的。如果你需要更高精度,可以尝试两个方向:一是调小降采样体素到0.3m,增加配准约束;二是在线标定外参,让外参收敛更准确。

5. 在ROS工程里的集成与后续优化方向

5.1 与move_base导航栈的配合

FAST-LIO2输出的地图是点云地图,move_base这类导航栈需要的是栅格地图/占据栅格地图,中间要加一层转换。简单做法是用octomap_server把点云地图转成OctoMap,再投影成2D代价地图。也有更轻量的方案,直接用pointcloud_to_laserscan把点云转成2D激光数据,喂给gmapping或者直接给costmap用,好处是省掉了OctoMap的计算量。

实测下来,用pointcloud_to_laserscan是最快速的集成方式。因为它把3D点云压成2D scan,配合move_base的costmap工作得很好。不过这种方法在陡坡、楼梯这类多层结构环境会丢失信息,如果机器人主要在平地上跑,完全够用。如果要做3D导航,就老老实实用OctoMap。

5.2 时间同步与多传感器时钟校准

多传感器融合最头疼的是时间同步。FAST-LIO2对时间戳的要求比纯视觉SLAM高得多,因为IMU和激光雷达的时间不同步会直接体现在点云畸变上。我在工程里踩过一个大坑:雷达驱动和IMU驱动用了不同的时间源,导致系统跑起来十几秒就发散,检查bag才发现时间戳差了200ms。

解决办法是让所有驱动统一使用机器人的系统时间,或者用time_synchronizer做软同步。更严谨的做法是给激光雷达和IMU都用PTP或PPS做硬件同步,但这需要传感器支持。对于大多数入门项目,软同步已经能解决80%问题。实际调试时,可以用rostopic delay单独查看每个话题的时间戳延迟,保持雷达和IMU的时间戳延迟在10ms以内就行。

5.3 从FAST-LIO2到自研方案:哪些模块可以借鉴

如果你不想直接用FAST-LIO2,而是想自己写一套定位建图系统,它的几个设计思想非常值得借鉴。一是“降采样+增量树”的组合,这个思路在视觉SLAM里也能用,比如对关键帧点云做降采样后插入地图,配合增量式数据结构提升查询效率。二是“IMU前置积分+激光修正”的紧耦合框架,比松耦合在退化环境下稳定很多。三是“误差状态建模”这个思路,把标定残差、传感器偏置都塞进状态向量里,工程上确实省事。

我自己在做一个轻量级定位模块时,参考了FAST-LIO2的ikd-Tree和iEKF框架,替换了部分代码来适配国产雷达,整个开发周期缩短了一大截。开源项目的最大价值就在这里,不一定拿来直接用,能从中提炼出适合自己的工程架构,就已经很值得了。

5.4 ROS2环境下的移植思路

ROS2逐渐成为主流,FAST-LIO2也有ROS2版本的分支,但功能完整度参差不齐。我在ROS2 Humble上试过编译,主要问题是PCL和Eigen的版本兼容、以及tf2接口的差异。如果是新项目直接上ROS2,建议先用Docker镜像稳定编译环境,再逐步移植自己的传感器驱动。

另外一个思路是保持ROS1和ROS2双系统,通过ros1_bridge互通。比如无人机上跑FAST-LIO2(ROS1环境),地面站用ROS2做导航和显示,两个系统通过桥接通信,开发效率和运行稳定性都能兼顾。这个方案我已经在多个地面机器人项目里验证可行,算是一种比较务实的过渡做法。

整体用下来,FAST-LIO2在“低算力高精度”这个平衡点上确实做得漂亮。它的设计取舍——不提取特征、直接配准、紧耦合IMU、增量式地图管理——每一项都在为算力和精度的平衡服务。如果你正准备在有限的硬件上做机器人定位建图,建议先拿公开数据集跑通流程,再换到自己的传感器组合,最后逐步调参数。等你把外参、时间同步、降采样这几个关键点摸透了,这套方案基本能在绝大多数室内外场景里稳定工作。

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

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

立即咨询