
很多搞机器人感知的朋友应该都有过这种经历看论文时觉得 LOAM 家族的算法思路很清晰真到自己要在 Ubuntu 20.04 上把 A-LOAM、LeGO-LOAM、SC-LeGO-LOAM、LIO-SAM、LVI-SAM 这一串跑起来时光是配环境就能耗掉一整个周末。这篇内容就是把我从零开始在这套系统上部署、编译、跑数据包、换自采数据的完整过程记录下来包括每个算法之间的依赖关系、编译顺序、常见报错和排查思路希望能帮后来者少踩几个坑。1. 内容整体设计与思路拆解1.1 为什么一口气梳理五个算法不少读者会问LOAM 都出来这么多年了直接装一个 LIO-SAM 不就够了吗为什么要把 A-LOAM、LeGO-LOAM、SC-LeGO-LOAM、LIO-SAM、LVI-SAM 逐个部署一遍我的看法是这五个算法恰好构成了一条非常清晰的技术演进线。A-LOAM 是 LOAM 的精简开源实现代码量小、逻辑直白适合用来理解激光里程计的核心思想——特征提取、帧间匹配、畸变补偿、局部地图优化。LeGO-LOAM 在 A-LOAM 的基础上增加了地面分割、聚类滤噪和基于图优化的回环检测工程性更强。SC-LeGO-LOAM 则把原本基于 ICP 的回环检测换成了 Scan Context 全局描述子解决大场景下的位置识别漂移问题。到了 LIO-SAMIMU 被真正紧耦合进系统前端用帧到局部地图的配准后端用因子图优化精度和鲁棒性都有了质的提升。LVI-SAM 更进一步把视觉相机接入系统视觉惯性里程计和激光惯性里程计互为辅助在退化场景下依然能保持稳定。把这五个算法串起来部署的好处是你能直观感受到每一代算法解决了什么问题、引入了什么新依赖、对传感器有什么新要求。很多初学者只跑通了一个 LIO-SAM遇到点云畸变、回环不准、IMU 外参标定等问题时因为没有对照根本不知道问题出在前端还是后端。五个都跑一遍之后排查思路会清晰很多。1.2 部署方案的选型考量先说系统版本。Ubuntu 20.04 搭配 ROS Noetic 是当前 LOAM 系列最省心的组合。Noetic 是 ROS1 的最后一个长期支持版本官方源里默认的 PCL 是 1.10、Eigen 是 3.3.7、OpenCV 是 4.2这几个版本恰好都在 LOAM 系列算法的兼容范围内。相比之下Ubuntu 18.04 配 Melodic 也能跑但 gtsam、Ceres 这些第三方库的编译依赖比较老装新版本容易冲突Ubuntu 22.04 配 ROS2 则基本告别了这套算法的原生支持需要额外做 ROS1-ROS2 桥接非常麻烦。再说编译工具链。我的建议是所有算法都放在同一个 catkin 工作空间里比如~/loam_ws/src而不是每个算法单独建一个工作空间。原因很简单A-LOAM 依赖velodyne_msgsLeGO-LOAM 依赖cloud_msgsLIO-SAM 和 LVI-SAM 又依赖 gtsam、Ceres、OpenCV 这些第三方库。放在同一个工作空间下catkin 会自动处理消息包的依赖顺序一次性编译五个包的成功率远高于逐个编译。不过有一点要提前说明A-LOAM 和 LeGO-LOAM 系列用的是 ROS Noetic 自带的 catkin 工具而 LIO-SAM 和 LVI-SAM 建议单独编译 gtsam 并安装到系统目录否则链接阶段会报找不到动态库的错误。这个细节我在后面会详细展开。2. 环境准备与依赖安装2.1 ROS Noetic 的安装与配置如果是全新安装的 Ubuntu 20.04ROS Noetic 的安装步骤是固定的。建议直接使用官方软件源不要用国内某些第三方源因为 ROS 依赖的 key 更新比较频繁第三方源经常出现 404 或签名过期的问题。安装命令如下sudo sh -c echo deb http://packages.ros.org/ros/ubuntu $(lsb_release -sc) main /etc/apt/sources.list.d/ros-latest.list sudo apt install curl curl -s https://raw.githubusercontent.com/ros/rosdistro/master/ros.asc | sudo apt-key add - sudo apt update sudo apt install ros-noetic-desktop-full桌面完整版包含了 rviz、rviz 插件、tf、pcl_ros 等常用工具后续跑 LOAM 系列基本够用。安装完成后记得初始化 rosdepsudo rosdep init rosdep update echo source /opt/ros/noetic/setup.bash ~/.bashrc source ~/.bashrc很多人在sudo rosdep init这一步会遇到网络问题因为 rosdep 需要访问 GitHub 上的 raw 文件。这里提供一个我实测可行的替代方案直接手动创建/etc/ros/rosdep/sources.list.d/20-default.list文件内容指向 rosdistro 的 master 分支。具体细节不展开但如果你卡在这一步搜索“rosdep init 超时 解决方法”能找到很多现成方案。2.2 第三方库版本选择Ceres、gtsam、OpenCV这五个算法对第三方库的依赖程度差异很大。A-LOAM 只需要 Ceres SolverLeGO-LOAM 需要 gtsamSC-LeGO-LOAM 基本在 LeGO-LOAM 基础上改代码和依赖LIO-SAM 需要 gtsam 和 CeresLVI-SAM 则额外需要 OpenCV 做视觉特征提取。这里有一个很重要的版本匹配问题。Ubuntu 20.04 的 apt 源里默认的 Ceres 是 1.14.0如果你用sudo apt install libceres-dev安装A-LOAM 编译没问题但 LIO-SAM 在链接时可能会报版本不匹配。原因是 LIO-SAM 的 CMakeLists 中明确要求 Ceres 版本至少 1.14而 Ubuntu 源里的版本在编译时使用的 Eigen 版本和头文件路径跟 LIO-SAM 的预期不完全一致。我的推荐做法是Ceres 和 gtsam 都用源码编译并且固定版本。Ceres 使用 1.14.0A-LOAM 官方测试版本gtsam 使用 4.0.2LIO-SAM 和 LVI-SAM 官方推荐版本。编译命令如下# Ceres 1.14.0 git clone https://github.com/ceres-solver/ceres-solver.git cd ceres-solver git checkout 1.14.0 mkdir build cd build cmake .. make -j8 sudo make install # 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_UNSTABLEON .. make -j8 sudo make install提示gtsam 编译时建议加上-DGTSAM_BUILD_UNSTABLEON否则 LIO-SAM 中使用的gtsam::PreintegratedImuMeasurements等不稳定模块会找不到头文件。至于 OpenCVUbuntu 20.04 自带的 4.2 版本可以直接使用不需要额外编译。但要注意如果之前装过 ROS Melodic 或其它版本的 OpenCV环境变量里可能会残留旧版本路径导致 LVI-SAM 编译时链接到错误的 OpenCV。建议在~/.bashrc里检查一下CMAKE_PREFIX_PATH是否被设置过如果有的话清理干净。3. 核心细节解析与实操要点3.1 A-LOAM理解特征提取与帧间匹配的最小闭环A-LOAM 是基于 LOAM 论文的精简实现作者是港科大的秦通等人。它保留了 LOAM 的核心思想——用曲率提取边缘点和平面点通过优化两类特征点的对应关系来估计雷达位姿但去掉了复杂的鲁棒核函数和局部地图管理代码量控制在 2000 行以内。编译 A-LOAM 的步骤很简单mkdir -p ~/loam_ws/src cd ~/loam_ws/src git clone https://github.com/HKUST-Aerial-Robotics/A-LOAM.git cd .. catkin_make这里有个容易忽略的点A-LOAM 依赖velodyne_msgs而它并没有在package.xml里显式声明这个依赖只写在 CMakeLists 里。如果你是从零开始的工作空间编译时会报找不到velodyne_msgs/Pointcloud2的错误。解决办法是提前安装sudo apt install ros-noetic-velodyne-msgs编译完成后跑官方提供的数据集比如 nsh_indoor_outdoor.bag可以这样启动三个节点source ~/loam_ws/devel/setup.bash roslaunch aloam_velodyne aloam_velodyne_VLP_16.launch rosbag play nsh_indoor_outdoor.bag跑通之后建议自己打开 rviz订阅/laser_cloud_mapping这个 topic观察建图效果。A-LOAM 的建图话题是全局地图比较密集如果你的电脑配置一般显示会卡可以把Decay Time调大一点或者直接订阅/laser_cloud_surround看局部地图。实测下来A-LOAM 在室内小场景下精度表现不错但在长走廊、空旷环境下容易产生漂移这也为后面 LeGO-LOAM 加入回环检测埋下了伏笔。3.2 LeGO-LOAM地面分割与回环检测的工程化改进LeGO-LOAM 是 Tixiao Shan 在 2018 年提出的全称是 Lightweight and Ground-Optimized LOAM。它的核心改进有两点一是利用地面分割把点云分成地面点和非地面点分别提取特征二是通过聚类算法滤除噪声点然后用两步优化的方式先地面、后非地面估计位姿。此外它增加了基于 ICP 的回环检测并用 gtsam 进行图优化。编译 LeGO-LOAM 前需要先处理一个依赖问题它需要自定义的cloud_msgs消息包这个包在 LeGO-LOAM 仓库里自带路径是LeGO-LOAM/cloud_msgs。如果你把整个 LeGO-LOAM 仓库克隆到 src 目录下catkin 会自动编译这个子包不需要额外处理。cd ~/loam_ws/src git clone https://github.com/RobustFieldAutonomyLab/LeGO-LOAM.git cd .. catkin_makeLeGO-LOAM 的启动方式和 A-LOAM 有点不同它需要先启动lego_loam/run.launch这个 launch 文件里默认加载了 VLP-16 的参数。官方提供的 demo 数据包可以这样跑roslaunch lego_loam run.launch rosbag play demo.bag这里有一个非常关键的注意事项如果你用的是 KITTI 数据集或者自己采集的、坐标系方向与 VLP-16 不同的数据LeGO-LOAM 的配准结果会直接翻转或旋转。原因是 LeGO-LOAM 在特征提取时假设点云的坐标系是“前-x 左-y 上-z”而 KITTI 的 velodyne 坐标系是“左-x 上-y 前-z”。解决办法是在utility.h里修改transformAssociateToMap函数的初始旋转矩阵或者在数据预处理阶段做坐标变换。我自己踩过这个坑跑 KITTI 序列时地图直接倒过来了排查了很久才发现是坐标系的问题。3.3 SC-LeGO-LOAMScan Context 带来的位置识别增强SC-LeGO-LOAM 是 LeGO-LOAM 的一个改进分支主要工作是引入 Scan Context 全局描述子替代原来的 ICP 回环检测。Scan Context 是 Giseop Kim 提出的一种点云全局描述方法核心思想是把 3D 点云按方位角-径向距离划分成扇形和环带每个格子统计高度信息生成一个二维矩阵然后通过矩阵相似度快速检索历史帧实现位置识别。从部署角度看SC-LeGO-LOAM 的编译方式与 LeGO-LOAM 几乎一致但它的代码结构有变化主要新增了Scancontext相关的源文件并且在mapOptimization.cpp里增加了回环候选帧的搜索逻辑。cd ~/loam_ws/src git clone https://github.com/irapkaist/SC-LeGO-LOAM.git cd .. catkin_make跑 SC-LeGO-LOAM 时有一个明显不同的点启动后会额外发布一个/scan_context话题并且日志里会打印回环检测的匹配得分和匹配帧 ID。实测下来在室外园区、停车场这类场景中SC-LeGO-LOAM 的回环检出率比原版 LeGO-LOAM 高很多尤其是当机器人回到起点附近但轨迹有一定偏移时Scan Context 的全局描述子比 ICP 的局部点云匹配更鲁棒。但 SC-LeGO-LOAM 也有自己的问题它的 Scan Context 生成依赖点云高度信息在纯平面结构、没有明显垂直特征的环境中比如非常空旷的广场描述子的区分度会下降容易产生误回环。如果后续你要做自采数据的定位建议结合实际场景评估一下是否需要对 Scan Context 的参数比如扇区数、环带数做调整。3.4 LIO-SAM紧耦合 IMU 与因子图后端LIO-SAM 是 Tixiao Shan 在 2020 年提出的全称是 Tightly-coupled Lidar-Inertial Odometry via Smoothing and Mapping。它的核心创新是把 IMU 预积分引入激光里程计用因子图统一优化位姿、速度和零偏同时在前端使用帧到局部地图的配准减少了漂移累积。LIO-SAM 的编译依赖比前面两个复杂一些主要原因是对 gtsam 和 Ceres 的版本要求比较严格。如果之前已经按我前面说的方法编译安装了 gtsam 4.0.2 和 Ceres 1.14.0那编译 LIO-SAM 就很顺利cd ~/loam_ws/src git clone https://github.com/TixiaoShan/LIO-SAM.git cd .. catkin_makeLIO-SAM 的官方 README 里提供了三个数据集的下载链接其中walking_dataset和park_dataset是手持设备采集的campus_dataset是车辆采集的。跑通官方数据的命令是roslaunch lio_sam run.launch rosbag play park_dataset.bag这里要特别提醒LIO-SAM 对 IMU 数据非常敏感。如果你在 rviz 里看到轨迹发散或者地图扭曲首先要检查的并不是算法参数而是 IMU 话题的时间戳是否和激光雷达同步。实测中我遇到过rosbag play的默认发布频率不稳定导致 IMU 数据间隔抖动最终定位漂移的情况。解决办法是在播放数据包时加上--clock参数并在 launch 文件中设置param name/use_sim_time valuetrue/强制使用仿真时间。LIO-SAM 还有一个在自采数据时一定会遇到的坑IMU 外参extrinsicRot和extrinsicTrans默认值是单位矩阵和零向量如果你的 IMU 安装位置不在激光雷达坐标系原点必须自己标定。哪怕是 5 厘米的平移误差在长距离运行后都会导致明显的建图扭曲。建议先用imu_utils或Kalibr做内参标定再用lidar-imu-calib这类工具做外参标定不要凭感觉改参数。3.5 LVI-SAM视觉激光惯导的深度融合LVI-SAM 是 LIO-SAM 的扩展版本同样来自 Tixiao Shan 团队。它在 LIO-SAM 的基础上加入了视觉惯性里程计VIO模块使用相机图像提取特征点与 IMU 预积分结合估计视觉位姿然后通过因子图与激光里程计的结果做联合优化。LVI-SAM 的依赖比 LIO-SAM 多了一个 OpenCV 的 feature 模块但 Ubuntu 20.04 的 ROS Noetic 桌面版自带 OpenCV 4.2所以不需要额外安装。编译命令cd ~/loam_ws/src git clone https://github.com/TixiaoShan/LVI-SAM.git cd .. catkin_makeLVI-SAM 的官方数据包需要到其 GitHub Release 页面下载文件名一般是park.bag。跑通命令是roslaunch lvi_sam run.launch rosbag play park.bagLVI-SAM 启动后会发布三个可视化话题/lvi_sam/mapping/map全局地图、/lvi_sam/odometry激光里程计、/lvi_sam/vio/odometry视觉里程计。在 rviz 里同时打开这三个话题可以直观看到视觉和激光融合的效果。实测下来在光照变化明显或者纹理稀疏的环境中VIO 部分容易丢特征但激光部分会兜底系统整体不会挂掉。这里要提醒一个编译上的坑LVI-SAM 的package.xml里写的是roscpp、sensor_msgs等标准依赖但它的 CMakeLists 里显式引用了 OpenCV 的find_package(OpenCV REQUIRED)。如果你在编译时提示找不到 OpenCV多半是因为系统里装了多个 OpenCV 版本CMake 找到了错误的路径。解决办法是在~/.bashrc里设置export OpenCV_DIR/usr/lib/x86_64-linux-gnu/cmake/opencv4然后再重新catkin_make。4. 实操过程与数据验证4.1 统一工作空间下的编译顺序前面提到我把五个算法都放在同一个~/loam_ws下现在给出一个完整的编译顺序避免新手在依赖问题上反复折腾。# 1. 安装基础依赖 sudo apt install ros-noetic-velodyne-msgs ros-noetic-pcl-ros ros-noetic-cv-bridge # 2. 克隆所有算法仓库 cd ~/loam_ws/src git clone https://github.com/HKUST-Aerial-Robotics/A-LOAM.git git clone https://github.com/RobustFieldAutonomyLab/LeGO-LOAM.git git clone https://github.com/irapkaist/SC-LeGO-LOAM.git git clone https://github.com/TixiaoShan/LIO-SAM.git git clone https://github.com/TixiaoShan/LVI-SAM.git # 3. 编译 cd ~/loam_ws catkin_make如果五个仓库一次性编译报错不要惊慌按下面的顺序逐个排查如果报Could not find a package configuration file provided by velodyne_msgs说明 velodyne_msgs 没装执行sudo apt install ros-noetic-velodyne-msgs。如果报Could not find a package configuration file provided by gtsam说明 gtsam 没有安装到系统目录回到前面的源码编译步骤重新安装。如果报No rule to make target /usr/lib/x86_64-linux-gnu/libopencv_core.so说明 OpenCV 库路径有问题用sudo apt install libopencv-dev安装开发包。4.2 用 KITTI 数据做横向对比五个算法都跑通官方 demo 之后我的建议是再用 KITTI 数据集做一次横向对比这样能直观感受不同算法对同一份数据的处理能力。KITTI 的 raw data 转换成 rosbag 后激光话题是/kitti/velo/pointcloudIMU 话题是/kitti/oxts/imu但 LeGO-LOAM 和 LIO-SAM 默认订阅的话题名不同需要做话题重映射。一个比较通用的做法是写一个 launch 文件在启动算法的同时做 remaplaunch include file$(find lio_sam)/launch/run.launch/ remap from/points_raw to/kitti/velo/pointcloud/ remap from/imu_correct to/kitti/oxts/imu/ /launch实测下来在 KITTI 00 序列上LIO-SAM 的轨迹精度最高SC-LeGO-LOAM 在回环处有明显的修正A-LOAM 因为缺乏回环和 IMU长距离漂移最大。LeGO-LOAM 由于它基于地面优化的设计在 KITTI 这种车载场景表现不错但在手持设备或者无人机场景下效果会差一些。这个对比结果基本符合五个算法的设计定位。4.3 录一段自己的数据包验证可迁移性如果你有自己的激光雷达和 IMU录一段数据包来验证算法可迁移性是很有必要的。这里给出一个快速验证的步骤把雷达点云话题发布为/points_rawIMU 话题发布为/imu_correct。如果传感器驱动自带的话题名不同优先用 rosbag 的 remap 功能不要改算法代码。静态初始化 5-10 秒后再开始移动让 LIO-SAM 和 LVI-SAM 的 IMU 预积分充分收敛。在 rviz 里观察/lio_sam/mapping/odometry话题的轨迹如果轨迹在起步后快速发散优先检查 IMU 话题频率是否在 100Hz 以上以及雷达点云的时间戳是否单调递增。如果地图在某个方向被拉长或压缩检查激光雷达的线数是否匹配 launch 文件中的参数。比如用 16 线雷达跑 64 线配置特征提取会失效导致里程计完全不工作。5. 常见问题与排查技巧实录5.1 编译阶段的典型报错第一个高频问题是fatal error: pcl_conversions/impl/pcl_conversions.hpp: No such file or directory。这通常是因为 PCL 版本和pcl_conversions包的版本不匹配。Ubuntu 20.04 上如果同时安装了 ROS Noetic 和系统自带的 libpcl-dev会出现两个版本的 PCL 头文件冲突。解决办法是卸载系统自带的 libpcl-dev只保留 ROS 的 PCLsudo apt remove libpcl-dev第二个高频问题是 gtsam 编译时出现undefined reference to gtsam::NonlinearFactorGraph::updateCholesky之类的链接错误。这个属于版本不匹配问题常见于 gtsam 4.1 或 4.2 版本编译的 LIO-SAM。我的建议是直接固定到 4.0.2不要使用最新版。第三个高频问题是 A-LOAM 编译时报error: ‘CV_LOAD_IMAGE_UNCHANGED’ was not declared in this scope。这是因为 OpenCV 4.x 移除了CV_LOAD_IMAGE_UNCHANGED这个宏而 A-LOAM 在kittiHelper.cpp里使用了它。解决办法有两个一是改代码把CV_LOAD_IMAGE_UNCHANGED替换成cv::IMREAD_UNCHANGED二是在 CMakeLists 里加入add_definitions(-DOPENCV_TRAITS_ENABLE_DEPRECATED)。我实测改代码更可靠。5.2 运行时的排查思路先讲一个最常见的现象启动后 rviz 里看不到地图。首先要确认算法节点是否真的收到了点云数据用rostopic hz /points_raw查看话题发布频率。如果频率为 0说明话题名不对或者数据包没有正常播放如果频率正常但 rviz 无显示检查 rviz 的固定坐标系是否设置成了map以及是否订阅了正确的点云话题。再讲一个我在 LIO-SAM 上遇到的比较隐蔽的问题启动后地图正常建了 10 秒然后突然跳变或者消失。排查后发现是 IMU 的协方差参数设置不合理导致因子图优化时给 IMU 的权重过大一旦 IMU 出现短暂的加速度计饱和整个轨迹就被拉偏了。解决办法是调低imuAccNoise和imuGyrNoise参数或者增大imuAttNoise让激光对位姿的约束更强一些。最后提醒一个回环检测相关的坑如果你跑 SC-LeGO-LOAM 或者 LIO-SAM 时发现回环检测一直没有触发检查一下雷达的探测范围。Scan Context 和 LIO-SAM 的 Radius Search 回环检测都依赖足够的点云重叠区域如果雷达探测距离太短比如室内用 VLP-16 且墙很近回环候选帧的相似度会很低算法自然就不会触回环。这种情况下可以适当降低回环检测的得分阈值但要小心误回环导致地图出现“鬼影”。6. 写在最后的实操体会五个算法全部部署下来我最深的感受是环境问题比算法本身更消耗精力。Ceres、gtsam、PCL、OpenCV 这几个库的版本排列组合足以让人在 CMake 报错里耗上一整天。但反过来想正是因为每个算法都有独特的依赖和设计取舍跑通它们的过程本身就是一个很好的学习路径——你会被迫去理解什么是因子图、什么是预积分、什么是 Scan Context而不只是机械地输入命令行。如果你现在的目标是快速跑通我建议按照 A-LOAM → LeGO-LOAM → SC-LeGO-LOAM → LIO-SAM → LVI-SAM 的顺序来每跑通一个就停下来看看 rviz 里的地图想想这个算法比上一个多解决了什么问题。这样一遍下来你对整个 LOAM 技术树的理解会比单纯看十篇论文都深刻。最后再分享一个小技巧把编译好的工作空间做一个 tar 备份下次在新机器上部署时直接解压再配合 Docker 的话基本上十分钟就能恢复到可运行状态。别问我怎么知道的都是重装系统换来的教训。