LIO-SAM 算法从入门到部署实践
1. LIO-SAM 概述
LIO-SAM (Lidar Inertial Odometry via Smoothing and Mapping) 是TixiaoShan在2020年IROS会议上提出的一种紧耦合的激光雷达惯性里程计系统,通过因子图优化方法,融合激光雷达、IMU以及可选的GPS数据,实现了高精度的定位与建图,源码及论文:https://pan.baidu.com/s/1wTwTyd9Weyc6zLV3LGkPwQ?pwd=zhan
相比之前的LeGO-LOAM,LIO-SAM主要有这些优势:
- 紧耦合集成IMU:通过IMU预积分提供初始估计并对点云进行运动补偿,显著提高了系统的鲁棒性和精度。
- 因子图优化框架:后端优化包含IMU预积分因子、激光雷达里程计因子、GPS因子和回环检测因子,实现了多传感器信息的深度融合。
- 更高的输出频率:里程计以IMU的频率输出(需要在收到雷达里程计信息后),使得前端频率更高。
- 更好的回环检测:基于位置关系选择回环帧,并通过点云匹配计算回环因子,有效减小了累积误差。
2. 环境配置与安装
LIO-SAM有两个版本,ROS1版本相对完整,ROS1官方默认支持Ubuntu16.04的kinetic,ROS2官方版本默认支持 Ubuntu 20.04的foxy及galactic和Ubuntu 22.04 的humble ,不过正常在Ubuntu 16.04到22.04系统上应该都可以,以下是详细的步骤:
2.1 安装ROS:
按照ROS官方Wiki指导安装ROS1/ROS2版本,参考ROS和Ubuntu对应关系
# 对于ROS xxx (Ubuntu)
sudo apt-get install -y ros-xxx-navigation
sudo apt-get install -y ros-xxx-robot-localization
sudo apt-get install -y ros-xxx-robot-state-publisher# 对于ROS noetic(Ubuntu 20.04)
sudo apt-get install -y ros-noetic-navigation
sudo apt-get install -y ros-noetic-robot-localization
sudo apt-get install -y ros-noetic-robot-state-publisher
2.2 安装GTSAM(建议4.0.2或4.0.3版本):
# 从GitHub克隆源码
git clone https://github.com/borglab/gtsam.git
cd gtsam
mkdir build && cd build
# 编译安装。注意:DGTSAM_BUILD_WITH_MARCH_NATIVE选项设为OFF以避免一些兼容性问题
cmake -DGTSAM_BUILD_WITH_MARCH_NATIVE=OFF ..
sudo make install -j4 # -j4表示使用4个线程编译,可根据CPU核心数调整
2.3 LIO-SAM源码
mkdir -p ~/catkin_ws/src
cd ~/catkin_ws/src
git clone https://github.com/TixiaoShan/LIO-SAM.git
cd ..
catkin_make # ROS1使用
colcon build # ROS2 使用
2.4 ROS2可能的编译及兼容性问题(跟Lego-loam一致):
- 标准C++和boost不兼容错误:lio-sam/src/imuPreintegration.cpp(r214),boost::shared_ptr 改为 std::shared_ptr,并增加#include
- 标准C++ 11不兼容错误(cc1plus):在lio-sam/CMakeLists.txt的find_package后,增加对c++11支持,set(CMAKE_CXX_STANDARD 11)
set(CMAKE_CXX_STANDARD_REQUIRED ON) - 格式不一致警告:lio-sam/src/mapOptmization.cpp(r1741),增加强制类型转换static_cast(cloudKeyPoses6D->size())
- 变量定义警告:lio-sam/src/mapOptmization.cpp(r365-366),删除变量unused
3. 算法解析
LIO-SAM的系统框架主要包含以下几个关键模块,它们通过因子图优化紧密耦合:
模块名称 | 核心功能 | 关键技术点 | 与其他模块的协作 |
---|---|---|---|
图像投影 | 点云预处理、运动畸变去除 | 检查点云"ring"和"time"字段;利用IMU数据去畸变 | 接收原始点云和IMU数据;为特征提取提供去畸变点云 |
特征提取 | 从点云中提取平面和边缘特征 | 基于曲率计算进行特征分类 | 接收去畸变点云;为激光里程计提供特征点 |
激光里程计 | 特征匹配与帧间位姿估计 | 前后帧特征匹配(平面/边缘);IMU预积分提供初值 | 接收特征和IMU数据;输出帧间约束到位姿优化 |
位姿优化 | 融合各传感器数据并进行位姿优化 | 因子图优化(IMU、激光、GPS、回环);IMU偏置估计 | 接收所有传感器约束;输出优化后的位姿和地图 |
-
点云预处理与运动畸变校正:LIO-SAM利用高频IMU数据对激光雷达扫描过程中的运动畸变进行校正,这一步对于低速或剧烈运动的平台尤为重要。
-
IMU预积分:IMU数据在因子图中以预积分的形式提供约束,不仅提供了帧间运动的初始估计,还可以估计IMU的零偏。
-
因子图优化:这是LIO-SAM的核心,它融合了四种约束因子:
- IMU预积分因子:提供帧间的运动约束。
- 激光里程计因子:来自特征匹配的位姿约束。
- GPS因子(可选):当GPS信号可用时,提供全局位置约束,防止累计误差漂移。
- 回环检测因子:当检测到回环时,提供位姿约束,校正累积误差。
-
地图管理:LIO-SAM维护一个全局地图,但为了效率,匹配时使用的是局部地图而非全局地图,这大大加快了处理速度。
4. 官方数据集
成功编译LIO-SAM后,下一步就是用官方数据集测试,直观感受其性能。
数据集下载:
LIO-SAM的官方数据集通常存储在Google Drive,国内下载可能不便,可以尝试百度网盘:https://pan.baidu.com/s/1o8AM52xmSeuVqQB0O6vo_A?pwd=zhan,常用的数据集包括:
- casual_walk_2.bag:最简单,通常无需修改参数即可运行。
- outdoor.bag 和 west.bag:需要修改参数。
- park.bag:包含GPS数据,可用于测试GPS融合。
运行数据集:
启动LIO-SAM节点:
source ~/catkin_ws/devel/setup.bash
roslaunch lio_sam run.launch
播放数据集:
# 在新终端中(以outdoor.bag为例)
rosbag play outdoor.bag
参数调整 (针对不同数据集):
-
对于outdoor.bag和west.bag,通常需要修改params.yaml配置文件:
- 将imuTopic从"imu_raw"改为"imu_correct"。
- 将extrinsicRot和extrinsicRPY(雷达与IMU之间的旋转外参)设置成单位矩阵。
-
对于包含GPS的数据集park.bag:
- 将gpsTopic从"odometry/gpsz"改为"odometry/gps"。
- 将useImuHeadingInitialization从false改为true,这对于GPS数据的正确处理至关重要。
保存地图:
如果想要保存生成的地图,可以在params.yaml中进行如下设置:
savePCD: true
savePCDDirectory: "/home/suo/Downloads/lio/" # 替换为你想要的保存路径,路径前后需有"/"
注意:保存地图可能需要较长时间。如果地图过大,ROS节点可能在保存完成前就被关闭。此时可以尝试调整ROS的_TIMEOUT_SIGINT参数(例如从默认的15秒改为60秒),该参数通常在/opt/ros/你的ROS版本/lib/python2.7/dist-packages/roslaunch/nodeprocess.py文件中。
5. 机器人部署
这是最富挑战性也最有价值的环节,即将LIO-SAM应用于你自己的机器人平台。
5.1 硬件准备与数据采集
传感器要求:你需要一个3D激光雷达(如Velodyne、Ouster或Livox)和一个IMU。IMU与雷达之间的外参(相对位置和姿态)需要尽量准确地获得,可以通过标定得到。
数据录制:使用rosbag record命令录制你机器人移动时的传感器数据,确保同时录制激光雷达点云话题和IMU话题。
5.2 关键配置与参数调整
机器人平台必然与官方数据集不同,因此需要修改LIO-SAM的配置文件params.yaml:
传感器话题名称:将pointCloudTopic、imuTopic等参数修改为你的传感器实际发布的话题名称。你可以使用rostopic list命令来查看。
外参标定:
- extrinsicTrans:IMU到雷达的平移外参,需要根据实际测量或标定结果填写。
- extrinsicRot 和 extrinsicRPY:IMU到雷达的旋转外参。这是最容易出错的地方之一。如果设置不正确,可能会导致系统发散。对于许多设备,这两个矩阵可以都设置为单位矩阵,但有些设备可能需要不同的旋转。
- 传感器参数:根据你的雷达型号(线数、视场角、频率等)和IMU型号,调整相应的参数。
5.3 适配自定义数据(核心难点)
LIO-SAM在imageProjection.cpp中会严格检查输入的点云数据是否包含ring和time字段:
- ring:表示激光点所属的线束序号(例如16线雷达的ring值从0到15)。
- time:表示当前激光点相对于该帧点云第一个点的扫描时间戳,用于运动畸变校正。
如果点云缺少这两个字段,程序会报错并退出,解决方法通常有两种:
- 修改驱动或转换节点:确保你的雷达驱动发布的点云消息中包含这两个字段。或者,编写一个转换节点,根据点云的物理特性(如垂直角度推断ring,根据扫描时间规律计算time)来补全这两个字段。
- 修改LIO-SAM源码(不推荐初学者,但有时不可避免):注释掉检查ring和time的代码段,但这可能会影响运动畸变校正的效果,需要非常谨慎。
5.4 运行与调试
像运行官方数据集一样启动bag包,密切观察RViz中的可视化结果。如果出现轨迹发散、地图错乱等问题,需要耐心调试,常见问题与排查:
- “Large velocity, reset IMU-preintegration”:外参不准(特别是旋转外参)是导致这个错误的常见原因。请重新检查并校准IMU和雷达之间的外参。
- 轨迹漂移严重:尝试调整因子图中各约束的权重参数;检查IMU数据的质量和时间同步。
- 系统运行缓慢:点云数量过多可能导致处理延迟。可以尝试在params.yaml中调整点云降采样的参数。