news 2026/10/3 1:24:44

Ubuntu 20.04 + ROS Noetic 下 LIO-SAM 编译与避坑全指南

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Ubuntu 20.04 + ROS Noetic 下 LIO-SAM 编译与避坑全指南

最近群里好几个朋友卡在LIO-SAM编译这一步,而且卡得最多的就是Ubuntu 20.04 + ROS Noetic这个组合。原因不复杂:LIO-SAM官方README写的是Ubuntu 18.04 + Melodic环境,到了Noetic这里,OpenCV从3.x跳到4.x,PCL和Eigen的版本也变了,再加上gtsam这个关键依赖库本身编译就有讲究,直接照着官方步骤走,大概率会在某个环节翻车。

这篇文章把我从零开始在Ubuntu 20.04 + ROS Noetic下编译LIO-SAM的完整过程、踩过的坑、以及排查思路整理出来。不管你是刚接触激光雷达SLAM的新人,还是已经被编译报错折磨了一下午的老手,照着这份记录操作,基本可以顺利跑通。文章会覆盖环境准备、依赖库编译、主程序构建、launch文件调试、数据集回放,以及高频报错的解决方案。有些细节是官方文档里不会写的,属于实操踩坑后的经验总结。

1. 环境准备与版本避坑

1.1 先搞清楚你的系统状态

动手之前,先确认三件事:操作系统版本、ROS版本、以及系统里是否装过其他版本的ROS或CUDA相关组件。

LIO-SAM这套框架本身不挑显卡,纯CPU就能跑,但不少人是在装了NVIDIA驱动和CUDA的环境中编译的。如果你之前折腾过显卡驱动、装过TensorRT或者别的深度学习环境,编译时偶尔会出现libopencv版本冲突或者Eigen头文件被错误链接的情况。我的建议是:如果机器只是用来跑SLAM,尽量不要在同一个系统里混装过多版本的OpenCV。Noetic默认自带OpenCV 4.2,LIO-SAM某些节点用到了旧版API,稍后会讲怎么改。

确认完这些,打开终端执行:

lsb_release -a rosversion -d

如果rosversion -d输出的是noetic,很好;如果什么都没输出,说明你的/opt/ros/noetic/setup.bash没source进bashrc,这个先解决:

echo "source /opt/ros/noetic/setup.bash" >> ~/.bashrc source ~/.bashrc

1.2 依赖库版本先对齐,再谈其他

按官方README装ros-noetic-pcl-ros、ros-noetic-velodyne-msgs、ros-noetic-cv-bridge这些包,基本没错。但以我实际操作的经验,有几个包就算官方没写,你也会用得上,建议一次性装齐:

sudo apt install ros-noetic-pcl-ros ros-noetic-velodyne-msgs ros-noetic-cv-bridge ros-noetic-image-transport ros-noetic-tf2-geometry-msgs ros-noetic-robot-state-publisher

顺便装一些基础工具:

sudo apt install git cmake libeigen3-dev libopencv-dev python3-catkin-tools

这里要特别提醒一个很多人忽略的点:Eigen版本。Ubuntu 20.04的软件源里Eigen是3.3.7,LIO-SAM对Eigen的需求不算苛刻,3.3.x都能用。怕的是你之前从源码装过更高版本的Eigen,导致头文件路径混乱。如果真的遇到过类似问题,可以先用dpkg -l | grep eigen看看系统里到底装了什么版本,再决定要不要清掉手动安装的版本。

2. 核心依赖逐一手动编译

2.1 gtsam的编译是整个流程的胜负手

LIO-SAM的位姿图优化、因子图构建,全建立在GTSAM这个库上。官方推荐的是4.0.0-alpha2这个版本,不是最新的4.1.1或者4.2.0。有人用新版本也编过了,但我的建议是别折腾,老老实实按推荐版本来。

编译gtsam之前,先把它的依赖装好:

sudo apt install libtbb-dev libboost-all-dev

然后clone源码并编译:

git clone https://github.com/borglab/gtsam.git cd gtsam git checkout 4.0.0-alpha2 mkdir build && cd build cmake -DGTSAM_BUILD_EXAMPLES=OFF -DGTSAM_BUILD_TESTS=OFF -DGTSAM_TANGENT_PREINTEGRATION=OFF .. make -j$(nproc) sudo make install

编译参数里有两个坑需要解释一下:

为什么-DGTSAM_TANGENT_PREINTEGRATION=OFF?LIO-SAM作者在代码里明确建议关闭这个选项。开启状态下gtsam会使用新的切空间预积分接口,而LIO-SAM的IMU预积分代码还是老接口,链接时会报一堆“未定义符号”的错。

