30分钟跑通LIO-SAM激光惯性里程计:安装、数据到排错的完整指南
【免费下载链接】LIO-SAMLIO-SAM: Tightly-coupled Lidar Inertial Odometry via Smoothing and Mapping项目地址: https://gitcode.com/GitHub_Trending/li/LIO-SAM
激光惯性SLAM的难点常常不在算法本身,而在环境、数据格式和IMU外参这三件事上。LIO-SAM(Tightly-coupled Lidar Inertial Odometry via Smoothing and Mapping)就是一个典型:源码只有 4 个 .cpp 文件,但装不对 GTSAM 版本、点云缺time字段、外参符号写反,任何一种都会让轨迹变成锯齿。下面按"先跑起来、再调参数"的顺序,把从裸机到出图的全流程走一遍,每个环节都给出验证方法,方便你卡住时知道卡在哪一步。
读完之后你可以做到:
- 用原生 ROS 或 Docker 两条路径之一装好 LIO-SAM,并能验证编译成功
- 用官方示例数据回放,在 Rviz 里看到实时轨迹与全局地图
- 为自己的雷达(velodyne / ouster / livox)切换传感器配置
- 看懂并正确填写
extrinsicRot与extrinsicRPY两个外参矩阵 - 面对 Z 字轨迹、上下跳变、进程崩溃、GPS 无输出这四种症状,直接定位到原因
1 先看效果:LIO-SAM 实时建图演示
LIO-SAM 在 Livox Horizon 数据上的激光惯性里程计演示:轨迹播放的同时全局地图持续生长
效果如上:Rviz 里同时有两条信息源——随机器人移动的点云地图,以及不断闭合修正的全局轨迹。它能在最高 10 倍实时速度下运行,核心是系统里同时维护两张因子图:
- mapOptimization(src/mapOptmization.cpp):全程持续维护,优化激光雷达里程计因子与 GPS 因子,负责全局地图
- imuPreintegration(src/imuPreintegration.cpp):周期性重置,对 IMU 做预积分并估计 IMU 偏置,按 IMU 频率输出实时里程计
LIO-SAM 系统架构:imageProjection 做点云去畸变,双因子图分别负责全局建图与 IMU 频率下的实时定位
2 安装前先排雷:四个最常见的坑
正式装环境之前,把下面四条先记住,能省掉后面大量排查时间。
雷区 1:GTSAM 版本必须走指定 PPA。因子图求解依赖 GTSAM(Georgia Tech 的平滑与建图优化库)。用发行版自带的或手动编译的其他版本,mapOptimization进程大概率直接崩溃。正确来源只有一个:ppa:borglab/gtsam-release-4.0。
雷区 2:只认 9 轴 IMU。和 LOAM 一样,LIO-SAM 用 IMU 的 roll/pitch 初始化姿态、yaw 配合 GPS 初始化航向,6 轴 IMU 无法提供完整姿态。特别注意 Ouster 系列自带的是 6 轴 IMU,必须外挂一个 9 轴的。
雷区 3:点云必须带time和ring两个字段。点云去畸变(把一帧内不同时刻采到的点修正到同一时刻的位姿)靠time字段给出每个点在扫描内的相对时间——10Hz 的雷达扫一圈 0.1 秒,所以这个字段取值应在 0~0.1 之间;ring字段标明点属于哪个激光通道,用于把点排进矩阵。新版 Velodyne 驱动直接输出这两个字段;换用其他雷达时,可能要在 src/imageProjection.cpp 顶部改字段名。
雷区 4:外参有"两个",而且可能不一样。params.yaml里extrinsicRot和extrinsicRPY看起来重复,原因是不少 IMU 的加速度计和姿态解算输出的坐标系不一致(作者用的 Microstrain 3DM-GX5-25 就是这种)。如果你的 IMU 两者坐标系相同,两个矩阵填一样的值即可。
3 环境准备:两条路线任选
官方在 ROS Kinetic 和 Melodic 上做过测试,Noetic 需要社区额外处理,新机器上装 ROS Melodic 最稳。
路线 A:原生编译
先装三个 ROS 功能包,再装 GTSAM:
sudo apt-get install -y ros-melodic-navigation sudo apt-get install -y ros-melodic-robot-localization sudo apt-get install -y ros-melodic-robot-state-publisher sudo add-apt-repository ppa:borglab/gtsam-release-4.0 sudo apt install libgtsam-dev libgtsam-unstable-dev然后拉代码并编译:
cd ~/catkin_ws/src git clone https://gitcode.com/GitHub_Trending/li/LIO-SAM cd .. catkin_make最后把两行 source 写进~/.bashrc:
source /opt/ros/melodic/setup.bash source ~/catkin_ws/devel/setup.bash怎么算成功:重新开终端,执行rosrun lio_sam imageProjection,看到"等待点云"一类的报错而不是"找不到命令",说明库和可执行文件都就位了。
路线 B:Docker 容器
不想污染系统环境的走容器,仓库根目录自带 Dockerfile,基于osrf/ros:kinetic-desktop-full-xenial,依赖和编译步骤已经全部写好:
docker build -t liosam-kinetic-xenial .构建完成后启动容器,挂载本地时间、时区和 X11 以便显示 Rviz:
docker run --init -it -d \ -v /etc/localtime:/etc/localtime:ro \ -v /etc/timezone:/etc/timezone:ro \ -v /tmp/.X11-unix:/tmp/.X11-unix \ -e DISPLAY=$DISPLAY \ liosam-kinetic-xenial \ bash怎么算成功:docker exec -it <容器名> bash进入容器,rosrun lio_sam imageProjection能正常启动并等待输入。
4 首次运行:用示例数据验证安装
编译通过不等于装好了——数据链路(话题名、字段名、外参)才是重灾区。先跑一遍官方示例数据,确认整条链路通了,再碰自己的数据。
README 的 Sample datasets 一节提供了几组示例包,其中 walking / park / garden 三组按默认配置就能跑;rotation / campus 两组需要改话题名和外参(见第 5 节)。以其中任意一组的 bag 为例:
roslaunch lio_sam run.launch另开终端回放,3 倍速:
rosbag play your-bag.bag -r 3怎么算成功:Rviz 中Map (cloud)随移动持续增长、轨迹连成线;命令行里odometry/imu话题按 IMU 频率稳定输出(可用rosrun rqt_graph rqt_graph或rostopic hz odometry/imu确认)。如果轨迹正常,说明安装、话题、外参三者全部对齐。
验证通过后,可以用服务把当前地图存成 PCD 文件:
rosservice call /lio_sam/save_map 0.2 "/Downloads/LOAM/"参数顺序是 [服务名] [点云分辨率] [保存路径],分辨率 0.2 米适合户外场景。
5 参数调优:config/params.yaml 导读
全部配置集中在 config/params.yaml,按"改哪个组"来读它。
数据源:话题名对齐
pointCloudTopic: "points_raw" imuTopic: "imu_raw"这两个值必须和你 bag / 驱动实际发布的话题一致。官方 rotation、campus 两组数据发布的是imu_correct,且数据已经按 ROS REP105 对齐,此时要把imuTopic改成"imu_correct",并把下面两个外参矩阵都改成单位阵。
传感器类型:换雷达时改这里
sensor: velodyne # 'velodyne' 或 'ouster' 或 'livox' N_SCAN: 16 # 通道数 Horizon_SCAN: 1800 # 水平分辨率 downsampleRate: 1 # 点太密时加大,如 64线改 4常用组合:16 线 Velodyne 是 16/1800;Ouster OS1-128 是 128/1024;Livox Horizon 是 6/4000。点云过密导致降速时,优先调大downsampleRate而不是动其他参数。
IMU 外参:最关键也最容易错
extrinsicTrans: [0.0, 0.0, 0.0] # IMU 相对雷达的平移 extrinsicRot: [...] # 加速度/陀螺数据从 IMU 系到雷达系的旋转 extrinsicRPY: [...] # 姿态角数据用的旋转,可能与上一项不同LIO-SAM 内部按雷达坐标系(REP105:x 向前、y 向左、z 向上)工作,IMU 原始数据要经过这两个矩阵变换过来。默认值对应的是作者的 Microstrain 3DM-GX5-25,你的设备大概率要重新标定——标定时把加速度、姿态两套外参分开确认,填完后按下一节的调试方法验证。
性能与节奏
numberOfCores:建图优化用的 CPU 核数,按机器实际调整mappingProcessInterval:建图频率(秒),调大省 CPU 但地图更新变慢odometrySurfLeafSize/mappingCornerLeafSize/mappingSurfLeafSize:体素滤波粒度,注释里已标注户外/室内两套默认值
回环检测
把loopClosureEnableFlag设为true后,回环基于 ICP 在历史关键帧子图上求解,频率由loopClosureFrequency控制。回环生效后要在 Rviz 里取消勾选Map (cloud)、勾选Map (global)才能看到修正后的全局地图(前者只是点云堆叠,位姿修正后不会更新)。ICP 较慢,开回环测试时建议把回放速度降到-r 1。
Ouster OS1-128 雷达:接入 LIO-SAM 时自带 6 轴 IMU 不可用,需外挂 9 轴 IMU
6 接入自己的数据
示例包跑通后,换成自己的采集数据时,只核对两类东西。
点云侧:确认驱动输出的点云包含"扫描内相对时间"和"通道号"两个字段且命名与代码一致。Ouster 用户额外注意:驱动 launch 文件里把timestamp_mode设为TIME_FROM_PTP_1588,点云才会带 ROS 格式时间戳。
IMU 侧:频率上 200Hz 是推荐下限,500Hz 最佳——系统精度对 IMU 数据质量非常敏感。外参配好后做一次人工验证:把 src/imageProjection.cpp 中imuHandler()里的 debug 打印打开,手持设备做俯仰、横滚、转弯动作,观察输出的加速度和角速度方向是否与动作一致。
LIO-SAM 的 IMU 数据变换链:IMU 系经外参旋转到雷达系(REP105),加速度与姿态角分别使用 extrinsicRot 与 extrinsicRPY
用 KITTI 车载数据的话,仓库提供了 config/doc/kitti2bag/ 下的 python 脚本,把 raw 数据转成 bag;对应参数(KITTI 的 64 线、外参等)见 README 的 KITTI 小节。
7 排错速查:按症状找原因
| 症状 | 最可能原因 | 处理动作 |
|---|---|---|
| 轨迹 Z 字、来回抖动 | 雷达与 IMU 时间戳未对齐 | 检查采集时的时间同步机制,确认两者时钟同源 |
| 一启动 base_link 就上下跳 | IMU 外参符号错,重力方向反了 | 核对extrinsicRot/extrinsicRPY,用 debug 打印验证静止时加速度应为 +9.8 左右 |
mapOptimization进程崩溃 | GTSAM 版本不对 | 卸载现有版本,严格按第 3 节的 PPA 重装 |
| GPS 里程计无输出 | 坐标系 tf 断链 | 确认imu_frame_id、gps_frame_id到base_link的变换可用,参考 robot_localization 的传感器数据准备文档 |
| 开了回环但地图不修正 | 看错了可视化层,或 ICP 没跑起来 | Rviz 切到Map (global);回放降到-r 1观察 |
8 接下来做什么
- 把自己雷达和 IMU 的真实话题名、通道数、外参填进 config/params.yaml,录一小段 30 秒 bag 回放验证,再跑长数据。
- 如果要上车载或做精度评估,用 config/doc/kitti2bag/ 的脚本把 KITTI raw 数据批量转成 bag 对比效果。
算法与因子图设计的完整推导在仓库内的 paper.pdf(IROS 2020),遇到第 7 节表格之外的异常时,结合两张因子图的数据流定位,通常比逐行读代码更快。
【免费下载链接】LIO-SAMLIO-SAM: Tightly-coupled Lidar Inertial Odometry via Smoothing and Mapping项目地址: https://gitcode.com/GitHub_Trending/li/LIO-SAM
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考