
做机器人的朋友多少都有过这种体会算法跑通了一上真机就卡成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 核心技术二迭代误差状态卡尔曼滤波iEKFFAST-LIO2的状态估计核心是迭代误差状态卡尔曼滤波可以把它理解为“IMU负责猜激光负责改”。每一帧激光到来之前IMU积分预测出机器人位姿和速度激光点云进来之后把点云投影到预测位姿下和地图做配准算出残差再用残差修正预测状态。这个过程迭代多次直到残差收敛。误差状态的好处是IMU的偏置、噪声、甚至外参误差都被建模成误差状态的一部分可以在线估计和修正。这意味着标定不太准的IMU、安装角度偏差几度只要不太夸张滤波过程会自动纠正一部分这对工程部署非常友好。我在实际使用中有一块IMU安装偏了两三度没重新标定直接跑地图只是稍微有点倾角定位没有发散这就是误差状态估计在兜底。1.4 核心技术三增量式k-d tree与降采样策略增量式k-d treeikd-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 Noeticros-noetic-pcl-ros, ros-noetic-cv-bridgeEigen 3.3.7以上PCL 1.10编译工具链源码克隆之后在src目录下执行catkin_make -j4这里有个经验如果设备内存比较小建议用-j2或者-j1加-DCMAKE_BUILD_TYPERelease明确开优化。第一次编译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_mid360、livox_avia这类。如果你手上的激光雷达不在列表里需要自己写配置。核心参数就那几个common段激光雷达类型、话题名、外参preprocess段点云去畸变开关、降采样体素大小imu段IMU话题名、噪声参数、外参filter_size_surf地图配准时的体素大小这个参数直接影响精度和算力我实测过用Livox Mid-360、ouster OS0-32、甚至国产16线机械雷达都能跑通关键就是降采样和体素参数要匹配雷达点云密度。Mid-360这类非重复扫描雷达点云分布均匀filter_size_surf可以设0.5m16线机械式雷达的垂直分辨率低可以设0.3m密一点保证配准有足够约束。启动命令一般是先起雷达驱动和IMU驱动再跑roslaunch fast_lio mapping.launch然后播放自己的bag包rosbag play your_bag.bag跑通之后保存地图有两种方式一种是用pcl_ros的pointcloud_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-360filter_size_surf设为0.6mCPU占用大概40%内存1.5GB左右长时间跑几公里不掉帧。这个数据可以作为低算力部署的参考基线。4. 踩坑实录与问题排查技巧4.1 常见问题速查跑FAST-LIO2过程会碰到不少问题很多问题现象一样但原因不同排查起来很费时间。我把自己的踩坑经验整理成表格先对照现象再按优先级排查现象可能原因排查方法建图发散/轨迹飞掉雷达话题时间戳异常、外参错误、IMU数据时间戳跳变用rostopic echo检查时间戳用rqt_tf_tree看坐标变换地图模糊/重影外参不准、运动畸变未补偿、降采样体素太大先做静态场景测试确认外参再调小filter_size_surfCPU占用过高降采样体素太小、地图增长过快、点云频率过高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-LIO2ROS1环境地面站用ROS2做导航和显示两个系统通过桥接通信开发效率和运行稳定性都能兼顾。这个方案我已经在多个地面机器人项目里验证可行算是一种比较务实的过渡做法。整体用下来FAST-LIO2在“低算力高精度”这个平衡点上确实做得漂亮。它的设计取舍——不提取特征、直接配准、紧耦合IMU、增量式地图管理——每一项都在为算力和精度的平衡服务。如果你正准备在有限的硬件上做机器人定位建图建议先拿公开数据集跑通流程再换到自己的传感器组合最后逐步调参数。等你把外参、时间同步、降采样这几个关键点摸透了这套方案基本能在绝大多数室内外场景里稳定工作。