5步跑通 GLIM 多传感器 3D SLAM:从 LiDAR+IMU 到全局一致的点云地图
【免费下载链接】glimGLIM: versatile and extensible point cloud-based 3D localization and mapping framework项目地址: https://gitcode.com/GitHub_Trending/glim/glim
你的 LiDAR+IMU 轨迹跑完一圈校园后开始漂移,走廊尽头的点云和出发点对不上,问题往往不是某几帧配准失败了,而是局部配准误差沿着整条轨迹一路累积,没人来"结账"。GLIM 就是做这个"结账"的:它是一个多传感器 3D 定位建图框架,把点云配准误差作为约束放进因子图(一种把位姿当未知量、用一堆"约束关系"整体求解的优化结构)里全局最小化,让整个轨迹和点云地图收敛到全局一致,并支持 GPU 加速。
这篇文章按 onboarding 的思路写:先讲清它能帮你做什么,再走一遍环境准备、首次运行、模块选型、调参速查和自检清单,最后给出手动修图和扩展的进阶用法。文中所有默认值、版本要求都取自本仓库(当前版本 v1.2.2),你可以在 CMakeLists.txt 和config/目录里逐条对账。
GLIM 能帮你做什么
它接得住哪些传感器
GLIM 刻意去掉了"传感器特化"的处理流程,只要输出点云(外加 IMU)就能跑,官方支持的类型包括:
- 旋转式 LiDAR:Velodyne HDL32e、Ouster OS1-32
- 非重复扫描 LiDAR:Livox Avia、Livox MID360
- 固态 LiDAR:Intel Realsense L515
- RGB-D 相机:Microsoft Azure Kinect
参数文档 里还给出了这些传感器典型的T_lidar_imu(LiDAR 与 IMU 之间的外参变换)参考值,方便你起步,但官方提醒"不要盲目照抄",务必以你自己的标定为准。
三级流水线的数据流
点云进来后经过三级处理,每级都是一个可独立替换的模块:
- 里程计(Odometry):实时估计传感器位姿,用固定滞后平滑(默认
smoother_lag5 秒,见 config/config_odometry_gpu.json)。 - 子图(Sub mapping):把连续轨迹切成一个个"子图"(submap,一段轨迹打包成的局部地图单元)并做批量优化。
- 全局建图(Global mapping):当两个子图重叠率超过阈值(默认
min_implicit_loop_overlap0.2)时自动建立约束——这就是 GLIM 的"隐式闭环检测",不需要显式的闭环检测器就能把走回去的路对齐。
各级实现分布在 里程计源码 和 建图源码,头文件接口在 include/glim/。
跑完之后你得到什么
关闭glim_rosnode或glim_rosbag时,结果会 dump 到/tmp/dump:建图因子图数据,加上 4 个 TUM 格式轨迹文件(每行t x y z qx qy qz qw):
| 文件 | 内容 |
|---|---|
odom_imu.txt/odom_lidar.txt | 闭环前的里程计轨迹(IMU 系 / LiDAR 系) |
traj_imu.txt/traj_lidar.txt | 闭环后的全局轨迹(IMU 系 / LiDAR 系) |
对比odom_*和traj_*两条轨迹,你一眼就能看出全局优化帮你"修正"了多少漂移。
部署前的准备:环境与依赖
版本要求一览
官方测试环境是Ubuntu 22.04 / 24.04 + CUDA 12.2 / 12.6 / 13.1,以及 NVIDIA Jetson Orin(JetPack 6.1)(README):
| 项目 | 要求 |
|---|---|
| 操作系统 | Ubuntu 22.04 / 24.04;NVIDIA Jetson Orin(JetPack 6.1) |
| CUDA | 12.2 / 12.6 / 13.1(当前版本不支持 CUDA 11 及更低) |
| 构建工具 | CMake ≥ 3.22,C++17(见 CMakeLists.txt) |
| 必装依赖 | Eigen、nanoflann、GTSAM(≥4.2,兼容 4.2a9 / 4.3a0 / 4.3a1)、gtsam_points 1.2.2 |
| 可选依赖 | CUDA、OpenCV(相机图像)、OpenMP、ROS/ROS2、Iridescence(3D 查看器) |
| ROS 版本 | ROS2 Humble(22.04)/ Jazzy(24.04),也支持 ROS1 |
两条安装路线
- PPA 二进制(官方推荐):一条在线脚本完成源注册后
apt install即可,Ubuntu 22.04/24.04 的 AMD64/ARM64 都覆盖,具体命令在 安装文档。另有官方预构建 Docker 镜像(ROS2 Humble/Jazzy,含 CUDA 变体,目前仅 AMD64),用法见 docker 文档。 - 源码构建:适合想改核心代码的人。GTSAM 和 gtsam_points 两个依赖需要先按 安装文档 的步骤构建安装(启用 GPU 模块必须用带 CUDA 编译的 gtsam_points,否则 CMake 会自动关闭
BUILD_WITH_CUDA并给出警告),核心库构建如下:
# 1) 系统依赖(GTSAM 4.3a0 与 gtsam_points 1.2.2 需另行构建,见安装文档) sudo apt install libomp-dev libboost-all-dev libmetis-dev libfmt-dev libspdlog-dev \ libglm-dev libglfw3-dev libpng-dev libjpeg-dev # 2) 克隆并编译 GLIM 核心库 git clone https://gitcode.com/GitHub_Trending/glim/glim glim cd glim && mkdir build && cd build cmake .. -DBUILD_WITH_CUDA=ON make -j$(nproc) sudo make install每个估计模块(GPU/CPU/CT 里程计、各类建图)被编译成独立的.so动态库,运行时由 JSON 配置里的so_name字段决定加载哪一个——这也是后面"换模块组合"只需要改配置的原因。
📦 从首次运行到出图
先把配置指对
入口是 config/config.json,它只做一件事:把三个后端模块指向各自的参数文件,默认全是 GPU 版:
"config_odometry": "config_odometry_gpu.json", "config_sub_mapping": "config_sub_mapping_gpu.json", "config_global_mapping": "config_global_mapping_gpu.json"另外两个必须确认的文件:
- config/config_sensors.json:
T_lidar_imu改成你这套传感器的外参(默认值是 Ouster OS1-32 的[0.006, -0.012, 0.008, 0, 0, 0, 1]); - config/config_ros.json:
imu_topic、points_topic指向你的话题名;如果你的 IMU 加速度单位是 g(例如 Livox 系列),把acc_scale设为9.80665(海esai 系列陀螺仪单位是 deg/s 时,ang_scale设为0.017453)。
一个容易踩的坑:在 ROS2 里改了包内配置后,需要重新colcon build才会生效(ROS2 要求配置在 install 目录),用--symlink-install或外部config_path可以绕开。
跑官方测试轨迹
官方提供了 Ouster OS1-128 的测试数据(降采样版约 515MB,下载入口见 quickstart 文档),默认配置就是为它准备的。ROS2 下:
# 方式一:rosbag 直读模式,自动调速、尽量不掉帧 ros2 run glim_ros glim_rosbag os1_128_01 # 方式二:标准节点模式,另开终端放 bag ros2 run glim_ros glim_rosnode ros2 bag play os1_128_01 # 跑完打开离线查看器(结果在 /tmp/dump) ros2 run glim_ros offline_viewerglim_rosbag适合离线回放,glim_rosnode适合接实时传感器。
出图与验收
结束后打开offline_viewer(File → Open Map选 dump 目录),可以直接查看因子图和子图球体、导出 PLY 点云。把traj_imu.txt和odom_imu.txt画在一起,轨迹首尾闭环处的差距就是你这次全局优化的"战绩"。
模块组合三选一:GPU / CPU / LiDAR-only
GLIM 提供 7 个估计模块,覆盖"有 GPU 的整机最高精度"到"树莓派级别的轻量实时"(模块源码与头文件)。官方组合图如下:
三种预设组合怎么选
| 组合 | 里程计 | 子图 | 全局建图 | 适用场景 |
|---|---|---|---|---|
| GPU 完整版 | OdometryEstimationGPU(需 GPU,需 LiDAR-IMU,固定滞后+关键帧) | SubMapping(批量优化,可 CPU/GPU) | GlobalMapping(配准代价最小化) | 有 NVIDIA GPU,追求精度上限 |
| CPU 轻量版 | OdometryEstimationCPU(仅需 CPU,scan-to-model) | SubMappingPassthrough(不优化) | GlobalMappingPoseGraph(位姿图优化) | 无 GPU 的机器;demo 页 记录过 Jetson Nano 可实时跑其中的里程计环节 |
| 纯 LiDAR 版 | OdometryEstimationCT(连续时间 ICP,无需 IMU) | 任选,但需enable_imu: false | 任选 | 没有 IMU 或 IMU 数据不可用 |
怎么切换组合
只改 config/config.json 的三行指向即可(quickstart 文档 给出的官方组合):
- CPU 版:
config_odometry_cpu.json+config_sub_mapping_passthrough.json+config_global_mapping_pose_graph.json - 纯 LiDAR 版:
config_odometry_ct.json,并在使用 IMU 的子图/全局配置里把"enable_imu"设为false - 只想跑里程计、不做建图:在 config/config_ros.json 里把
enable_local_mapping、enable_global_mapping都关掉,系统就只跑里程计估计
调参速查:先动这几个参数
全部参数见 参数文档,下面是日常 90% 的调优目标,默认值均摘自仓库配置文件:
| 参数 | 默认值 | 作用与调整建议 | 所在文件 |
|---|---|---|---|
T_lidar_imu | OS1-32 参考值 | LiDAR-IMU 外参,必改,以自标定为准 | config_sensors.json |
acc_scale | 0(自动检测) | IMU 加速度为 g 单位时设 9.80665 | config_ros.json |
random_downsample_target | 10000 | 每帧降采样目标点数,降到 5000 可显著提速 | config_preprocess.json |
k_correspondences | 10 | 协方差估计的邻域点数;VLP16 这类稀疏线数雷达建议 15~30 | config_preprocess.json |
voxel_resolution | 0.25 m | GPU VGICP 基础体素分辨率,室内取 0.1~0.25 | config_odometry_gpu.json |
voxelmap_levels | 2 | 多分辨率层级,调大提升大位移鲁棒性(2 或 3) | config_odometry_gpu.json |
max_num_keyframes | 15 | 关键帧上限,调大减少里程计漂移 | config_odometry_gpu.json |
keyframe_update_strategy | OVERLAP | 改DISPLACEMENT后按位移阈值插入关键帧,更直观好调 | config_odometry_gpu.json |
smoother_lag | 5.0 s | 固定滞后平滑窗长 | config_odometry_gpu.json |
ivox_resolution | 0.5 m | CPU GICP 体素分辨率,室外调大(如 1.0) | config_odometry_cpu.json |
min_implicit_loop_overlap | 0.2 | 隐式闭环的重叠率门槛,调小=约束更多 | config_global_mapping_*.json |
submap_voxel_resolution | 0.5 m | 子图体素分辨率,室内建议 0.15~0.25 | config_sub/global_mapping_*.json |
一个实用技巧:怀疑协方差估计时,把标准查看器的color_mode改成NORMAL,平面上点色均匀说明协方差正常(参数文档 推荐的健康度检查)。
🔍 遇到问题时:自检清单
按出现频率从高到低排:
- 轨迹整体歪 / 旋转不对:九成是
T_lidar_imu外参或 IMU 坐标系问题。把 IMU 静置且 z 轴朝上,静置加速度读数应约为[0, 0, +9.81](参数文档 的验收标准);config_odometry_gpu.json里validate_imu默认开启,会输出 IMU 校验日志。 - 稀疏线数雷达(如 VLP16)估计退化:
k_correspondences从 10 提到 15~30,用上面的NORMAL颜色模式验证协方差。 - 改了配置不生效(ROS2):重新
colcon build,或启动时传--ros-args -p config_path:=$(realpath ./config)直接指向包外配置目录。 - 想用 AVX 加速却段错误:
BUILD_WITH_MARCH_NATIVE=ON要求所有相关库都用march=native编译,漏一个就会崩;官方建议不确定时保持关闭(安装文档)。 - 用立体视觉 RGB-D(D455、ZED2i)效果差:这是已知边界——这类相机的点云质量本身不佳,而 GLIM 基于点云匹配,demo 文档 明确建议立体传感器改用视觉 SLAM。
- 老显卡跑不起来:当前版本不支持 CUDA 11 及以下,升级 CUDA 或退回 CPU 组合。
进阶:手动修图与二次开发
手动补闭环和平面约束
全局建图只做隐式闭环,地图局部失败时可以人工兜底。offline_viewer里(quickstart 文档 有逐步说明):
- 手动闭环:右键一个子图球选
Loop begin,再右键另一个选Loop end,把红/绿点云大致对齐后点Align执行配准,满意再点Create Factor把约束加入因子图; - 平面 BA 约束:右键平面上的点选
Bundle Adjustment (Plane),拖动球体大小覆盖足够多的平面点,再Create Factor——适合走廊、墙面这类重复结构场景; - 改完点
Optimize重跑优化,File → Save → Export Points导出 PLY 点云。
多段轨迹合并成一张大地图
多次建图会话可以在offline_viewer里合并(合并文档):File → Open New Map打开第一段,Open Additional Map打开第二段,点Merge sessions选 Indoor/Outdoor 参数集,Run global registration(或手动 Gizmo 对齐)→Run fine registration精配准 →Create factor,再用Find overlapping submaps建立重叠子图间的代价因子,多次Optimize融合。注意:合并前若某段地图报X34 -> E69 is missing之类的 warning,要先用Recover graph逐段修复再合并,否则优化结果可能损坏。
用回调插槽扩展自己的功能
GLIM 的扩展机制是"全局回调插槽":里程计、子图、全局建图各自暴露一组回调,你以动态库形式注册进去,就能读取内部状态、往因子图里塞新约束(机制详解见 扩展文档)。最小骨架长这样:
class MyExtensionModule : public ExtensionModule { public: MyExtensionModule() { using std::placeholders::_1; OdometryEstimationCallbacks::on_new_frame .add(std::bind(&MyExtensionModule::on_new_frame, this, _1)); } void on_new_frame(const EstimationFrame::ConstPtr& frame) { // 拿到最新帧位姿,可在这里向因子图插入自定义约束 } }; extern "C" ExtensionModule* create_extension_module() { return new MyExtensionModule(); }编译成.so后,把库名加进 config/config_ros.json 的extension_modules数组即可加载(注意:三个模块跑在不同线程,回调可能来自不同线程,扩展代码要自己保证线程安全)。官方示例库 glim_ext 提供过显式闭环检测(ScanContext / DBoW)、LiDAR-视觉-惯性里程计、GNSS 约束、速度抑制因子等实现,扩展文档 有清单;提醒一下:那些是 proof-of-concept 代码且各自带外部依赖,接入前先看许可证。地图编辑(手动选点剔除)见 edit 文档。
最后收个尾:GLIM 的路线很清晰——传感器无关的预处理 + 可插拔的三级估计模块 + 因子图全局优化 + 离线人工修图兜底,你从改三行 JSON 开始就能出第一张闭环一致的点云地图,遇到漂移也有明确的手动修正路径。
同时说清它不擅长什么:立体视觉 RGB-D(D455/ZED2i 这类)和纯视觉、无深度信息的场景不适合用它;没有 IMU 时只剩纯 LiDAR 的 CT 里程计,没有 GPS 辅助的绝对定位能力;显式闭环检测不在主库内,依赖扩展库或手动操作;GPU 路径要求 CUDA 12.2 以上,Docker 镜像目前只有 AMD64。如果你的场景落在这几条边界外,选方案前先读一遍 demo 文档 里的官方说明再定。
【免费下载链接】glimGLIM: versatile and extensible point cloud-based 3D localization and mapping framework项目地址: https://gitcode.com/GitHub_Trending/glim/glim
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考