为什么关掉examples和tests?这两个选项会生成大量测试程序和示例代码,编译时间极长,内存占用也高。关掉之后能节省至少一半的编译时间。

make -j$(nproc)这里也注意一下,如果电脑内存只有8G,-j$(nproc)可能直接把内存吃满导致编译被杀。建议内存小的机器改用make -j4或者make -j2。

编译过程大概需要10到20分钟,取决于机器性能。装完之后,确认一下gtsam是否被正确安装:

ls /usr/local/lib | grep gtsam ls /usr/local/include/gtsam | head

能看到libgtsam.so和头文件目录,说明gtsam这块稳了。

2.2 OpenCV版本差异处理

Noetic自带的OpenCV是4.2,LIO-SAM里imageProj节点读取图像时用了老写法CV_LOAD_IMAGE_GRAYSCALE,在OpenCV 4环境会直接报错。这个错误不用怕,改一行代码就行,后面第三章具体说。

如果你特别介意这些API差异,有个取巧方案:把LIO-SAM的CMakeLists.txt里OpenCV相关的引用改成find_package(OpenCV REQUIRED COMPONENTS core imgproc imgcodecs),然后代码里的旧API全部替换。但说实话,不值得为了追求“零警告”去折腾,能用就行。

2.3 关于Ceres和LIO-SAM的关系

有些教程会让你额外编译Ceres Solver,那是针对LIO-SAM作者另一个项目LIO-SAM的变体或者LOAM系列项目的。原版LIO-SAM根本不依赖Ceres,它的后端优化由gtsam完成。看到网上教程让你装Ceres时,可以跳过,别浪费时间。

3. LIO-SAM主程序编译全流程

3.1 建立工作空间并获取源码

这一步是所有ROS项目的常规操作:

mkdir -p ~/lio_sam_ws/src cd ~/lio_sam_ws catkin_make

这里catkin_make第一次运行是为了生成devel目录和build目录,很多教程跳过了这一步,直接clone源码再catkin_make也问题不大,但先执行一次能避免某些情况下CMake缓存没初始化导致的怪问题。

然后clone LIO-SAM源码:

cd ~/lio_sam_ws/src git clone https://github.com/TixiaoShan/LIO-SAM.git cd ~/lio_sam_ws catkin_make

如果你需要修改源码后重新编译,推荐用catkin_make --pkg lio-sam单独编译这个包,编译速度快很多:

cd ~/lio_sam_ws catkin_make --pkg lio-sam

3.2 修改CMakeLists.txt里的编译标准

LIO-SAM源码默认的CMakeLists.txt里有这么一行:

add_compile_options(-std=c++11)

在Noetic环境下,某些头文件(尤其是PCL 1.10和OpenCV 4.2的)用了C++14的特性,继续用C++11标准编译会报一堆莫名其妙的错误,比如shared_ptr相关的问题。把这一行改成:

add_compile_options(-std=c++14)

或者直接用更稳妥的方式,在文件开头加上:

set(CMAKE_CXX_STANDARD 14) set(CMAKE_CXX_STANDARD_REQUIRED ON)

具体操作:

gedit ~/lio_sam_ws/src/LIO-SAM/CMakeLists.txt

找到add_compile_options那一行,改完保存。

3.3 imageProj节点的OpenCV API替换

如果你用的是比较新的LIO-SAM源码分支,imageProjection.cpp里可能已经修复了OpenCV 4兼容性。如果编译时报错,定位到报错的文件,找到类似这样的代码:

cv::Mat image = cv::imread(bag_path, CV_LOAD_IMAGE_GRAYSCALE);

改成:

cv::Mat image = cv::imread(bag_path, cv::IMREAD_GRAYSCALE);

改完后重新编译:

cd ~/lio_sam_ws catkin_make --pkg lio-sam

3.4 最容易忘的一步:launch文件加执行权限

这是个特别容易踩的坑。LIO-SAM的launch文件在源码里默认没有x(执行)权限,直接用roslaunch启动时,偶尔会出现“Permission denied”或者直接没有任何反应。虽然有些系统下roslaunch能自动处理这个问题,但保险起见,建议先手动加一下权限:

