这几年做机器人和测绘相关的实时建图,Mid-360和FAST-LIO2这个组合算是绕不开的一对搭档。前者是Livox推出的一款360°非重复扫描固态激光雷达,后者是港大火星实验室开源的一套紧耦合激光惯性里程计算法,一个负责“看”,一个负责“算”,配合起来能在室内外场景下实时输出高质量的点云地图。这篇文章把我从硬件连接、驱动安装到跑通FAST-LIO2、保存高精度点云地图的完整过程梳理一遍,包括我实际踩过的坑和调参思路,给正在做SLAM建图、或者刚接触激光雷达点云处理的同学一份可以直接参考的完整流程。
1. 为什么用Mid-360和FAST-LIO2这个组合
1.1 选型逻辑:非重复扫描带来的数据红利
先说硬件。Mid-360是Livox在2022年前后推向市场的混合固态激光雷达,最核心的特点是采用了非重复扫描方式。传统的机械式激光雷达靠电机旋转带动激光发射器,扫描轨迹是固定的水平线束,点云虽然均匀但垂直分辨率受限于线数。Mid-360的内部棱镜结构让激光束在视场角内做花瓣式摆动,随着积分时间增加,点云覆盖率会不断提升。这意味着在任意一帧数据里,环境细节的采集密度远高于同价位的机械雷达。
我最早用这台雷达做园区巡检项目时,感受最深的一点是它能“看”清楚墙面的电箱、管线和植被轮廓,而这些信息在16线机械雷达上基本是一团模糊的点带。Mid-360的水平视场角达到360°,垂直视场角覆盖-7°到+52°,探测距离在10%反射率下约40米,标称精度在±2厘米左右。对建图来说,这些参数决定了它既能做近距离的精细扫描,也能在中距离保持足够的地图覆盖能力。
软件侧,FAST-LIO2匹配这套硬件的逻辑也很直接:它不需要对原始点云做特征提取,而是直接拿全量点云与局部地图做配准。传统激光里程计为了追求实时性,往往先提取平面点、边缘点这些特征,再通过特征匹配估计位姿。这种做法在结构化环境里表现不错,但遇到植被、堆料、碎石等非结构化场景时,特征点数量和质量都会明显下降。FAST-LIO2把所有点都当作配准约束,再加上ikd-Tree做增量式空间索引,在保证精度的同时计算效率也扛得住每秒几十万点的输入。
1.2 全流程技术路线拆解
从点云采集到高精度建图,整个流程可以拆成四段:硬件与驱动层、数据预处理层、里程计建图层、地图后处理层。
硬件与驱动层包含Mid-360的机械安装、供电、网口通信以及Livox官方驱动livox_ros_driver2,输出的是原始点云话题和IMU话题。数据预处理层负责时间同步、点云去畸变和必要的外参标定,这部分效果直接决定建图质量。里程计建图层就是FAST-LIO2的核心,它把IMU预积分结果和雷达点云配准残差做紧耦合优化,实时输出机器人的位姿轨迹和增量更新的全局地图。地图后处理层是把运行过程中累积的点云地图保存下来,再做抽稀、滤波、矫正和格式转换,最终交付给测绘、导航或者展示使用。
这个路线里最容易被人忽略的是第四段。很多人以为FAST-LIO2打印出“Map saved”就完成了,但实际保存下来的pcd文件往往带有运动畸变、重叠点和离群噪点,尤其当你在建图过程中路过玻璃幕墙、镜面物体或者动态行人时,地图里会残留明显的拖影和杂点。后处理不是可选的锦上添花,而是工程落地的必要一步。
2. 硬件准备与环境搭建
2.1 Mid-360的机械与电气安装
Mid-360整机重量在265克左右,尺寸很小,可以直接用底部四个M3螺丝固定在机器人顶板或者测绘支架上。安装时有一个容易被忽视的细节:雷达顶部的朝向标识。Mid-360的坐标系定义里,X轴指向雷达正面,Y轴指向左侧,Z轴竖直向上。安装时要确保雷达的正面标记与机器人前向一致,否则后续在FAST-LIO2里调整外参会非常折磨人,因为旋转矩阵的初始值差一点,收敛结果就可能差出十万八千里。
供电方面,Mid-360支持10到24V直流输入,推荐使用12V或24V稳压电源单独供电。这里我吃过一次亏:一开始把雷达和驱动电机共用一个电源模块,电机启动时瞬时压降导致雷达间歇性重启,点云数据出现周期性丢帧。后来改成独立电源回路,问题立刻消失。激光雷达对电源质量非常敏感,如果在建图过程中发现点云每隔几秒就断一帧,优先检查电源而不是代码。
通信方面,Mid-360走的是千兆以太网,默认IP是192.168.1.50,连接雷达时要把电脑的有线网卡配到同一网段,比如192.168.1.100,子网掩码255.255.255.0。Livox官方也提供了Livox Viewer工具,可以先在Windows或者Ubuntu上打开它确认雷达能被识别,再进ROS环境。
2.2 开发环境与软件依赖
我这次使用的环境是Ubuntu 20.04 + ROS Noetic,这也是目前FAST-LIO2社区里验证最充分的组合。如果你用Ubuntu 22.04,可以跑ROS2 Humble版本,但需要注意Livox ROS2驱动和FAST-LIO2的分支选择,否则容易碰到编译不通过的问题。
需要安装的核心依赖包括:
- ROS Noetic(ros-noetic-desktop-full)
- PCL库(点云处理,ros-noetic-pcl-ros自带)
- Eigen3(线性代数库)
- Ceres Solver(非线性优化求解器)
- livox_ros_driver2(Livox官方ROS驱动)
- fast-lio2(港大开源的建图算法包)
编译FAST-LIO2之前建议先单独验证livox_ros_driver2能否正常工作。很多新手把两个包一起编译,出了问题分不清是驱动的问题还是算法的问题。我是这样做的:先在工作空间里只放livox_ros_driver2,编译后用Livox Viewer确认点云话题正常发布,再往工作空间里加FAST-LIO2。
一个小技巧:编译Ceres Solver时如果系统自带的版本过旧,建议直接源码编译最新稳定版。FAST-LIO2对Ceres版本有一定要求,旧版本在某些优化问题上会直接崩掉或者迭代不收敛,排查起来非常浪费时间。
3. FAST-LIO2的核心原理与参数配置
3.1 算法原理:从特征匹配到全量点云配准的转变
FAST-LIO2之所以在建图精度和鲁棒性上表现突出,核心在于它把“配准”这件事做得很彻底。传统方案通常先做特征提取,再基于特征匹配估计位姿。FAST-LIO2却直接用原始点云,把当前帧每个点与局部地图里的最近邻点建立对应关系,然后构造点到平面的距离残差,通过迭代优化同时修正位姿和地图。
这里就不得不提ikd-Tree这个数据结构。它是FAST-LIO2开源代码里最关键的工程创新。普通的kd-Tree在每次插入新点后都要重建,数据量一大效率就会断崖式下降。ikd-Tree则通过增量式更新机制,只在必要时重平衡子树,让建图过程中几十万点的地图插入与查询都能保持在实时水平。可以说,没有ikd-Tree,直接全量配准的思路很难在嵌入式平台上跑起来。
IMU紧耦合是另一个核心点。FAST-LIO2里IMU数据不是用来辅助去畸变的简单角色,而是参与状态估计的主线索。系统把IMU预积分结果作为预测,再把雷达点云配准残差作为观测,两者在迭代误差状态卡尔曼滤波框架下融合,输出高频且平滑的位姿。这也是为什么在快速旋转、颠簸路面这类IMU信息丰富的场景里,FAST-LIO2的轨迹比纯雷达里程计稳定得多。
3.2 关键参数配置详解
FAST-LIO2的配置主要体现在launch文件和yaml文件里。我以自己常用的配置为例,把几个直接影响精度的参数列出来:
雷达话题与IMU话题:launch文件里要确保lid_topic和imu_topic与实际驱动发布的话题一致。使用livox_ros_driver2时,默认点云话题是/livox/lidar,IMU话题是/livox/imu。
外参矩阵:yaml文件中的extrinsic_T和extrinsic_R定义了雷达相对于IMU的位置和姿态。如果雷达和IMU是分体安装的,这两个值必须实际测量或者标定,不能随便填零。Mid-360自带IMU,通常在出厂时Livox已经给了雷达和IMU之间的外参,可以先用默认值,再通过实际建图效果微调。
点云密度相关参数:max_iteration控制每次配准的最大迭代次数,一般在5到10之间。调大这个值会增加计算负担,但对收敛稳定性有帮助。voxel_size控制局部地图的体素下采样分辨率,这个值越小地图越精细,但计算量也越大。在室内环境我用0.2米,室外大场景会调到0.3到0.5米,兼顾精度和实时性。
时间同步:Livox驱动默认会给点云和IMU打上时间戳,FAST-LIO2里通过time_sync_en参数控制是否启用时间同步。如果雷达和IMU来自同一个设备,直接用硬件时间戳即可;如果分体安装且没有做硬同步,建议先用软件时间同步,否则位姿估计会出现明显延迟误差。
这里我个人的实用建议是:第一次运行时不要急着调参数,先用默认配置把数据跑通,记录下CPU占用率和里程计漂移情况,再做针对性优化。一上来就改一堆参数,出了问题根本不知道是哪个改错了。
4. 从采集到建图的完整实操流程
4.1 启动雷达与检查数据质量
连接好雷达电源和网线后,在终端里执行:
source /opt/ros/noetic/setup.bash source ~/catkin_ws/devel/setup.bash roslaunch livox_ros_driver2 msg_Mid360.launch这条命令会启动Mid-360驱动,并发布/livox/lidar和/livox/imu话题。接着打开两个新终端,一个运行rviz查看点云,另一个用rostopic工具检查话题频率。
rostopic hz /livox/lidar rostopic hz /livox/imu正常情况下,点云话题发布频率应该在10Hz左右,IMU话题在200Hz左右。如果点云频率忽高忽低,说明网络有丢包或者供电不稳。还有一个常见问题是一开始雷达需要短暂的初始化时间,前几秒点云帧可能显示为空,这是正常的。
在rviz中检查点云时,我通常会绕雷达走一圈,确认周围的墙体、桌椅、地面轮廓是否清晰,有无明显变形。如果看到点云漂移、重影或者局部膨胀,先别急着调FAST-LIO2,优先排查雷达安装是否牢固、是否有强反射物体干扰、IMU数据是否正常。硬件层面的问题不解决,软件调参都是白费功夫。
4.2 实时建图运行与轨迹监控
确认点云质量没问题后,启动FAST-LIO2:
roslaunch fast_lio mapping.launch启动后rviz会自动加载FAST-LIO2的显示配置,可以看到当前帧点云、累积地图和实时轨迹。我习惯边走动边在rviz里观察地图增长情况。如果地图边缘清晰、没有明显拖影,说明系统的位姿估计比较稳定。
一个值得注意的点是,建图过程中应尽量避免长时间静止不动。FAST-LIO2这类激光惯性系统在静止状态下,激光点云退化成重复的同一场景,IMU的积分误差无法被配准约束修正,位姿漂移会缓慢累积。这也是为什么很多人在原地开机半天后,地图会出现整体扭曲。
在把设备移动到新环境前,我会先让系统稳定几秒钟,确认当前地图没有明显的重影再继续。如果发现地图开始歪斜,最好停一下走回之前清晰的位置,让系统重新收敛。
4.3 地图保存与后处理
FAST-LIO2提供两种地图保存方式。运行过程中按下键盘的2键,会保存当前扫描帧为pcd文件;按下3键,会保存全局累积地图。保存位置可以在launch文件里通过pcd_save_path参数指定,默认路径通常是pcd文件夹。
我通常保存两种地图:一个是不做任何处理的全局完整点云,用于精度分析;另一个是经过体素滤波抽稀后的轻量版本,用于导航避障和展示。保存后可以用PCL的pcl_ros工具做后处理:
rosrun pcl_ros voxel_grid pcd_input.pcd pcd_output.pcd -leaf 0.05 0.05 0.05这条命令会把地图中5厘米范围内的点合并成一个点,既能减小文件体积,又能适当去除重叠噪点。如果地图里有离群点,可以再用StatisticalOutlierRemoval滤波器处理:
rosrun pcl_ros statistical_outlier_removal pcd_input.pcd pcd_output.pcd -mean 20 -stddev 1.0这两个命令的语义是:统计每个点与周围20个邻近点的距离分布,剔除与平均距离相差超过1个标准差的点。实际使用下来,对去除玻璃反光产生的飞点非常有效。
后处理后的点云可以直接用CloudCompare打开做精度检查,或者存储为其他格式。比如需要高程渲染时,可以在CloudCompare里根据Z轴给点云着色,再导出成图片或tif格式用于测绘应用。
5. 常见问题与排查技巧实录
5.1 点云“飘”和地图重影的根本原因
做激光建图,大家最常遇到的三个问题就是点云飘、地图重影、轨迹漂移。根据我的经验,这些问题大多数时候不是算法bug,而是工程细节没做到位。
点云飘的本质是位姿估计偏差被投影到了点云坐标变换上。原因包括:IMU外参标定不准确、雷达安装松动、建图过程中设备剧烈震动、IMU数据频率异常等。其中外参不准是最隐蔽的。雷达和IMU之间的旋转矩阵哪怕偏了零点几度,远距离点云的投影误差会被放大到厘米甚至分米级别。
地图重影则常出现在多次经过同一区域时。系统在闭环的时刻通过配准把当前帧对齐到已有地图,但如果配准优化陷入局部极小值,新地图和旧地图之间就会错开一个角度,形成明显的“重影”。多数情况下重影可以通过提高点云密度、增加观测角度多样性来缓解。
轨迹漂移是累积误差的体现。FAST-LIO2没有回环检测,长距离建图时小误差会不断累积。如果建图时间超过20分钟,或者移动范围特别大,轨迹尾部与头部之间可能会出现可见偏差。我的经验是分段建图、每段较短,再通过后处理配准融合各段地图,比一次性长距离硬跑要可靠得多。
5.2 实战排查流程与解决方案
下面这张表是我在实际项目中总结出的快速排查指南,按问题出现的概率排序:
| 问题现象 | 可能原因 | 排查与解决方案 |
|---|---|---|
| 建图刚开始就飘 | IMU未完成初始化 | 启动后静止3到5秒,确保IMU预积分收敛再移动 |
| 地图边缘模糊 | 点云配准残差过大 | 检查雷达是否松动,重新紧固安装螺丝 |
| 局部地图重影 | 外参标定不准 | 重新标定雷达到IMU外参,或使用Livox出厂标定文件 |
| 动态物体拖影 | 行人、车辆经过 | 后处理时用统计滤波去除离群点,无法根除则采集时避开 |
| 里程计突然中断 | 计算资源不足 | 降低voxel_size、关闭可视化节省CPU占用 |
| 点云整体偏斜 | 初始位姿错误 | 确认RViz中的固定坐标系设为camera_init或body |
排查时我的习惯是“从硬件往软件走”。先看电源和网线,再看IMU数据是否稳定,然后看外参是否合理,最后才怀疑算法参数。很多人一上来就立刻调FAST-LIO2内部参数,反而浪费大量时间。
现场调试时,我还会开几个辅助命令实时监控状态:
rosrun rqt_tf_tree rqt_tf_tree rostopic echo /Odometry -n 20前者检查TF树是否完整,后者能直接看到里程计输出的位姿变化,一旦发现数值跳变就能立刻定位异常。
5.3 独家避坑技巧
这里分享三个很难从官方文档里直接学到的经验。
第一个是雷达视场角利用。Mid-360的垂直视场角是59°,向上覆盖52°。建图时如果雷达装得过于水平,顶部的点云信息就浪费了。在楼梯间、仓库货架这类环境里,我会把雷达稍微向上倾斜10到15度,既保留了地面信息,又能更多扫描到墙面上部的结构,地图完整度明显提升。
第二个是IMU温漂问题。Mid-360的IMU在刚上电的几分钟内,零偏会随着温度变化而漂移。FAST-LIO2会在启动时读取IMU初始零偏估计,如果此时IMU还没达到热稳定状态,后续建图会产生缓慢但持续的漂移。我的做法是每次上电后先等2到3分钟再开始建图,这个小习惯帮我避免了很多“查不出原因”的漂移问题。
第三个是保存地图之前先绕回起点。建图结束后,我会再走回出发位置附近,让系统重新观测一遍初始场景。这相当于给里程计一个“余量校验”,即使中间有累积误差,也能在最后一段通过配准修正一部分。保存出来的地图,整体闭合度比直接结束要好很多。
6. 高精度建图的进阶扩展方向
流程跑通之后,如果想在实际项目中进一步提升地图精度或者拓展应用,可以参考我后续尝试过的几个方向。
多传感器融合是第一步。Mid-360的点云精度虽然不错,但在雨雾、扬尘等恶劣环境下依然会退化。我后面把视觉相机和GNSS接收机加进来,通过FAST-LIO2的扩展框架进行视觉惯性激光联合建图,简单场景下精度提升不大,但复杂环境下的鲁棒性提升很明显。
动态物体过滤可以引入深度学习。激光雷达点云里,行人和车辆是可以被语义分割网络识别的。我试过在FAST-LIO2之前串一个轻量级点云语义分割模型,把标为“人”、“车”的点剔除后再送入配准模块,地图干净程度提升很大。缺点是增加了计算负载,对嵌入式平台的实时性会有影响。
地图格式转换与导航对接也值得重视。建好的pcd地图要用于导航,需要先转换成栅格地图或者八叉树地图,做膨胀处理生成代价地图。CloudCompare里可以精确裁剪地图范围、做坐标对齐,把点云地图语义化后再交给move_base等导航框架使用。这一步虽然不直接影响建图精度,但决定了地图能不能真正用起来。
如果你后续要做的不是固定场景建图,而是大规模地形测绘,那重点应该放在多段地图的配准融合和全局优化上。可以把多次采集的pcd文件在CloudCompare里做手动粗配准,再用ICP进行精配准,拼接出完整的区域点云。这套流程我在户外坡地场景和园区环境里都验证过,效果稳定,只是对点云重叠率和初始对齐的要求比较高。
从Mid-360的硬件安装、FAST-LIO2的配置调优,到pcd点云地图的后处理,这一套流程走下来,基本就能在绝大多数场景里拿到可用的高精度地图了。我是用“先跑通、再调参、后优化”的思路推进的,遇到问题也是从硬件到软件逐层排查。建图这件事越急着追求效果越容易踩坑,反而是慢下来把每个环节都确认一遍,往往一次就能跑出满意结果。