ARTICLE DETAIL

资讯详情

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

Lidar-IMU外参标定实战:基于lidar_align的完整流程与排错指南

Lidar-IMU外参标定实战:基于lidar_align的完整流程与排错指南 先说点掏心窝的话。搞过激光雷达SLAM、做过多传感器融合的兄弟大概率都被Lidar与IMU之间的外参折磨过。外参这个东西你平时感觉不到它的存在可只要它稍微偏上那么一点点——旋转多个0.1度、平移多个一两厘米——你建出来的地图就开始分层、重影里程计轨迹开始飘。更难受的是很多做上层算法的人默认外参是准的结果系统出了问题怎么都排查不到这一层最后定位到标定问题时项目周期已经浪费掉两三个礼拜了。我当年第一次跑lidar_align也是一路踩坑过来所以干脆把整个流程、原理、坑点全部整理成一篇能直接照着操作的文章。不管你是刚入行的视觉SLAM工程师还是搞机器人底盘、自动驾驶感知的从业者只要手上有激光雷达和IMU的组合这篇内容都能帮你少走不少弯路。这篇文章里我要做的事情很明确结合开源工具lidar_align把Lidar-IMU外参标定的原理讲清楚把从环境配置、数据采集到结果验证的完整实操流程走一遍再把那些文档里从来不写的坑一个一个挑出来。我尽量把这些年的经验和踩坑记录浓缩成一段一段可以直接抄作业的内容你看完完全可以拿自己手头的数据试一遍。1. 先把背景说清楚Lidar-IMU外参标定到底在标什么1.1 传感器坐标系之间的固定桥梁到底有多重要想象一下这个场景。一个移动机器人或者一辆测试车上激光雷达装在车顶IMU装在底盘或者更靠近质心的位置。传感器各自测量各自的数据雷达输出一帧一帧的点云IMU输出高频的角速度和加速度。后续要做的事通常是把两者数据融合起来——比如用IMU做运动补偿来矫正雷达点云畸变或者用雷达点云辅助IMU做零偏估计。不管用在哪一步前提都是你得能回答一个问题雷达坐标系里的某个点在IMU坐标系下的坐标是多少这就是外参的含义。它由两部分组成一部分是旋转矩阵R描述两个坐标系坐标轴之间相对旋转了多少另一部分是平移向量t描述两个坐标系原点之间在三个方向上的相对位移。学名都听过就叫Lidar相对于IMU的外参有的文献写成T_imu_lidar有的写成T_lidar_imu顺序不同实现起来差很多这个后面细说。数学上如果雷达坐标系下的一个三维点写为p_lidar那么它转换到IMU坐标系下的坐标是p_imu R * p_lidar t。R和t加起来总共6个自由度看着不多但想靠尺子量或者CAD模型直接量出来基本不现实。雷达和IMU的外壳不在一个平面安装支架可能有加工误差设备批次不同也可能导致内部装配偏差所以最靠谱的办法就是通过算法用采集到的实际数据把R和t算出来。这就是Lidar-IMU外参标定要做的事情。1.2 外参不准系统会表现出哪些病症很多刚接触融合定位的工程师忙着调权重、调滤波参数却忽略了外参这个最基础的东西。外参不准确带来的问题不是某一个指标崩掉而是整体精度全面退化。我见过的典型病症大概是这三类第一类是点云的地图叠加重影。车开过一条街同一个路灯或者墙面在第一次经过和第二次经过时被点云描出了两条线要么是重叠出厚厚的一层要么是边缘毛刺特别明显看起来整个地图都是脏的。这种情况如果纯雷达SLAM定位漂移还能归咎于回环没闭合但融合IMU之后依然脏那大概率就是外参里面的旋转分量偏了。第二类是运动畸变补偿失效。因为激光雷达扫描一个周期要有时间比如机械式雷达一个scan大约100毫秒这个过程中车在动点云每一行发射时对应的传感器位姿其实不一样。常用做法是用IMU的角速度和线速度做一个插值把点云每一行都补偿到统一的帧上。如果外参旋转给错了IMU数据投影过去之后不匹配补偿出来的点云反而更扭曲不仅没有消除畸变还会把原先单纯的环境结构扭曲成类似扇形的形状。第三类是松耦合或紧耦合融合时视觉或者雷达位姿与IMU预测位姿互相打架。简单说就是系统里两个模块各说各话状态估计器不知道信谁最后输出轨迹呈现非常单调但持续性的弯曲看起来像是有偏置实际上极可能是外参里的平移分量在作怪。有这三类症状基本上就可以锁定外参问题的嫌疑。但要真正把外参数值标出来还是得借助工具。这就是接下来要介绍的主角。2. 为什么选择lidar_align原理、优势与适用场景2.1 lidar_align的核心原理是什么样的先交代清楚这里的背景。Lidar-IMU外参标定这个方向其实提出了很多算法有的基于标定板配合特定几何特征有的基于神经网络回归有的基于信息论准则。但开源、好用、被大范围验证过的工具里lidar_align是一个绕不开的名字。它由ETH Zurich的Autonomous Systems Lab开发本质上是一个基于连续时间轨迹优化的标定方法实现思路直观得多。它的做法可以拆成几步。第一步给一个外参初值这个初值可以很粗糙比如来自CAD图纸或者粗略测量只要方向大致对就行。第二步利用IMU测量的角速度和加速度通过积分得到每一时刻IMU在世界坐标系下的位姿轨迹。第三步根据外参把每一帧雷达点云从雷达坐标系变换到IMU坐标系再利用IMU轨迹把点云投影到世界坐标系下。第四步在一个滑动窗口内衡量点云与世界地图之间的配准残差以残差最小化为目标反过来调整外参和轨迹循环迭代最终收敛出精确的外参。这个思路体现了非常经典的多传感器一致性优化思想。IMU提供短时间内的运动约束雷达点云提供环境几何约束两者通过外参这个桥梁发生联系外参错了点云投影后的几何一致性就会变差优化算法把这个变差检测出来并反向修正外参。理论上比手拿角尺去比量、或者用一个粗劣的初值去做ICP要可靠得多。2.2 它相比于其他标定方式的优势在哪里很多人会问标定外参不是有标定板吗不是有一些手眼标定的方法吗为什么非要用lidar_align我的回答是分场景。如果激光雷达和IMU之间是一个确定的机械结构而且你只需要在一个固定平台上标定一次标定板法或者基于特定运动模式的离线方法问题不大。但现实里很多系统是分布式架构雷达在车顶、IMU在计算单元旁边中间还有减震结构每次重新安装就得重新标定。还有的机器人平台工作在野外、矿井、地下车库你根本找不到合适的标定板也不一定有良好的光照和平面环境给视觉方法用。lidar_align的强项恰恰在这里它不依赖任何特定的人工标定物只需要环境中有一定的几何结构比如墙面、地面、树干、路沿甚至是一些杂乱物体然后在运动过程中采集数据即可。这意味着工程现场、车载环境、户外场景都可以用。再有就是它同时优化雷达外参和IMU轨迹不会要求IMU轨迹预先非常准。这一点非常关键因为IMU本身有零偏、有噪声积分时间长了轨迹就飘很多方法都栽在这上面而lidar_align在迭代中像一个联合优化器一样持续修正轨迹等于把标定外参这件事和估计轨迹这件事放在同一个框架里解决鲁棒性高不少。2.3 这个工具有什么局限什么时候不要用它俗话说无功不受禄工具再强也有适用边界。lidar_align的局限性主要是三块。第一它假设环境中有足够的几何纹理如果在纯空旷的广场或者完全均匀的雪地上采集数据点云配准没有足够的约束标定结果就退化表现就是优化结果每次跑都不一样甚至明显不合理。第二它需要IMU和雷达在运动中充分激励各个轴通俗讲就是要转够弯、加够速、俯仰侧倾都要覆盖到如果全程匀速直线行驶很多参数不可观测标定自然不准。第三它对非重复扫描雷达的支持几乎没有很多早期版本只支持旋转式机械雷达像固态雷达、R-Fans这类非重复扫描的花样就得多做很多预处理。当然了这些都是搞标定的常识后面采集数据部分还会详细展开。3. 环境准备从零开始把lidar_align跑起来3.1 依赖项的安装与编译细节先交代一下我的环境Ubuntu 18.04 ROS Melodic这是lidar_align比较常见的运行环境。如果你用的是Ubuntu 20.04 ROS Noetic问题也不大很多人在上面也能编译过但个别老版本的依赖可能有坑后面避坑部分会细说。lidar_align本身依赖Open3D和PCL。Open3D这个库很关键它负责点云处理相关的部分。# 安装Open3D依赖 sudo apt install libeigen3-dev libflann-dev libvtk7-dev libqt5gui5 pip install open3dPCL在ROS里一般已经自带。如果ROS装上之后PCL相关的头文件找不到可以考虑单独安装sudo apt install libpcl-dev接下来就是正式下载和编译lidar_aligncd ~/catkin_ws/src git clone https://github.com/ethz-asl/lidar_align.git cd .. catkin_make编译过程中有一个非常经典的坑就是缺少Open3D相关的CMake路径报错可能长这样Could not find a package configuration file provided by Open3D原因很简单Open3D的CMake包没有装到系统目录或者pip安装的版本没有生成CMake配置文件。解决思路是把Open3D从源码编译并安装这样才能在编译lidar_align时被正确找到。具体做法是找到Open3D源码目录然后cd Open3D mkdir build cd build cmake -DBUILD_SHARED_LIBSON -DCMAKE_INSTALL_PREFIX/usr/local .. make sudo make install编译完成后把lidar_align/CMakeLists.txt里的Open3D相关路径核对一遍即可。这一套下来基本就能过了。3.2 需要准备的数据格式与话题约定lidar_align通过ROS的bag文件读取数据。你需要提前把采集好的雷达和IMU数据录制为一个bag至少包含两类话题雷达话题/points_raw 或 /velodyne_points 这类消息类型为sensor_msgs/PointCloud2IMU话题/imu/data 这类消息类型为sensor_msgs/Imu需要注意bag里还可以有其他话题但这两个必须有。lidar_align默认订阅的雷达话题是/points_rawIMU话题是/imu/data。如果你的话题名字不一样可以打开代码里的launch文件或者源码配置文件把对应的订阅话题名改掉。launch文件里一般会设置雷达帧和IMU帧的名字比如lidar_link和imu_link这两个名字在后续输出外参的时候只是当作文字标签用实际标定结果的物理含义取决于坐标系的朝向和安装关系只要保证代码里的tf树和实际一致即可。4. 数据采集这一步决定了标定的上限4.1 环境怎么选运动怎么规划先说结论数据采集的重要性不亚于优化算法本身甚至可以说标定效果上限是由数据决定的算法只是尽可能逼近这个上限。我见过不少人下载了lidar_align兴冲冲跑了一个半小时车回来一看标定失败问题十有八九出在采集数据上。环境选择上尽量找有丰富几何特征的空间。地下车库就极好立柱、墙面、地面标线、停在旁边的车全是满满的结构信息。走廊、街道两侧有连续建筑立面和树木也是不错的选择。避开的地方包括没有任何遮挡的大广场、完全水平且空旷的停车场顶层、大雪覆盖的野外。这些环境点云配准约束不够结果飘。运动规划上主要是要满足可激励性。翻译成大白话让机器人把六个自由度方向上的运动都表现一遍。不要只是匀速直线跑要在合适的速度下转弯、刹车、加速如果有条件可以做8字形绕圈并且在开始和结束时原地旋转几圈。这里特别强调一点采集过程中要有意识的产生俯仰和侧倾。很多车辆平台不方便做这种动作但如果你做的是带机械臂的移动机器人或者手持设备可以在采集过程中晃一晃设备让滚转、俯仰方向有足够的角速度激励。标定的可观测性就跟这些运动相关哪一轴缺激励哪一轴的外参就容易不准。4.2 采集时长、频率与数据量怎么设置时长的建议是至少采集3到5分钟数据量不要太小。lidar_align采用滑动窗口优化太短的bag数据里面有用的约束太少。我实测下来如果车速保持在5到10km/h绕着一个中型地下车库跑五六分钟数据量就足够了。如果场地太大可以分两段采集一段用于标定一段用于验证。IMU频率一般要在100Hz以上常见的200Hz最佳。激光雷达频率10Hz即可。bag录制命令用rosbag record建议把雷达和IMU话题都录进去同时再录制一份GPS或者轮式里程计话题作为后期验证参考。如果你手头用的雷达是机械式16线或者32线注意确认雷达的内参旋转中心、零度方向是准确的这一点会影响点云本身但跟外参标定是两回事。4.3 采集时IMU数据质量要如何保障IMU数据质量对外参标定影响极大。采集时务必保证IMU没有大幅饱和或者剧烈噪声。有一种常见问题就是IMU的陀螺仪量程设置太小转弯稍一急就砍顶数据直接废掉。所以在采集之前先手动转动设备几次到Rviz或者Plotjuggler里看一眼IMU角速度输出有没有削顶现象。如果有就先把IMU量程设置调大再采集。还有一个容易忽视的点就是IMU的采样时间戳要和雷达对齐。lidar_align默认认为IMU和雷达消息的时间戳是在同一个时基下所以录制bag时最好把两个话题都用同一个时钟源。用rosbag record默认就是收到数据时打上当前机器时间一般两个传感器驱动都在同一台主机上跑时基一致问题不大。但如果你是通过网口从不同设备接收数据就得确认时间同步不然标定出来的外参会把时间延迟也吸收进去表现为旋转平移用量很怪。5. 配置参数与运行标定手把手走一遍流程5.1 launch文件和参数含义逐个拆解进入工作空间先看一下lidar_align的launch文件长什么样。一般放在lidar_align/launch目录下我以常见的那个lidar_align.launch为例里面有这几个关键参数launch node pkglidar_align typelidar_align namelidar_align outputscreen param namebag_file value/path/to/your/calibration.bag / param nameimu_topic value/imu/data / param namelidar_topic value/points_raw / param nameoutput_tf valuetrue / param namevisualize valuetrue / /node /launchbag_file指定你要标定的数据包路径。imu_topic和lidar_topic分别指定话题名话题名如果不对程序会一直卡在等待数据的状态注意看控制台输出。visualize如果置为true会打开一个可视化窗口你可以实时看到点云匹配的效果。output_tf控制是否输出一个tf变换方便在Rviz里检查。还有一个参数藏在源码里叫做number_of_frames或者window_size用来控制每次优化时取多少帧雷达点云参与计算。默认值可能比较小如果数据包很长可以适当增大这个参数让它覆盖更多帧标定结果会更稳定。但反过来窗口太大每轮迭代计算量会指数级增长。我对自己的数据集一般是在保证单次迭代不超过几十秒的前提下尽量把这个窗口调大一些。5.2 外参初值的给法怎么给才不容易陷入错误收敛这是整个流程里最容易出问题的环节也是很多人标定失败的元凶。lidar_align虽然是优化算法但它本质上还是非凸优化需要一个合理的初值。当初值给得明显离谱比如旋转差了几十度优化过程很容易直接发散或者收敛到错误的局部极小值。常见的做法有三步。第一步查产品手册或者CAD图纸把雷达和IMU安装位置之间的粗略尺寸量出来平移初值精度在5cm以内最好。第二步根据安装朝向判断旋转初值。比如IMU的坐标系通常定义为x轴前向y轴左向z轴朝上而很多雷达是x轴朝向某个固定的零度角需要你根据实际安装把两者之间的旋转关系转成欧拉角填进去。第三步如果完全没有任何参考也可以先给一个单位旋转、零平移然后通过直观观察点云对齐效果去手动微调找到一个大致的对齐状态后再交给优化器。这里有一个重要的技巧不要直接关闭优化旋转或者平移的任意一个自由度。有些版本代码里提供了锁旋转或者锁平移的选项一开始图省事只优化旋转得到结果后再优化平移。这样做在小误差情况下可行但如果初始误差大旋转错了仅仅优化平移永远找不到正确的解因为旋转残差会映射到平移上。我的经验是先手动对齐到肉眼看起来点云大致不重影的程度然后让算法同时优化R和t。5.3 运行标定的过程与观察技巧配置好launch文件后终端运行roslaunch lidar_align lidar_align.launch程序会逐步读入bag数据并打印每一轮优化的cost值。正常情况下cost值会呈现一个先快速下降、后缓慢收敛的过程演变过程可以理解为点云对齐程度在持续变好。cost值如果出现震荡或者不断增大基本可以认定数据有问题或者初值太差。可视化窗口里你观察的点是不同帧之间的点云是否能够紧密贴合成一个完整体。如果外参收敛你会明显感觉到原本错位的地图块慢慢拼接到了一起轮廓变得清晰锐利。如果没有明显改善甚至更乱就要考虑停止程序排查数据或初值问题。运行过程中控制台还会打印一个变换矩阵这个矩阵就是把雷达点云变换到IMU坐标系下的外参矩阵。当cost收敛时取最后输出的这个矩阵即可。我记得lidar_align在跑完数据包后会把结果保存成一个名为lidar_align_result.tf之类的文件你也可以直接用命令行读出来。6. 标定结果怎么看怎么判断好坏6.1 读懂输出矩阵和优化日志拿到最终输出的4x4变换矩阵第一个要做的就是做一次物理合理性检查。什么意思就是你大致估算雷达装在IMU前方还是后方、上方还是下方平移向量应该跟实际安装位置基本一致且方向正确。举个例子雷达在IMU前方0.2m、上方0.1m处那么平移向量应该大约是[0.2, 0, 0.1]的量级。如果算出来平移是[-1.2, ...]这种完全不符合常识的数那结果大概率有问题。旋转矩阵部分可以转换成欧拉角看一眼角度量级合不合理。如果安装方式是IMU与雷达都水平朝前旋转角应该接近零即便有偏差一般也在几度以内超过十五度就要谨慎说明某个环节没对上。6.2 做一次验证把外参用起来看效果标定结果不是打印出来就完事的。我强烈建议做一次完整的验证方案有两种简单高效。方案一用标定出来的外参做一次离线点云拼接。把bag里的雷达点云逐帧投影到世界坐标系观察建出来的地图是否干净锐利。如果地图锐利、边缘清晰基本证明外参是准的比看任何指标都直观。方案二在rosbag回放时加载标定后的tf然后跑一个基础的融合定位算法比如基于LOAM的框架对比融合定位轨迹和纯雷达里程计轨迹。外参正确时融合轨迹的全局一致性会有明显提升尤其是转弯处不再出现轨迹弯曲或者漂移。动手验证这一步千万别省因为它能帮你区分数值上收敛和实际物理正确这两个完全不同的概念。一个数值收敛但错误的外参优化过程同样可以打出很低的cost但用起来会原形毕露。7. 常见问题与排错经验这些年踩过的坑一次讲完7.1 编译阶段的各种怪问题问得最多的问题就是Open3D相关的编译报错我在前面已经提到了解决办法。还有一个常见情况是升级了ROS Noetic之后pcl_ros和open3d之间出现ABI冲突表现是编译通过但运行直接段错误。这种问题很难查往往跟库版本有关。我的建议是如果遇到先别急着在Noetic上死磕用Docker包一个Melodic环境跑完标定再把外参文件带出来省心省力。还有一种情况是bag文件里的雷达消息类型不是sensor_msgs/PointCloud2而是自定义类型比如Livox的livox_ros_driver/CustomMsg。这种情况下lidar_align直接不认你需要先写一个转换节点把自定义消息转成PointCloud2再录成bag或者实时转发。7.2 标定结果不对劲收敛了但明显错误这类问题最让人头大。我遇到过的情况是这样的cost收敛得很好可视化窗口里看起来点云也对齐了但平移量的输出跟实际安装差了10厘米以上。最后排查出来的原因是IMU的零偏没有处理干净导致IMU轨迹整体发生缓慢漂移而优化器为了让点云对齐会把一部分轨迹误差补偿到外参上形成一个在数学上等价、在物理上不对的解析解。针对这种情况如果平台允许可以尝试在开始和结束时保持静止一段时间。这样IMU在静止段里可以得到零速修正轨迹漂移的影响能降下来。如果数据已经采完无法重采也可以在跑标定之前先用imu_utils之类的工具估计并补偿IMU零偏再喂给lidar_align效果也会有明显改善。还有一类问题是标定结果每次运行都不一样。这是典型的约束不足或者初值敏感。你可以尝试换一个更有结构性的环境重新采集数据或者在优化窗口里把参与点云帧数调大一些。如果依然不稳定说明当前数据里外参的某些自由度不可观建议增加俯仰或者侧倾方向的运动激励而不是盲目加大数据量。7.3 避坑清单一张表帮你快速定位问题现象可能原因解决方向编译报错找不到Open3DOpen3D未安装或CMake路径未配置源码编译Open3D并安装至系统目录程序启动后一直等待数据bag路径不对或话题名不匹配检查launch里的bag路径和话题名Cost值不下降或震荡外参初值太差/数据激励不足调整初值重新采集含多方向运动的数据标定结果与安装常识不符IMU零偏严重/时间戳不对齐静止段补偿零偏检查时间同步每次跑结果都不一样环境约束不足/优化窗口太小换结构化环境增大窗口帧数可视化点云重影但收敛外参局部最优/初值错误手动粗对齐后再交给优化器7.4 一些提升成功率的进阶技巧再分享几个不太被注意但很管用的小细节。第一个如果条件允许在采集bag之前先录一小段静态数据让雷达和IMU在完全不动的状态下持续工作二三十秒。这段数据虽然不参与标定但可以用来做IMU零偏的预估计也可以用来检查雷达话题里的点云是否在静止时保持稳定。第二个在把数据喂给lidar_align之前把bag文件压缩一下或者只保留标定需要的两个话题。拿大几十GB的原始bag直接跑光是读数据就能把你心态整崩。第三个如果你的雷达是固态或者非重复扫描型号即使lidar_align不能直接处理你也可以通过累积多帧点云凑出一个伪旋转式扫描的数据形态再尝试。不过说实话这个操作比较折腾效果也看运气我一般更推荐直接用厂商自带的标定工具或者基于NDT匹配的自研标定。第四个如果标定完还是觉得精度差点意思可以再跑一遍这次以上一轮输出作为初值数据也用新采的一组形成一个迭代式标定流程。很多团队的标定结果就是这么慢慢磨出来的。我在实际使用中还有一个习惯就是每标定一次都会把完整的外参变换矩阵连同验证结果截图存到工程目录里标注好传感器型号、安装方式、采集环境和日期。这样后续如果发现系统状态有变化可以快速定位到底是外参漂了、传感器松动还是算法改动引入的新问题。这个习惯帮我省了不少排查的力气推荐你也养成。关于lidar_align其实能聊的细节还有很多。比如它内部如何维护点云体素地图、如何做残差项的鲁棒核函数配置这些在代码里都有对应的可调参数。等你有了一批成功标定的数据集再回过头去啃这些源码结合论文一起看会有更深的理解。外参标定这个东西技术上不难难的是把每个环节都做得干净、扎实。我的经验是数据采好、初值给好、验证做好整个流程跑通就是水到渠成的事。希望这篇内容能让你少踩一些我已经踩过的坑。
返回列表