chmod +x ~/lio_sam_ws/src/LIO-SAM/launch/*.launch chmod +x ~/lio_sam_ws/src/LIO-SAM/rviz/*.rviz

网上很多教程压根不提这一步,导致很多人卡在“明明编译成功了,但roslaunch就是报错”的环节。

3.5 编译成功之后的验证

编译完成后,确认可执行文件已经生成:

ls ~/lio_sam_ws/devel/lib/lio_sam/

正常会看到lio_sam_imuPreintegration、lio_sam_imageProjection、lio_sam_featureExtraction、lio_sam_mapOptimization四个可执行文件。看到这四个文件,说明编译阶段全部通过。

4. 常见问题排查与避坑经验

4.1 编译阶段的高频报错

报错:Could not find a package configuration file provided by "gtsam"

百分之百是gtsam没装或者安装路径不在CMake默认搜索范围里。先确认/usr/local/lib/cmake/GTSAM目录是否存在。如果存在,在CMakeLists.txt里加一句:

list(APPEND CMAKE_PREFIX_PATH /usr/local/lib/cmake/GTSAM)

如果连这个目录都不存在,回第二章重新编译gtsam。

报错:fatal error: gtsam/nonlinear/ISAM2.h: No such file or directory

头文件路径没找到。确认/usr/local/include/gtsam存在,如果之前把gtsam安装在自定义前缀(比如~/gtsam_install),需要显式指定:

set(GTSAM_INCLUDE_DIR ~/gtsam_install/include) set(GTSAM_LIBRARY_DIR ~/gtsam_install/lib)

报错:candidate expects 2 arguments, 2 provided

这种一般是gtsam版本不对,用了最新版gtsam的接口差异导致。回退到4.0.0-alpha2版本重新编译。

报错:undefined reference tocv::imread(...)

OpenCV 4改了图像读取接口,按照3.3节的替换方法处理。

报错:PCL 1.10的警告(warning)特别多

这个不影响编译结果,不用管它。PCL 1.10在C++14下编译时会有大量“deprecated”警告,属于正常现象。

4.2 运行阶段的常见问题

问题:roslaunch一键启动后,RViz弹出来了但没有任何点云

先检查rosbag play有没有真的在播数据。LIO-SAM没有数据源输入时,所有话题都是空的,RViz自然什么都没有。确认一下bag文件路径和launch文件里读取的路径是否一致。

问题:提示No transform from [imu] to [base_link]

这是TF树不完整导致的。LIO-SAM的launch文件里已经包含了静态TF发布节点,正常情况下会发布base_link到imu、base_link到lidar_link的坐标变换。如果报错,试着在另一个终端手动发布一次静态变换:

rosrun tf2_ros static_transform_publisher 0 0 0 0 0 0 base_link imu

但根本性的解决办法还是检查launch文件里robotStatePublisher节点有没有被正确加载。

问题:启动后立刻段错误(Segmentation fault)

多半是gtsam库版本不匹配。有人用gtsam 4.1.1编译通过,但运行时内存访问出错,退回4.0.0-alpha2之后问题消失。这种就是典型的“能编译不代表能运行”,遇到段错误优先排查依赖库版本。

问题:位姿飘了,点云发散

这已经不是编译问题,是传感器标定问题。检查三点:IMU的噪声密度和随机游走参数是否配置正确;lidar到IMU的外参是否按你的传感器实际安装位置写了;bag里的IMU话题频率是否正常(一般200Hz)。参数文件在config/params.yaml,改完需要重新编译才能生效。

4.3 launch文件修改了需要重新编译吗

这是很多新手会问的问题,也确实是ROS里最容易混淆的一个点。答案是:不需要编译。

launch文件本质上是XML格式的启动描述文件,roslaunch在运行时会直接读取并解析它,不会编译成二进制。修改launch文件、改参数文件(.yaml)之后,只要重新roslaunch一次,改动就会生效。

但要注意区分:如果你改的是.cpp或.h源码文件、CMakeLists.txt、package.xml,那就必须重新编译。这里有个速查标准:

改动的文件类型是否需要编译说明
.launch否roslaunch直接解析XML
.yaml(params)否节点启动时读取参数服务器
.cpp / .h是需要重新catkin_make
CMakeLists.txt是需要重新catkin_make
package.xml是需要重新catkin_make

实际操作中,频繁改launch文件和yaml参数时,我习惯先catkin_make一次再把所有终端重启一遍。这样能避免老节点的参数服务器缓存没清干净导致的“改了没生效”假象。

4.4 数据集回放时的Topic名称匹配问题

用rosbag回放数据时,要先看bag里的topic名称是否和LIO-SAM期望的一致。LIO-SAM节点订阅的话题主要有:

  • /points_raw:原始点云,类型sensor_msgs/PointCloud2
  • /imu_correct:IMU数据,类型sensor_msgs/Imu
  • /imu_preintegration:预积分的IMU增量,类型sensor_msgs/Imu
  • /odometry/imu:IMU里程计输出
  • /odometry/lidar:激光里程计输出

先用rosbag info yourbag.bag看一下topic名称。有些公开数据集把IMU话题命名为/imu/data,这时候要么改launch文件里的remap,要么改params.yaml里的订阅话题名称。

我记得有个公开数据集叫Parking Garage,它的bag里IMU话题是/imu_correct,正好和LIO-SAM默认的匹配,适合第一次跑通流程时使用。跑通之后再换成自己的数据,逐步调整参数。

5. 参数配置与运行效果观察

5.1 先跑官方demo数据验证全链路

编译完成且ROS环境正常之后,建议先跑官方提供的demo数据验证整个系统是否正常工作。官方README里给了两个bag下载链接:

  • Walking deg
  • Parking Garage

下载后直接在终端里播放:

rosbag play your_downloaded.bag

同时另开一个终端启动LIO-SAM:

roslaunch lio_sam run.launch

如果一切正常,你会看到:

  1. RViz里出现当前扫描的点云
  2. 地图点云逐渐累积,形成完整的3D地图
  3. 轨迹线(里程计路径)随数据输入不断延伸
  4. 终端里定时输出位姿变换信息

第一次跑通的时候,建议盯着RViz的左上角看消息频率,如果/odometry/lidar以接近10Hz的频率更新,说明整个链路是通的。

5.2 用自己的传感器数据时需要注意什么

换到自己的传感器数据后,外参标定是绕不开的坑。LIO-SAM对IMU和LiDAR之间的外参非常敏感,外参差个几厘米、几度,建图质量就可能从“清晰”变成“糊成一片”。

params.yaml里的外参需要填的是LiDAR坐标系到IMU坐标系的变换矩阵:

extrinsicRot: [1, 0, 0, 0, 1, 0, 0, 0, 1] extrinsicRPY: [1, 0, 0, 0, 1, 0, 0, 0, 1]

这里建议动笔前先确认自己的传感器坐标定义,别照抄demo数据里的默认值。不少人卡在“跑demo数据很好,换自己数据就飘”的问题上,八成就是外参没标对。

另外注意IMU话题的静止状态。LIO-SAM启动后,IMU预积分节点需要一小段时间让IMU达到静止偏置收敛状态,如果数据一开始就是运动状态,初值偏差大会影响后续优化效果。实际操作时,录制bag前最好让设备静止1到2分钟再开始运动。

6. 编译过程中的几条实践心得

这套LIO-SAM在Ubuntu 20.04 + Noetic环境下的编译流程,我前前后后操作过不下十次,帮别人排查问题的次数更多。最后说几条自己的心得。

第一,尽量别用最新的gtsam版本。很多人觉得库越新越好,但在SLAM这种对接口稳定性要求极高的场景里,新版本反而可能带来不兼容问题。LIO-SAM作者明确指定了4.0.0-alpha2,一定有他的道理。这个版本的问题不是最新版,但它是和LIO-SAM代码配合最稳定的版本。

第二,编译时别贪多线程。make -j$(nproc)在16核桌面上编译gtsam,能瞬间把内存吃到20G以上。如果编译中途被系统OOM杀死,别急着加内存,先用make -j4试试,编译慢一点总比反复被杀舒服。

第三,多留一个备用终端。LIO-SAM运行时涉及多个节点,建议至少开三个终端:一个跑roslaunch、一个跑rosbag play、一个用来rostopic echo或者rqt_graph检查话题概要。遇到问题的时候,第三终端能很快定位是哪个节点没起来、哪个话题没有数据。

第四,学会看日志而不是乱猜。编译报错或者运行报错后,一行行看输出。大多数情况下报错信息已经把原因写得明明白白,只是太长了没人愿意读完。先把最后的10行输出读完,再看报错的文件和行号,80%的问题能自己定位。剩下的20%,再把报错信息复制去搜,比只搜“LIO-SAM编译失败”这种模糊关键词有效太多。

最后说一个关于Noetic环境的小技巧:如果你在Ubuntu 20.04上同时装了ROS1和ROS2(有人会这么搞),一定要检查一下bashrc里source的顺序。Noetic的setup.bash必须在任何ROS2环境之前source,否则ROS1的命令会被覆盖,roslaunch直接找不到。这个坑很冷门,但只要碰到过一次,就会记得一辈子。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/10/3 1:24:03

真需求判断指南:三层过滤与数据验证,避开伪需求陷阱

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/10/3 1:23:58

SkyWalking指标体系实战解读:CPM、SLA、P99与JVM监控指南

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/10/3 1:23:27

工程伦理期末复习指南:核心概念、决策框架与案例分析

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/10/3 1:23:24

基于两阶段鲁棒优化的微网多电源容量配置与CCG实现

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/10/3 1:23:23

立创EDA元件库迁移到Cadence全攻略:从OrCAD符号到Allegro封装

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/10/3 1:23:17

基于DRV8818与PIC18F4682的工业步进电机驱动控制方案解析

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华