资讯动态

Ubuntu 20.04 上 GAC-Mapping 从编译到建图全流程与避坑指南

发布时间:2026/10/26 21:31:02 来源:尧图企业网站定制
1. 为什么要在 Ubuntu 20.04 上折腾 GAC-MappingGAC-Mapping 这套东西第一次听到的人大概率会愣一下名字里带 Mapping直觉反应是建图但它真正做的事情是把激光雷达点云配准和因子图优化这两件事揉在一起做成一个可以离线跑、也可以在线跑的建图框架。我在几个室内外混合场景的项目里用过它最直接的感受是它对点云质量的要求比很多开源方案要挑剔但一旦跑通轨迹的平滑度和回环的闭合质量确实让人省心。这篇文章面向的是手里已经有一台装了 Ubuntu 20.04 的机器、想把这套框架从源码编译到实际跑出一张完整地图的人。不管你是刚接触 SLAM 的学生还是需要快速验证一个建图方案的工程师下面这套流程都可以直接照着走。我会把每一步为什么这么做讲清楚也会把我在编译和调参过程中踩过的坑原原本本写出来——很多坑在官方文档里是看不到的只有真正编译过、跑过数据集的人才会遇到。先说清楚这套框架的核心构成方便你建立整体认知。GAC-Mapping 的骨架大致分三块前端点云预处理与特征提取、基于 GICP 类思想的配准模块、后端因子图优化与回环检测。前端负责把原始点云降采样、去畸变、提取面元和边元特征配准模块负责相邻帧之间的位姿估计后端则把里程计因子、回环因子、GPS 或先验因子一起丢进因子图里做全局优化。理解了这个分层后面编译时看到一堆包名就不会晕。Ubuntu 20.04 这个选择其实挺关键。它自带的是 GCC 9 和 CMake 3.16ROS 版本对应 NoeticPCL 是 1.10Eigen 是 3.3.7。这套组合对 GAC-Mapping 依赖的几个库来说是比较友好的——太老的系统比如 18.04PCL 版本偏低某些点云容器接口对不上太新的系统比如 22.04Eigen 升到 3.4 之后一些老代码里的对齐宏会报编译错误。所以 20.04 算是一个甜点版本这也是为什么网上大量教程都锚定在这个版本上。2. 环境准备依赖装对了后面少一半麻烦2.1 系统基础依赖的完整清单很多人编译失败不是代码问题而是依赖没装全。GAC-Mapping 依赖的库我整理成下面这张表建议你对着一条条核对缺一个都可能在链接阶段炸出来。依赖库版本要求作用安装方式Eigen3.3.x矩阵运算、位姿表示apt 安装PCL1.10点云容器与滤波apt 安装Ceres Solver1.14 或 2.0后端非线性优化源码编译GTSAM4.0因子图优化源码编译OpenCV4.2图像与可视化辅助apt 安装ROS Noetic对应版本消息传递与可视化apt 安装yaml-cpp0.6参数文件解析apt 安装TBB2020并行加速apt 安装一次性把 apt 能装的都装上命令如下sudo apt update sudo apt install -y libeigen3-dev libpcl-dev libopencv-dev \ libyaml-cpp-dev libtbb-dev libboost-all-dev \ cmake git build-essential这里有个细节值得说Eigen 一定要确认版本。装完之后执行dpkg -l | grep eigen看到 3.3.7 就对了。如果系统里混进了 3.4 的版本比如你之前手动装过后面编译 Ceres 时会出现Eigen::internal::aligned_malloc相关的报错非常隐蔽。我当时的处理办法是把手动装的 Eigen 从/usr/local/include里清掉只保留 apt 版本。2.2 Ceres 与 GTSAM 的源码编译要点这两个库为什么不用 apt因为 Ubuntu 20.04 源里的 Ceres 版本偏老GTSAM 干脆没有官方包。Ceres 我建议用 2.0.0它对 Eigen 3.3 的兼容性最好。编译时打开BUILD_TESTINGOFF能省掉一大堆测试依赖git clone https://ceres-solver.googlesource.com/ceres-solver cd ceres-solver git checkout 2.0.0 mkdir build cd build cmake .. -DBUILD_TESTINGOFF -DBUILD_EXAMPLESOFF make -j$(nproc) sudo make installGTSAM 的编译稍微讲究一点。它默认会去找系统里的 Boost 和 TBB如果版本对不上会静默降级导致后端优化速度变慢。我的做法是显式指定git clone https://github.com/borglab/gtsam.git cd gtsam git checkout 4.1.1 mkdir build cd build cmake .. -DGTSAM_BUILD_EXAMPLES_ALWAYSOFF \ -DGTSAM_BUILD_TESTSOFF \ -DGTSAM_WITH_TBBON make -j$(nproc) sudo make install注意GTSAM 编译时如果报Could NOT find pybind11不用管它那是 Python 绑定的可选依赖不影响 C 主库。但如果你看到TBB not found一定要回头检查libtbb-dev是否真的装上了否则后端多线程优化会退化成单线程跑大数据集时慢得让人怀疑人生。2.3 ROS Noetic 工作空间的初始化GAC-Mapping 的很多节点是以 ROS 包的形式组织的所以需要一个 catkin 工作空间。这里我建议单独建一个干净的空间别和别的项目混在一起避免包名冲突mkdir -p ~/gac_ws/src cd ~/gac_ws/src catkin_init_workspace cd .. catkin_make source devel/setup.bash把source那行写进.bashrc里省得每次开终端都要手动敲。这一步看似简单但我见过不少人因为忘了 source编译时提示找不到某个自定义消息包白白折腾半小时。3. 源码获取与编译把报错一个个摁下去3.1 代码结构与编译顺序把 GAC-Mapping 的源码放进src目录后先别急着catkin_make。我建议先tree -L 2看一眼目录结构确认里面是不是有多个相互依赖的子包。通常这类框架会拆成gac_core算法核心、gac_rosROS 接口、gac_msgs自定义消息几个部分。编译顺序上消息包必须最先编译否则依赖它的节点会因为找不到头文件而失败。如果框架提供了CMakeLists.txt的顶层聚合直接catkin_make一般能自动处理依赖顺序。但如果你发现编译到一半报fatal error: gac_msgs/xxx.h: No such file那就手动分步来catkin_make --pkg gac_msgs catkin_make --pkg gac_core catkin_make --pkg gac_ros3.2 高频编译报错与对应解法我把实际编译中遇到的报错整理成速查表你对照着看报错信息关键词根本原因解决办法undefined reference to Eigen::...Eigen 版本混用或对齐问题清理/usr/local/include/eigen3只用 apt 版本PCL requires C14CMake 标准设置过低在 CMakeLists 里加set(CMAKE_CXX_STANDARD 14)cannot find -lGTSAMGTSAM 安装路径未进链接器搜索路径sudo ldconfig刷新缓存Sophus not found缺少 Sophus 库源码编译 Sophus 并 installboost::filesystem链接错误Boost 版本与编译选项不匹配确认libboost-all-dev已装重编其中 Sophus 这个坑值得单独说。GAC-Mapping 里位姿的 SE(3) 表示大概率用了 Sophus而 Ubuntu 20.04 的 apt 源里没有它。你需要从源码编译注意选对分支——如果用模板化的新版 Sophus头文件路径是sophus/se3.hpp老版是sophus/se3.h。代码里 include 的是哪个你就编哪个版本别想当然。git clone https://github.com/strasdat/Sophus.git cd Sophus git checkout 1.0.0 mkdir build cd build cmake .. -DBUILD_TESTSOFF make -j$(nproc) sudo make install3.3 编译参数调优的实操心得catkin_make默认是单线程编译这套框架代码量不小单线程能编到你打瞌睡。加上并行参数catkin_make -j$(nproc) -DCMAKE_BUILD_TYPERelease一定要加Release。我第一遍编译时忘了这个编出来的是 Debug 版跑数据集时帧率只有个位数一度以为是算法本身慢后来重新用 Release 编译速度直接翻了五六倍。这个教训很典型SLAM 类框架对编译优化极其敏感Debug 版里的断言和未优化循环会把性能拖垮。提示如果你的机器内存小于 8G-j$(nproc)可能会因为并行编译占用内存过高而触发 OOM。这种情况把并行数降到-j4甚至-j2宁可慢一点也别让编译进程被系统杀掉。4. 数据集准备与参数配置跑通的第一道门槛4.1 数据集格式与目录组织GAC-Mapping 一般支持两种输入ROS bag 包和离线点云序列。我建议先用离线序列跑通因为它的可控性更强出问题容易定位。典型的目录结构是这样的dataset/ ├── velodyne/ # 每帧点云按时间戳命名 .pcd 或 .bin ├── IMU/ # 可选IMU 数据 ├── config.yaml # 传感器外参和算法参数 └── ground_truth.txt # 可选用于评估轨迹精度点云文件的命名一定要和时间戳严格对应因为框架内部靠文件名排序来建立帧间时序。我见过有人用000001.pcd、000002.pcd这种纯序号命名结果框架解析时间戳失败直接报空指针。稳妥的做法是用纳秒级时间戳比如1620000000123456789.pcd。4.2 配置文件里那几个必须改的参数配置文件是整个流程的神经中枢改错一个参数可能让建图结果面目全非。下面这几个是我认为最需要关注的# 传感器参数 lidar_topic: /velodyne_points lidar_min_range: 1.0 # 最小有效距离过滤近处噪点 lidar_max_range: 80.0 # 最大有效距离室外场景可调大 # 前端参数 voxel_size: 0.5 # 降采样体素大小室内可降到 0.2 keyframe_threshold: 1.0 # 关键帧距离阈值单位米 # 配准参数 gicp_max_iter: 30 # GICP 最大迭代次数 gicp_corr_dist: 1.5 # 对应点最大距离 # 后端参数 loop_closure_enabled: true loop_search_radius: 15.0 # 回环搜索半径voxel_size这个参数我特别想强调。它直接决定了点云密度和计算量的平衡。室内场景比如走廊、房间用 0.2 到 0.3 比较合适能保留足够的墙面细节室外开阔场景用 0.5 到 0.8否则点太多配准一次要好几秒。这个值不是拍脑袋定的它和你的激光雷达线数有关——16 线雷达点本来就稀体素再设大就没什么特征了64 线雷达可以适当放大。gicp_corr_dist也需要根据场景调。它是对应点匹配的距离上限设太小会导致匹配点对不足、配准失败设太大会引入错误匹配、轨迹漂移。经验值是场景中最大物体尺寸的 1/10 左右。室内 1.5 米、室外 3 米是个不错的起点。4.3 外参标定的常见误区如果你的点云来自多个传感器比如激光雷达加 IMU外参矩阵必须准确。很多人直接抄别人的外参结果建图时地面是斜的、回环对不上。外参的平移部分相对好测旋转部分尤其是安装俯仰角差个一两度跑长距离就会累积成明显的漂移。我的建议是先用一个已知的平坦地面场景验证。把车或设备静止放在水平地面上跑几帧点云看地面拟合出来的法向量是不是接近(0, 0, 1)。如果偏了就微调外参里的旋转直到地面水平。这个土办法虽然不精确但能快速排除大的标定错误。5. 实际运行与结果验证从启动到出图5.1 启动流程与节点依赖关系环境、代码、数据都就绪后启动一般分两步先起核心建图节点再起可视化。用 launch 文件的话一条命令搞定roslaunch gac_mapping run.launch \ config_file:$HOME/gac_ws/src/gac_mapping/config/params.yaml \ dataset_path:$HOME/dataset如果框架没有现成的 launch 文件就手动起rosrun gac_mapping mapping_node _config:/path/to/params.yaml启动后第一件事是看终端输出。正常的日志应该能看到点云加载成功关键帧创建回环检测触发这类信息。如果卡在等待点云不动八成是话题名对不上或者数据路径写错了。这时候用rostopic list看看实际发布的话题和配置里的lidar_topic核对一下。5.2 用 RViz 观察建图质量的三个关键点RViz 是判断建图好坏的直观工具。我通常关注三样东西第一是点云地图的连续性。好的建图结果里墙面应该是薄薄一层如果出现明显的重影或者双层墙说明配准有偏差回环没闭合好。第二是轨迹的平滑度轨迹线如果出现突兀的折角或者来回抖动前端里程计可能有问题。第三是回环约束的可视化很多框架会把检测到的回环用连线画出来连线过多说明阈值太松一条都没有说明阈值太严。5.3 轨迹精度评估的实操方法如果数据集带真值轨迹可以用 EVO 工具做定量评估。安装很简单pip install evo --upgrade然后对比估计轨迹和真值evo_traj tum estimated.txt --ref ground_truth.txt -p --plot_modexy evo_ape tum ground_truth.txt estimated.txt -va --plotevo_ape输出的是绝对位姿误差重点看 RMSE 那一栏。室内小场景RMSE 在 0.1 米以内算不错室外大场景0.5 米以内可以接受。如果误差大得离谱先别怀疑算法回头检查时间戳对齐——估计轨迹和真值的时间戳如果没对齐算出来的误差毫无意义。EVO 支持--t_offset参数做时间偏移补偿这个细节很多人不知道。6. 常见问题排查与避坑经验实录6.1 运行期典型故障速查编译过了不代表能跑通运行期的问题往往更磨人。我把遇到过的整理如下现象可能原因排查与解决启动即崩溃报 segfault配置文件字段缺失或类型错误用 yaml 校验工具检查逐字段核对建图跑一半卡死内存泄漏或点云累积过多检查降采样是否生效限制地图保存频率轨迹整体漂移外参错误或 IMU 未对齐重标外参检查 IMU 时间同步回环检测不触发搜索半径过小或描述子阈值过严调大loop_search_radius放宽阈值地图出现分层配准对应距离设置不当调整gicp_corr_dist重跑6.2 内存与性能的平衡技巧GAC-Mapping 在长距离建图时点云地图会越积越大内存占用直线上升。我跑一个两公里的室外数据集时内存一度飙到 12G。解决办法有两个一是开启地图降采样保存每隔一定距离对已建地图做一次体素滤波二是限制关键帧数量超过阈值时对旧关键帧做边缘化处理。这两个开关一般在配置文件的地图管理段落里默认可能是关的长距离场景务必打开。另外如果你的机器有独立显卡确认框架是否支持 GPU 加速的配准。有些版本把 GICP 的对应点搜索放在 CUDA 上跑速度能提升一个数量级。但要注意驱动和 CUDA 版本匹配装错了反而会退化成 CPU 模式还不报错白白浪费显卡。6.3 我踩过的三个印象最深的坑第一个坑是时间戳单位。有的数据集时间戳是秒浮点有的是纳秒整数框架内部如果按纳秒处理而喂进去的是秒帧间时间差会变成天文数字配准直接失效。我第一次遇到时排查了大半天最后发现是数据格式问题。建议在配置文件里明确写清timestamp_unit: ns或s。第二个坑是坐标系约定。不同框架对前向的定义不一样有的是 X 轴向前有的是 Z 轴向前。如果搞反了建出来的地图会是躺着的虽然轨迹本身没错但可视化时极其别扭而且和真值对比时误差会莫名其妙地大。跑之前一定确认框架用的是哪种约定必要时在配置里加一个坐标变换。第三个坑是回环误检测。在结构重复的场景比如长走廊、对称建筑里回环检测容易把两个长得像但实际不同的地方匹配上导致地图被拉链式地扭曲。这种情况单靠调阈值治标不治本更好的办法是加几何一致性校验——检查候选回环的位姿变换是否和里程计累积的变换大致吻合不吻合的直接丢弃。很多成熟框架里这个校验是默认开的如果你用的版本没有值得自己补上。7. 参数调优的进阶思路跑通只是起点调好才是目的。GAC-Mapping 的参数大致分三组前端降采样与特征、配准、后端优化。调参的顺序应该是先前端、再配准、最后后端因为前端的输出质量直接决定后面两步的上限。前端调优的核心是保留多少特征。体素太大特征丢失配准找不到足够对应点体素太小计算量爆炸。一个实用的判断方法是降采样后单帧点云数量控制在 5000 到 20000 之间比较合适。你可以写个小脚本统计一下超出范围就调体素。配准调优看的是收敛性和残差。如果每次配准迭代次数都顶到上限还没收敛说明初始位姿太差或者对应距离设小了如果残差一直很大可能是点云噪声太重需要加强滤波。我习惯在配准模块里打开残差日志跑几十帧看看残差分布正常应该在厘米级。后端调优主要围绕因子权重。里程计因子、回环因子、先验因子在因子图里的相对权重决定了优化结果偏向谁。回环权重给太高一个误检测就能把整张图拉歪给太低回环起不到纠正作用。这个没有万能值得根据你的回环检测置信度来定置信度高就敢给高权重。提示调参时每次只改一个参数改完跑同一个数据集对比结果。同时改多个参数出了问题根本不知道是哪个引起的。这个原则听起来简单但真到着急出结果的时候很多人就忘了。8. 一点个人体会这套流程我从头到尾跑过好几遍每次换机器、换数据集都会遇到新的小问题但大框架是稳定的依赖装全、编译用 Release、配置逐项核对、先离线后在线、先小场景后大场景。Ubuntu 20.04 这个环境之所以被反复推荐本质上是因为它的库版本组合经过大量实践验证踩坑的概率最低。如果让我给刚上手的人一句建议那就是别一上来就追求跑通完整数据集先用几帧数据把整条链路走通。拿十帧点云确认能加载、能配准、能出图、能保存这条最小链路通了再往上加数据量、加回环、加优化。很多让人崩溃的问题其实在最小链路上就能暴露出来早发现早解决比跑到一半崩掉再回头查要省事得多。

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价 →
↑