ARTICLE DETAIL

资讯详情

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

LIO-SAM在Ubuntu 20.04与ROS Noetic下的编译指南

LIO-SAM在Ubuntu 20.04与ROS Noetic下的编译指南 作为一个常年跟激光SLAM算法打交道的人我深知LIO-SAM这套代码的含金量。它是Tixiao Shan在LEGO-LOAM基础上迭代出来的作品核心思路是把激光雷达、IMU和GPS可选通过因子图做紧耦合在实时性和精度之间取得了很好的平衡而且代码量不大非常适合拿来学习多传感器融合的工程实现。不过很多人在Ubuntu 20.04 ROS Noetic环境下编译LIO-SAM时会踩到不少坑尤其是GTSAM版本、PCL/OpenCV版本冲突这类问题网上资料虽然多但真正能一次性跑通的教程却不多。这篇文章我就把LIO-SAM在Noetic下从零编译到跑通demo数据集的完整过程梳理一遍把我踩过的坑和验证过的方案都写清楚给需要的人省点时间。先说结论LIO-SAM在Ubuntu 20.04 Noetic下是完全可以编译通过的核心难点不在代码本身而在依赖库版本的选择上。只要把GTSAM、PCL、OpenCV这几个关键依赖的版本和编译顺序处理好整个编译过程其实很顺。1. 编译前的全局思路与方案选型1.1 为什么推荐用Ubuntu 20.04 Noetic来跑LIO-SAM虽然LIO-SAM的作者最初是在Ubuntu 18.04 Melodic环境下开发测试的但如今Ubuntu 20.04 Noetic已经成为ROS生态的主流组合特别是Noetic是最后一个完全基于Python 2官方支持的ROS版本说反了恰恰Noetic是第一个默认使用Python 3的ROS发行版这意味着大量新工具链和新算法库都在这个版本上做了适配生态更健康后续做扩展开发也方便。但问题也随之而来Noetic自带的PCL 1.10、OpenCV 4.2以及Eigen 3.3.7等库和LIO-SAM在18.04环境下依赖的旧版本库有细微差异。这会导致编译过程中出现各种类型不匹配、函数签名改变、头文件路径缺失等报错。所以编译前搞清楚各依赖库的版本对应关系比盲目改代码重要得多。我整理了一张常见的环境组合对比表可以直观看到差异依赖项Ubuntu 18.04 Melodic 默认Ubuntu 20.04 Noetic 默认说明PCL1.8.11.10.0头文件路径有变化部分API弃用OpenCV3.2.04.2.0部分旧API需要兼容处理Eigen3.3.43.3.7差异不大基本兼容gtsam需要自行编译需要自行编译LIO-SAM核心后端优化库ROS底层MelodicNoetic消息接口基本一致实际编译时PCL和OpenCV的API变化是主要的坑点后面我会专门讲。1.2 编译策略的确定先攻依赖再战源码LIO-SAM编译失败的案例里绝大多数不是因为LIO-SAM源码本身有问题而是GTSAM没有编译好或者GTSAM与PCL的冲突没有处理好。GTSAM是Georgia Tech开发的因子图优化库LIO-SAM用它来实现位姿图优化是后端的关键依赖。因此整个编译路线应当按照系统依赖 → ROS基础包 → 算法依赖库 → LIO-SAM功能包的顺序分层推进。这个顺序是有讲究的先确保系统的包管理器装好基础库再用源码方式编译GTSAM最后才编译LIO-SAM本体。如果反过来先编译LIO-SAM再处理GTSAM你会陷入报错→改代码→又报错→重新编译的循环里非常浪费时间。2. 依赖环境搭建与核心库编译实操2.1 系统与ROS基础环境的准备首先你需要一台装了Ubuntu 20.04的机器。如果是双系统或者虚拟机需要注意分配足够的磁盘和内存我建议至少分配4核CPU和8GB内存否则编译C工程时会比较吃力特别是在编译GTSAM这种模板库时内存不够很容易被系统OOM杀死。然后是ROS Noetic的安装这里我默认你已经完成了ROS Noetic的安装和rosdep的初始化。如果没有安装请参考ROS官方Wiki的安装步骤先安装Desktop-Full版本因为Desktop-Full自带RVIZ、TF树可视化工具和常用消息包后面跑demo数据包时都会用到。需要注意的一点是Noetic推荐使用Python 3环境如果之前切换过Python版本要注意保证ROS工具链能正常运行可以用roscore快速验证一下。rosdep初始化记得要做好因为后续编译过程中catkin会通过rosdep检查功能包的依赖是否齐全。如果rosdep没有update成功编译时会出现Unable to resolve dependencies的提示。2.2 核心依赖库的安装与版本匹配在开始编译LIO-SAM前要把这些系统依赖库装齐sudo apt-get install -y \ ros-noetic-pcl-ros \ ros-noetic-velodyne-msgs \ ros-noetic-rviz \ ros-noetic-tf2-geometry-msgs \ ros-noetic-cv-bridge \ libeigen3-dev \ libopencv-dev \ libpcl-dev \ libyaml-cpp-dev \ libgflags-dev \ libgoogle-glog-dev \ libtbb-dev这里重点说说PCL和OpenCV。Noetic自带的libpcl-dev版本是1.10。LIO-SAM源码里imageProjection.cpp和featureExtraction.cpp等文件大量使用了PCL的点云类型和滤波功能这些在1.10版本下基本都能编译通过但有一个需要注意的地方pcl_conversions的头文件路径和消息转换接口在ROS版本间有调整必须保证编译时能找到pcl_conversions/header.h否则会出现找不到头文件的错误。OpenCV则需要注意cv_bridge的版本匹配问题。Noetic自带的cv_bridge默认针对OpenCV 4.x编译LIO-SAM中visual_feature.cpp如果启用视觉特征可能会使用OpenCV的特征提取接口这些接口在OpenCV 4.2中统一到了opencv2/features2d.hpp中不再推荐使用旧的opencv2/xfeatures2d/nonfree.hpp。所以只安装libopencv-dev即可不需要额外安装OpenCV 3的兼容包。安装完基础依赖后用下面命令验证关键版本的匹配情况pcl-config --version pkg-config --modversion opencv4 pkg-config --modversion eigen3正常输出的版本号应该分别是1.10.0、4.2.0和3.3.7。2.3 GTSAM源码编译整个流程中最关键的环节GTSAM的编译是LIO-SAM编译成功与否的分水岭。LIO-SAM官方推荐的GTSAM版本是4.0.2。这个版本经过了LIO-SAM作者的验证稳定性最好。网上有人说4.0.3也能用确实能编译通过但有个坑是4.0.3在部分Ubuntu 20.04版本的Boost库下会出现模板实例化的问题虽然概率不高但一旦遇到排查起来非常痛苦。我的建议是不要冒这个险直接从GitHub拉取4.0.2的tag。具体编译步骤如下cd ~ git clone --branch 4.0.2 https://github.com/borglab/gtsam.git cd gtsam mkdir build cd build cmake -DGTSAM_BUILD_WITH_MARCH_NATIVEOFF -DGTSAM_USE_SYSTEM_EIGENON -DGTSAM_BUILD_TESTSOFF -DGTSAM_BUILD_UNSTABLEON .. make -j$(nproc) sudo make install这里有几个关键参数我要特别说明GTSAM_BUILD_WITH_MARCH_NATIVEOFF这个参数非常关键。如果设置为ONGTSAM在编译时会根据当前CPU的指令集做针对性优化这意味着编译生成的二进制文件只能在你当前这台机器上运行。如果你后续要把编译好的代码拷贝到其他机器或者与其他库混用就会出现非法指令illegal instruction的错误。在编译LIO-SAM所依赖的算法库时我统一建议关掉这个选项提升可移植性。GTSAM_USE_SYSTEM_EIGENON让GTSAM使用系统已安装的Eigen而不是自己捆绑的Eigen版本。这一步能有效避免“Eigen对齐冲突”这类经典的编译错误。Eigen是一个模板库它内部使用了大量固定大小的向量化内存对齐如果同一个程序里使用了不同版本的Eigen头文件会直接导致各种奇怪的段错误或编译报错。统一使用系统Eigen是消除这类问题的根本手段。GTSAM_BUILD_UNSTABLEONLIO-SAM的IMU预积分因子部分实际上依赖了GTSAM的Unstable模块所以这个选项必须打开否则编译LIO-SAM时会出现找不到ImuFactor相关头文件的错误。编译GTSAM的时间取决于CPU性能一般10分钟到半小时不等。编译完成后执行sudo make installGTSAM的库文件会被安装到/usr/local/lib头文件到/usr/local/include/gtsam这些路径后续编译LIO-SAM时需要cmake能找到。安装完成后建议验证一下GTSAM的版本信息ls /usr/local/include/gtsam/base/Vector.h能列出这个文件就说明GTSAM的基本头文件已经就位。2.4 一个需要提前确认的依赖Ceres SolverLIO-SAM本身不强制依赖Ceres但很多基于LIO-SAM改造的项目比如LIO-SAM-Map优化、激光-视觉联合标定流程会用到Ceres做BA优化。如果你只是跑LIO-SAM原生代码Ceres可以不装。但如果你是做SLAM方向的研究后续大概率会用到我建议顺手把Ceres也装好避免之后用到时再回头补环境。Ceres的源码编译在Ubuntu 20.04下比较顺畅sudo apt-get install -y libceres-dev也可以选择源码编译最新版本但系统源里的Ceres版本对LIO-SAM相关项目来说完全够用源码编译反而可能因为依赖冲突浪费时间。实测下来Ubuntu 20.04自带的Ceres 1.14版本在后续标定项目中表现稳定。3. LIO-SAM源码编译与demo数据包运行实录3.1 工作空间的创建与源码拉取依赖库就位后就可以创建ROS catkin工作空间了。我习惯把所有算法的代码统一放在~/catkin_ws/src下这样方便维护也方便和后续其他功能包交叉引用。mkdir -p ~/catkin_ws/src cd ~/catkin_ws/src git clone https://github.com/TixiaoShan/LIO-SAM.git cd ~/catkin_ws catkin_make这里的catkin_make会报错吗第一次直接运行catkin_make一般会失败因为工作空间里只有LIO-SAM一个功能包而且它会去查找GTSAM等依赖。报错信息通常会在CMake阶段就中止提示找不到GTSAM。这是因为GTSAM安装到/usr/local后LIO-SAM的CMakeLists.txt中find_package(GTSAM COMPONENTS ...)需要能搜索到/usr/local/lib/cmake/GTSAM路径。如果遇到找不到GTSAM的情况可以手动设置环境变量export GTSAM_ROOT/usr/local或者干脆在~/.bashrc中加上export GTSAM_ROOT/usr/local export LD_LIBRARY_PATH/usr/local/lib:$LD_LIBRARY_PATH然后source一下使得环境变量生效。3.2 编译过程与关键参数调整重新打开一个终端进入工作空间执行以下命令cd ~/catkin_ws catkin_make -j4-j4是并行编译的线程数我这里故意保守一点用4线程因为LIO-SAM的源码里包含了几个比较大的模板类比如mapOptimization.cpp、imageProjection.cpp这些文件单文件编译内存开销比较大如果机器内存不足并行线程数开太高容易被系统杀掉。如果是16GB内存以上的机器用-j8也问题不大。整个编译过程通常会遇到一个警告就是using namespace Eigen;和某些第三方库的命名空间冲突但一般只是warning不会报错可以忽略。编译成功的标志是在~/catkin_ws/devel/lib/lio_sam/目录下生成四个可执行文件lio_sam_imageProjectionlio_sam_featureExtractionlio_sam_mapOptimizationlio_sam_imuPreintegration看到这四个节点文件就说明编译已经通过了接下来可以进行demo数据测试。3.3 demo数据集的运行与launch文件修改跑demo数据前需要先下载官方提供的rosbag数据集。LIO-SAM官方在GitHub的README里提供了一组Google Drive链接内容覆盖了各种场景我们选其中最常见的walking dataset为例来演示。下载好rosbag后需要修改LIO-SAM的launch文件中的参数配置。打开终端编辑~/catkin_ws/src/LIO-SAM/config/params.yamlgedit ~/catkin_ws/src/LIO-SAM/config/params.yaml重点修改以下内容useImuLoopClosure: true这里可以保持默认它控制是否启用IMU雷达的里程计回环检测。savePCD: false如果要保存地图点云改为true并设置savePCDDirectory为你的目标路径。注意这个路径必须是已存在的绝对路径否则程序运行时会直接崩溃不会给出任何友好提示。然后是launch文件中的参数调整打开~/catkin_ws/src/LIO-SAM/launch/run.launch检查以下两项点云话题名称数据集中的点云话题一般是/points_raw和launch文件里默认的/velodyne_points不同。需要把param namepointCloudTopic value/points_raw /改对。IMU话题名称数据集中的IMU话题一般是/imu_raw同样要检查是否匹配。改完之后启动三个终端终端1启动roscoreroscore终端2启动LIO-SAMcd ~/catkin_ws source devel/setup.bash roslaunch lio_sam run.launch终端3播放数据集rosbag play your_downloaded_dataset.bag播放之后RVIZ窗口会实时显示点云地图的构建过程。这里有个小技巧如果RVIZ里看不到地图先检查点云话题时间戳是否和系统时间同步。如果是下载的公开数据集时间戳是历史时间需要加上--clock参数让ROS使用bag中记录的时间rosbag play --clock your_downloaded_dataset.bag同时在run.launch中确认use_sim_time设置为true。这样TF树和各传感器的时间戳才能对齐。3.4 运行效果评估与地图输出运行结束后LIO-SAM会在控制台输出位姿轨迹信息和回环检测结果。如果一切正常你会看到回环检测报出多条“loop found”信息地图构建也非常平滑。此时如果设置了savePCD: true运行结束后在设定的目录下会生成map.pcd文件可以手动保存地图。我个人实操时用walking数据集在普通笔记本上i7-9750H 16GB内存 GTX1660Ti能保持30Hz左右的实时建图CPU占用率在80%左右说明LIO-SAM的轻量化特性确实名不虚传。4. 编译与运行中的高发报错与排查方案4.1 GTSAM相关的编译报错编译LIO-SAM时最常见的报错是/usr/local/include/gtsam/...: error: gtsam::PinholeCamera has not been declared这类错误九成原因是GTSAM版本不对或者GTSAM没有被正确找到。尤其是如果你系统里碰巧装了多个GTSAM版本比如通过apt装过ros-noetic-gtsam然后你又手动编译安装了4.0.2两者就会冲突。排查方法先查看/opt/ros/noetic/lib下是否有gtsam相关库文件。如果执行dpkg -l | grep gtsam能查到系统自带gtsam建议先卸载它sudo apt-get remove ros-noetic-gtsam然后再重新手动编译安装4.0.2版本。这个坑我踩过当时编译LIO-SAM时一直提示某些头部函数声明找不到后来源头是apt版GTSAM版本过旧和LIO-SAM期望的API版本不一致。4.2 PCL版本相关的编译报错在Ubuntu 20.04 Noetic环境下PCL 1.10相比PCL 1.8有一些接口弃用和改名。LIO-SAM源码中容易触发问题的是以下两个位置imageProjection.cpp中使用了pcl::PointCloudPointType::Ptr和pcl::transformPointCloud。这些在PCL 1.10下完全没有问题但如果出现“找不到PCLPointCloud2转换函数”这类错误说明pcl_ros的消息类型没有正确链接。解决方法是检查是否安装了ros-noetic-pcl-ros并在CMakeLists.txt中确认find_package(PCL REQUIRED)被正确声明。mapOptimization.cpp中调用了pcl::voxel_grid滤波和pcl::StatisticalOutlierRemoval滤波1.10版本中这些类的头文件路径变为pcl/filters/voxel_grid.h和pcl/filters/statistical_outlier_removal.h一般不会冲突。另外GTSAM和PCL同时使用时可能会出现Eigen::aligned_allocator相关的报错。这本质上是Eigen内存对齐引起的编译冲突解决方案已经在前面说过了保证GTSAM使用系统EigenGTSAM_USE_SYSTEM_EIGENON同时不要往任何加了EIGEN_MAKE_ALIGNED_OPERATOR_NEW的类里塞STL容器元素这属于Eigen的老话题了。4.3 OpenCV版本相关的运行时异常LIO-SAM默认不依赖视觉特征但如果你的项目中额外启用了visualFeature相关模块可能会遇到OpenCV 4.2下的API差异。最典型的问题是cv::solvePnP函数在多解时的行为变化以及在OpenCV 4下findEssentialMat默认使用RANSAC时抛出的异常。如果遇到这类运行时崩溃首先确认是否安装了libopencv-dev和ros-noetic-cv-bridge其次检查cv_bridge和OpenCV版本是否一致。Noetic默认的cv_bridge针对OpenCV 4编译如果你另外用源码编译了OpenCV 3那必然会产生链接冲突。这种情况下的解决方法只有一个保持系统标准版本不要动OpenCV。4.4 编译卡死或内存不足现象LIO-SAM的mapOptimization.cpp在编译时是出了名的吃内存。如果你使用的是虚拟机或者物理内存只有8GB那么catkin_make -j$(nproc)经常会导致编译进程被系统杀死表现为终端显示Killed字样。处理办法有两个方向降低并行编译线程数例如用catkin_make -j2让每个编译任务拥有更多内存。临时增加swap空间在/etc/fstab中配置一个swap文件或者直接用fallocate和mkswap创建一块临时swap来缓解物理内存不足。我个人实际测试8GB内存的机器用-j2编译LIO-SAM是完全能通过的只是时间会稍长一些大概多等10分钟而已。不要盲目追求编译速度稳定通过才是第一目标。4.5 运行时不建图或地图闪退问题排查运行LIO-SAM时最让人头疼的问题就是RVIZ中看不到点云或者地图稍微转两下就崩溃。这类问题通常不是编译造成的而是数据时间同步和TF坐标系设置的问题。用rqt_tf_tree命令检查TF树是否完整。LIO-SAM的正常TF树结构应当是map - odom odom - base_link base_link - sensor_link (通常是 velodyne 或 camera_init)如果map到odom的TF一直没有发布说明回环检测或者后端优化节点没有正常工作检查mapOptimization节点的输出日志。如果odom到base_link抖动剧烈则说明IMU数据处理有误检查imuTopic话题中的数据频率是否正常LIO-SAM要求IMU频率不低于100Hz如果只有50Hz需要调整参数或使用IMU内插数据。另外数据集的点云话题如果是/points_raw但你的launch文件里用的是/velodyne_points那么RVIZ中当然不会有任何点云因为节点根本就没有订阅到数据。用rostopic list查看当前话题列表用rostopic hz /points_raw查看话题发布频率这都是排查数据链路问题的基本功。4.6 常见问题排查速查表我把上边提到的坑整理成一个速查表方便以后排障时直接查阅问题现象可能原因解决方案CMake找不到GTSAMGTSAM未安装或未加入环境变量检查/usr/local/lib/cmake/GTSAM是否存在添加GTSAM_ROOT/usr/local环境变量编译时报Eigen对齐错误GTSAM使用了自带Eigen而非系统Eigen重编GTSAM加上-DGTSAM_USE_SYSTEM_EIGENONundefined reference togtsam::...GTSAM版本不对或与系统自带版本冲突卸载apt版GTSAM源码安装4.0.2运行时找不到/points_raw话题点云话题名称不匹配修改launch文件中的pointCloudTopic参数RVIZ无地图且无TF时间戳不同步播放bag时加--clock参数launch中设置use_sim_time: true编译时内存不足被Killed并行线程数过多或物理内存不足降低-j线程数或增加swap空间运行时崩溃Segmentation fault保存pcd的路径不存在确保savePCDDirectory路径存在且可写运行时报Invalid argumentIMU话题频率过低检查IMU话题数据频率重新录包或增加IMU数据率5. 编译成功后的功能扩展与二次开发方向5.1 从LIO-SAM到LIO-SAM-Map与语义SLAM一旦LIO-SAM在Noetic下成功编译和运行你就拥有了一个非常稳定的多传感器融合SLAM底座。最常见的扩展方向是LIO-SAM-Map这种引入大量历史帧进行大规模建图的变种。它和LIO-SAM的主要差异在后端优化策略后者保留更大的局部地图进行扫描匹配对内存和算力的需求更高但建图精度也会提升。实现方式通常是修改mapOptimization.cpp中的关键帧插入策略并增加一个SC-PGOScan Context全局回环检测模块。SC-PGO和LIO-SAM的结合是当前比较热门的增强方向它能显著改善大场景下的累计漂移问题。如果你对语义SLAM感兴趣LIO-SAM的轻量化结构非常适合嫁接语义分割网络。思路也简单在LIO-SAM提取特征之后加入一个语义分割线程为每个点云帧增加语义标签让里程计和回环检测只使用地面点和背景点等静态物体而把车辆、行人等动态物体剔除。这个方向在Noetic下实现起来很方便因为Noetic对Python 3的支持很好很多语义分割模型都可以直接部署。5.2 适配自有传感器从demo到真实设备跑通demo数据集之后下一步大概率是要把LIO-SAM迁移到自己的传感器平台上。这一步的关键在于把传感器数据转换成ROS消息格式并且保证时间戳同步。LIO-SAM的输入是一个3D激光雷达话题消息格式为PointCloud2一个6轴或9轴IMU话题消息格式为sensor_msgs/Imu如果使用的激光雷达是Livox系列需要额外注意点云数据的预处理。Livox官方提供了livox_ros_driver2发布的消息是自定义的livox_ros_driver2/CustomMsgLIO-SAM原版是不认这种数据格式的需要先使用livox_point_cloud_converter把它转成标准的PointCloud2格式再通过pointcloud_to_laserscan或直接转发到/points_raw话题。如果直接让LIO-SAM订阅CustomMsg编译能过但运行时不会有点云数据。IMU的安装位置校准也容易被忽视。LIO-SAM假设IMU和激光雷达之间的外参已经标定好如果外参不准即使编译运行成功建出的地图也会有明显的漂移和分层现象。建议先使用lidar-IMU联合标定工具如LiLi-OM、lidar_imu_calib做好外参标定再把外参参数填入params.yaml。5.3 性能调优实践编译优化参数如果你对实时性有更高要求还可以在编译阶段做一些优化。LIO-SAM源码的CMakeLists.txt中默认使用的是-O2优化级别你也可以尝试改为-O3在某些CPU上能带来5%-10%的帧率提升。修改方式是在CMakeLists.txt中找到add_definitions或者set(CMAKE_CXX_FLAGS_RELEASE ...)的行加上-O3 -marchnative。但要注意-marchnative和GTSAM编译时的可移植性设定是冲突的如果是自己本机使用可以加上如果后续要换机器运行就别加。另一个调优方向是修改params.yaml中关键帧之间的距离阈值和角度阈值让系统插入更少的关键帧减轻后端优化的压力。对于室外大场景将keyFrameMeter从1.0调整到1.5或2.0能明显降低CPU占用而精度损失通常在一个可接受范围内。这个参数的调整没有绝对标准需要根据传感器精度和应用场景实测折中。6. 写在最后一个过来人的经验小结LIO-SAM的编译折腾下来我的最大感受是这套代码的质量整体是过硬的它之所以让很多人卡住问题几乎都集中在依赖库管理上。Ubuntu 20.04 Noetic的组合只要把GTSAM的编译参数选对把PCL和OpenCV的版本匹配处理好整个编译过程比想象中顺利。最后分享一个我自己的习惯编译任何SLAM算法之前先把系统的所有依赖库版本记录下来用pkg-config --modversion逐个验证一遍这比编译报错后再回头排查要高效得多。另外养成使用catkin build而不是catkin_make的习惯catkin build在增量编译时更人性化能精确告诉你每个功能包的编译状态和依赖顺序排查问题的时候直观很多。如果你的编译过程遇到了我在文章里没提到的问题优先去GitHub的Issue区搜索很多坑早就有前人留下了解答。祝大家都能顺利跑通LIO-SAM在自己平台上建出漂亮的第一张地图。
返回列表