ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

LIO-SAM实战:激光雷达与IMU联合标定全流程指南

LIO-SAM实战:激光雷达与IMU联合标定全流程指南 一年前我给一台室内巡检机器人做停车场环境建图LIO-SAM跑出来的地图在回环处直接裂开同一面墙出现了三层重影。排查到第三天才发现罪魁祸首是params.yaml里那组拍脑袋填的雷达与IMU外参。标定完再跑同一份bag地图精度完全是两个段位回环闭合后墙面对齐得干净利落。从那以后我把项目里所有激光雷达IMU组合都重新标了一遍顺手也帮同事们的机器人小车检查了一圈。这篇文章就把LIO-SAM这条技术栈下的激光雷达与IMU联合标定完整梳理一遍从外参标定的原理、标定工具选型到数据采集实操和参数回填最后是把LIO-SAM跑通之后的调参与验证方法。内容偏实战适合已经有LIO-SAM基本使用经验、想进一步提升建图精度或者正在搭建激光惯性SLAM系统的朋友参考。1. 先搞明白联合标定到底在标什么外参、内参与坐标系约定1.1 外参标定的本质一个旋转矩阵加一个平移向量激光雷达和IMU是两个独立的传感器各自有坐标系。LIO-SAM在做点云配准和IMU预积分之前必须把雷达点云从雷达坐标系变换到IMU坐标系。这个变换就是一组刚体变换旋转矩阵R加上平移向量t合起来叫外参extrinsic。数学上很简单假设雷达坐标系里有一个点p_l它在IMU坐标系里的坐标p_i就是p_i R * p_l t旋转矩阵R决定姿态对齐平移向量t决定原点偏移。就是这组数值直接影响后续所有环节——点云畸变校正、特征提取、scan-to-map匹配、因子图优化全都在这个变换之后进行。实际项目里最典型的坑是把雷达装在IMU正上方平移向量大概估一个0.05, 0, 0.15旋转全填0就开始跑地图。这种拍脑袋外参在小场景、短时间里问题不大但建图时间一长、场景一大误差就被因子图优化慢慢放大最后地图扭曲到你怀疑算法被改坏了。1.2 外参不准在地图上到底长什么样我在多个项目里遇到过外参不准的情况表现通常很一致地图出现重影、叠影尤其是墙面和门框边缘同一特征在点云图里有两到三层轮廓机器人静止时点云还在缓慢旋转或漂移IMU明明已经静止建图节点却认为自己在动走过长走廊这类退化环境时轨迹发散严重回环形同虚设回环检测成功后地图出现明显断裂或错位整个走廊对不齐。这些现象有一个共同特点靠调LIO-SAM的里程计参数基本救不回来。我见过有人连续调了好几天voxel leaf大小和匹配线程数最后才发现是外参初值错了。外参是系统级的输入错误优化器只会把它分摊到轨迹和地图里让每一个环节都看起来有问题。1.3 标定方案选型imu_utils、lidar_align、手动迭代怎么搭配LIO-SAM这条技术栈下标定任务其实分两类IMU内参标定和雷达与IMU外参标定。标定类型常用工具输出内容适用场景IMU内参imu_utils、kalibr_allan噪声密度、随机游走、零偏稳定性配置LIO-SAM噪声模型外参标定lidar_align雷达到IMU的旋转矩阵和平移向量中高精度外参初值手动迭代LIO-SAM自带extrinsic参数粗略外参快速验证、冷启动实际项目里我的做法是三件套一起用先用imu_utils标出IMU的噪声参数配置进LIO-SAM的noiseModel再用lidar_align求解外参得到一个比拍脑袋靠谱得多的初值最后回填进LIO-SAM跑几轮数据微调。1.4 为什么拿LIO-SAM当标定验证骨架LIO-SAM本身并不直接输出外参标定结果但它是最好的标定验证框架。reason很简单LIO-SAM的前端同时用到了雷达配准和IMU预积分两个传感器之间的外参只要有一点不对系统误差就会以明显的方式暴露出来。另外它的params.yaml把所有外参、噪声模型参数都放在明面上改起来非常方便。标定结果好不好跑一段数据看地图和轨迹就知道。相比单独写一个优化脚本来验证外参直接跑SLAM反而更贴近真实使用场景。2. 环境搭建阶段最容易被拖死的几个细节版本、依赖与话题配置2.1 Ubuntu版本与ROS发行版怎么选目前我主力环境是Ubuntu 20.04 ROS Noetic。如果你的团队还在用Ubuntu 18.04 Ros MelodicLIO-SAM同样能跑通但编译依赖上会有一些差异。新项目建议直接上20.04后面接其他激光雷达驱动、相机驱动也少踩坑。安装ROS本体之后先把基本的依赖装上sudo apt update sudo apt install -y ros-noetic-pcl-ros ros-noetic-cv-bridge ros-noetic-image-transport ros-noetic-tf2-geometry-msgs这里有个容易忽略的点LIO-SAM源码里用到PCL和OpenCV但它是通过ROS的pcl_ros、cv_bridge间接依赖的。如果你系统里之前装过别的OpenCV版本可能出现头文件或库冲突。最干脆的做法是在一个干净的catkin工作空间里编译别把其他项目的第三方源码混进来。2.2 GTSAM版本LIO-SAM编译的第一大坑LIO-SAM依赖GTSAM做因子图优化最稳的是4.0.2版本。我从源码编译过最新版GTSAM结果imuPreintegration.cpp里好几个接口对不上报错信息五花八门最后老老实实切回4.0.2。编译GTSAM 4.0.2时也要注意默认情况下会编译自带的可视化工具和测试非常慢。建议关掉不需要的模块git clone https://github.com/borglab/gtsam.git cd gtsam git checkout 4.0.2 mkdir build cd build cmake .. -DGTSAM_BUILD_TESTSOFF -DGTSAM_BUILD_EXAMPLES_ALWAYSOFF -DGTSAM_BUILD_UNSTABLEON make -j8 sudo make install编译LIO-SAM之前确认一下GTSAM是否被正确找到。如果你用的是ROS Noetic有时需要给CMake指定GTSAM的安装路径否则它会去系统默认目录找旧版本。2.3 雷达驱动和IMU驱动的话题检查清单驱动都装好后别急着跑标定先把话题健康状态检查一遍。这是整个流程里最省时间的操作。rostopic hz /livox/lidar rostopic hz /imu/data rostopic echo /imu/data -n 1重点检查几个地方IMU话题频率是否稳定一般需要100Hz以上200Hz更好频率不稳会影响IMU预积分的精度雷达点云话题的frame_id是否设置正确建议统一成lidar_link或laser_frameIMU消息里的linear_acceleration和angular_velocity是否有明显数值跳变如果静止时数值乱跳说明IMU驱动或硬件有问题先修驱动再标定是否有多个节点抢同一个话题名导致数据源混乱。还有一个frame_id的坑LIO-SAM启动的时候会跑到TF树里找雷达和IMU的坐标变换关系。如果你在驱动里把雷达点云的frame_id写错了启动之后虽然不报错但点云全被变换到奇奇怪怪的坐标位置地图自然就废了。3. 联合标定实操全流程从IMU内参到外参回填LIO-SAM3.1 第一步用imu_utils标定IMU内参IMU内参主要影响LIO-SAM参数文件里三组噪声模型的数值imuAccNoise: 0.001 imuGyrNoise: 0.001 imuAccBiasN: 0.001 imuGyrBiasN: 0.001这些数值如果随意填IMU预积分对加速度和角速度的信任程度就是错的。往大了填系统过于信任激光配准在退化场景里容易飘往小了填系统过于信任IMU激光配准跳出局部最优的能力又被削弱。我的做法是用imu_utils来标定编译它之前要先编译code_utilsmkdir -p ~/catkin_lio_ws/src cd ~/catkin_lio_ws/src git clone https://github.com/gaowenliang/code_utils git clone https://github.com/gaowenliang/imu_utils cd ~/catkin_lio_ws catkin_make如果你在Ubuntu20.04上编译code_utils报错通常是缺少依赖或者std::bind相关接口问题可以先把系统的build-essential和cmake升级到最新然后再试。之后录制一段至少两小时的静态IMU数据rosbag record -O imu_static.bag /imu/data录制过程中传感器要放在稳定平面上不要碰它。两小时起步时间越长Allan方差曲线尾部越稳定标定出的随机游走值越可信。录完之后用imu_utils的launch文件处理bag会输出一个包含噪声密度和随机游走的yaml文件把这些数值填进LIO-SAM的params.yaml即可。3.2 第二步用lidar_align求解雷达与IMU外参lidar_align是ETH开源的雷达与IMU外参标定工具原理是找一个旋转矩阵和平移向量让IMU轨迹积分出的运动与雷达配准出的运动对齐。它对输入数据的要求不低但同一份数据能同时优化出外参和轨迹在工程上很实用。编译lidar_align需要先建一个catkin工作空间并把他放进去mkdir -p ~/lidar_align_ws/src cd ~/lidar_align_ws/src git clone https://github.com/ethz-asl/lidar_align.git cd ~/lidar_align_ws catkin_make编译完成后修改lidar_align的launch文件指定bag路径、雷达话题和IMU话题。建议先把IMU话题频率降到100Hz左右再录标定数据这样lidar_align处理起来更快CPU压力小一些。采集标定数据的要点是传感器在空间里做充分的多自由度运动既有平移也有旋转最好走S形轨迹并包含俯仰和滚转变化。尽量避免在狭窄走廊、空旷广场这些退化环境里采集否则优化问题病态化标定结果会非常离谱。我自己的经验是室内采一段2-3分钟、运动充分的数据然后换个房间再采一段。lidar_align运行结束后终端里会打印一组四元数和平移向量这就是雷达坐标系到IMU坐标系的变换。这里有一个需要注意的问题lidar_align给出的结果对初值有一定敏感性。如果初值和真实值差得太远它可能优化到局部最优。所以最稳妥的流程是先利用安装几何位置粗估外参再喂给lidar_align做优化。3.3 第三步把外参写进LIO-SAM的params.yamlLIO-SAM的params.yaml里有两个关键字段extrinsicRPY: [0.0, 0.0, 0.0] extrinsicTrans: [0.0, 0.0, 0.0]extrinsicRPY是旋转的欧拉角顺序通常按roll、pitch、yawextrinsicTrans是平移向量。在写入之前一定确认lidar_align输出的变换方向到底是雷达到IMU还是IMU到雷达。LIO-SAM的约定是使用雷达坐标系到IMU坐标系的变换也就是前面提到的p_i R * p_l t。如果你把lidar_align输出的变换直接照着抄进去但方向刚好反了地图大概率会散成一片。批量操作的时候可以写一个小脚本把lidar_align输出的四元数转成欧拉角再填进yaml里。回填之后先不要急着跑长距离建图。用同一份标定bag跑一小段观察初始阶段是否正常、地图是否对齐。确认没有问题后再去跑正式的SLAM数据。3.4 第四步快速验证标定结果是否靠谱验证方法我推荐两种结合使用。第一是肉眼观察地图质量跑一段包含回环的数据看回环闭合之后墙面对不齐。如果外参差几度地图很可能在闭合处有几厘米到十几厘米的错位。第二是用evo工具做轨迹评估。如果你的系统有GPS、动捕系统或者cartographer的高精度轨迹作为真值可以对比LIO-SAM里程计输出与真值的绝对轨迹误差。evo的安装和使用非常直接pip install evo evo_ape tum groundtruth.tum lio_sam_odometry.tum如果外参正确里程计轨迹的APE应当显著低于未标定时的结果。我见过一个项目标定前APE误差在20厘米以上标定后降到5厘米左右数据非常直观。3.5 手动微调当工具标定结果还不够好怎么办lidar_align这类自动工具在大多数场景下能给出不错的初值但有些传感器组合或运动环境下优化结果仍有偏差。这时候可以做一个简单的手动迭代先固定一个外参初值跑LIO-SAM观察地图如果地图朝某个方向倾斜或旋转就按对应方向微调外参重复几次。这个方法比较费时间但非常实用。关键是一次只调一个变量先调旋转再调平移先调roll再调pitch最后调yaw。如果一次改了好几个参数地图变了也不知道是哪个参数导致的。4. 成功跑通LIO-SAM之后的参数调优与效果评估4.1 params.yaml里的关键参数到底怎么读外参回填之后LIO-SAM并不是就万事大吉了。params.yaml里还有一组参数直接决定系统性能我也在这里做一个梳理。voxelLeafSize: 0.5 imuAccNoise: 3.9939570888238808e-03 imuGyrNoise: 1.5783679948825181e-03 imuAccBiasN: 6.4356659353465690e-05 imuGyrBiasN: 3.5640318696367613e-05voxelLeafSize是降采样体素尺寸。这个值太小点云数量太大CPU消耗飙升太大特征被抹平匹配精度下降。室内场景我一般从0.5起步室外大场景可以调到1.0到2.0。IMU相关的四个噪声参数来自imu_utils标定结果描述的是IMU本身的噪声密度和随机游走。这些值如果标定得准LIO-SAM对IMU的置信度就比较合理预积分和因子图优化的权重分配也更可信。4.2 启动顺序与话题流检查LIO-SAM启动后正常情况能看到多个线程在跑特征提取、scan-to-map匹配、IMU预积分。启动命令很简单roslaunch lio_sam run.launch但启动之前要保证雷达和IMU话题已经发布否则LIO-SAM会一直等待输入。启动之后用rqt_graph查看节点和话题连接是否正常尤其确认pointcloud和imu数据确实进入了lio_sam节点。如果启动后map发布频率很低建图原地踏步大概率是CPU算力不足或voxelLeafSize设置过小。可以先降低点云频率或者在录制好的bag上测试不同参数组合再回到实机上使用。4.3 调参经验多快好省的组合拳很多人在LIO-SAM跑通之后会陷入一种状态觉得地图不够准但不知道调什么。我的经验是分三步走。第一步先确认外参和IMU内参没问题这一步上面已经聊过外参不对调什么都白搭。第二步调voxelLeafSize和匹配阈值。先从小体素开始慢慢增大观察匹配耗时和地图清晰度找到曲线拐点。第三步调回环检测相关参数。如果你的场景经常出现回环但回环优化后地图反而更差很可能是回环检测过于敏感把错误的位置当成了回环。这种情况可以通过降低回环检测频率、提高帧间匹配的分数阈值来过滤。4.4 用evo量化标定前后的误差对比我建议每个项目都应该把标定前后的轨迹误差记录下来形成数据档案。尤其在对外汇报项目进度时一组标定前APE 0.35米、标定后APE 0.08米的数据比一百句我们的系统精度提高了都更有说服力。操作方法是把同样的bag分别用标定前和标定后的参数跑两遍输出轨迹然后用evo对比。evo_ape tum gt.tum before.tum -a evo_ape tum gt.tum after.tum -a如果手头没有真值轨迹可以用多个回环闭合点作为参考量地图中的特征点之间的距离和实际物理距离做对比。这个土办法在开放路面也够用。5. 避坑指南标定和跑通LIO-SAM过程中踩过的大坑5.1 时间戳不同步大家以为没事但后果很严重LIO-SAM对IMU时间戳和雷达时间戳的同步有一定容忍度但容忍度不等于零。时间戳偏差过大会导致IMU预积分的参考时间和雷达帧时间错位表现是轨迹出现周期性抖动、地图边缘出现毛刺。我遇到过一次IMU驱动使用系统时间雷达驱动使用设备内部时钟两者差了将近200毫秒跑出来的地图在小范围拐弯时经常漂移。解决方式是在驱动层面统一时间戳来源或者在录制bag时将传感器时间同步的机制打开。录制标定数据时也建议加上/tf和/tf_static这样后续调试时可以通过TF树快速定位坐标变换问题。5.2 退化场景导致标定发散这是一个很难从程序日志发现的坑。lidar_align在标定过程中依赖点云配准来估计雷达运动如果把设备放在一个狭长走廊或者白墙环绕的房间里配准容易退化外参优化也跟着发散。我建议数据采集时选择有明显几何特征的环境比如室内桌椅、货架区域或者室外有树木、电线杆的场地。运动过程中适当加入一些俯仰和滚转动作不要只走平面轨迹否则roll和pitch这两个自由度几乎没有可观测性标定出来的旋转矩阵在这两个方向上不可信。5.3 点云畸变和去畸变问题旋转式激光雷达在扫描过程中雷达自身也在运动导致一帧点云里的点不是同一时刻采到的。LIO-SAM内部利用IMU做去畸变但如果外参不准去畸变方向就错了效果甚至比不去畸变更差。判断是否有这个问题的办法是看雷达静止时的点云如果静止墙面在点云里出现拖影说明去畸变可能有问题。另外如果雷达是固态雷达扫描机制和旋转式不同畸变模型也不一样标定思路要相应调整。5.4 GTSAM和PCL版本问题导致的重新编译这部分在第二章详细说过这里再补充一个现象如果你在编译LIO-SAM时遇到形形色色的undefined reference错误大概率是GTSAM版本和LIO-SAM源码接口不匹配而不是你的CMake配置有问题。先检查GTSAM版本再检查LIO-SAM的commit版本两者最好和官方README保持一致。我在新环境里复现LIO-SAM的速度已经降到20分钟内就是因为把这套版本对应关系固定下来了。建议把环境依赖和版本写进项目的README而不是靠记忆。5.5 坐标系约定的各种隐藏陷阱ROS社区里激光雷达坐标系通常是x向前、y向左、z向上IMU通常也是x向前、y向左、z向上但并非所有硬件都遵循这个约定。比如某些工业IMU默认z轴向上但加速度计方向的定义可能和ROS的REP-103不完全一致。如果标定结果看起来正确但地图始终存在一个固定的旋转偏移很可能是传感器坐标系本身的轴方向和ROS标准不一样。解决办法是在驱动节点里把原始数据转换到ROS标准坐标系下再做标定。不要试图用一个万能外参来补偿所有坐标系定义差异那样后期维护会非常痛苦。5.6 一个很不起眼但常见的坑IMU频率不足导致预积分失败有些便宜的IMU模块最高只有50Hz输出而LIO-SAM对IMU频率的要求通常建议在100Hz以上。频率太低IMU预积分对载体运动描述的精度会下降尤其在快速旋转时角速度积分误差会迅速放大。如果你的IMU只有50Hz可以尝试提高雷达帧率来补偿或者在运行LIO-SAM之前用插值把IMU数据升频到100Hz。插值虽然不能增加物理信息但至少能让时间对齐更平滑。不过更推荐的方式是换一块更高输出频率的IMU硬件省很多麻烦。5.7 最后一个经验标定结果要建立可复现的数据档案把标定工具的输出参数、LIO-SAM中的配置文件、当时的bag数据全部打包存档。每次改动硬件或换传感器之后重新标定并记录变化。我踩过的最深的一个坑是某次项目交付时同事反映地图精度下降排查了一整天才发现是因为传感器被拆下重装过外参已经变化但配置文件里还是旧的外参参数。如果没有版本管理这种问题很容易演变成通宵排障的事件。给传感器模组加一个清晰标签或者在机器人启动脚本里把外参文件按硬件序列号索引都能有效避免这个坑。个人的经验是激光雷达与IMU联合标定这件事没有一劳永逸只有一遍一遍把流程做扎实。每一次标定文档记录、参数回填和效果验证都是在为后续更复杂的算法开发打地基。如果你现在也被外参不准折磨得头疼不妨照着这个流程完整走一遍应该能少走不少弯路。
返回列表