☰
ROS2下LIO-SAM与MID360建图实战:从数据集到真机全解析
2026/9/28 3:51:28 网站建设 项目流程

LIO-SAM在ROS2下建图这事儿,说难不难,说简单也真不简单。我最近一个项目就是用MID360做室内外场景下的建图,一开始想着先用官方walking_dataset把算法链路跑通,再切到真机上,结果在数据集转换、topic对齐、时间戳同步这些环节上硬生生耗了两周。今天把这条完整路线整理出来——从walking_dataset入手熟悉LIO-SAM的ROS2移植版,再到MID360驱动适配、Gazebo仿真验证、真机建图踩坑,一条线讲清楚。适合已经在ROS2里写过几个节点、想开始上手激光惯性SLAM建图的朋友。

1. 整体设计思路:为什么从walking_dataset起步,终点是MID360

1.1 LIO-SAM在ROS2生态下的现状

LIO-SAM是激光惯性紧耦合里程计算法的代表作之一,核心思路是把IMU预积分、激光里程计、回环检测和GPS因子统一放到因子图里做优化,输出低漂移的位姿轨迹和全局点云地图。官方实现是基于ROS1的,GitHub上star量很高,但ROS1已经停止维护,现在新项目基本都是Ubuntu 22.04加ROS2 humble起步,所以直接用ROS2移植版属于刚需。

ROS2移植版和ROS1原版在算法核心上区别不大,主要差异集中在消息传递、tf树管理、launch机制和参数系统上。ROS2用的rclcpp API、参数声明机制、launch文件变成Python,这些都是接触ROS2移植版时最先遇到的问题。不过好消息是,只要把topic对应关系理清楚,算法本身的参数和配置思路完全可以沿用ROS1时代的经验。

1.2 为什么选walking_dataset做第一站

walking_dataset是LIO-SAM作者发布的经典数据集,用Velodyne VLP-16采集,包含激光点云和IMU数据,内容是一段手持设备在室内外行走的轨迹。选它有两个原因:一是数据是现成的rosbag,不需要自己准备硬件,下载解压就能跑;二是数据集里包含了比较丰富的场景特征,有走廊、墙面、拐角,能明显看出建图效果的好坏。

更重要的是,这个数据集在官方仓库里配套了完善的话题配置和参数文件。你在ROS2下移植时,只需要对照着把rosbag从ROS1格式转成ROS2格式,再把launch里的topic映射调整正确,就能得到一个“标准答案”一样的效果。这对于验证移植代码是否正确、算法链路是否通畅,非常有价值。

1.3 终点为什么是MID360

MID360是Livox推出的一款混合固态激光雷达,水平视场角360度、垂直约59度,采用非重复扫描方式,点云覆盖密度比传统机械式雷达均匀得多。它的量程、精度和成本对室内外建图项目来说很均衡,而且自带IMU,省去了外挂IMU的标定和固定问题。实际用下来,在走廊、拐角这种重复纹理比较少的场景里,非重复扫描方式反而能扫到更多角落点,建出来的地图边缘更干净。

不过MID360也有它自己的麻烦:默认发布的点云是自定义格式还是标准PointCloud2、内置IMU的时间戳机制、初始外参的标定,这几个点如果没处理好,LIO-SAM不但建不出好图,还可能出现轨迹漂移甚至发散。后面我会把每一个坑挨个展开。

2. 环境准备:ROS2 humble、gtsam与lio-sam-ros2编译

2.1 ROS2 humble环境与基础依赖

建议直接用Ubuntu 22.04加ROS2 humble。安装方式通常两种,一种是自己配apt源按官方文档装,另一种是用社区的一键安装脚本,可以省很多事。不管用哪种,装完记得验证一下环境:ros2 topic list能正常输出、rviz2能打开,基础环境基本就没问题了。

LIO-SAM的ROS2移植版依赖几个ROS2核心包,包括pcl_ros、pcl_conversions、tf2_ros、robot_state_publisher、nav_msgs、sensor_msgs、geometry_msgs和visualization_msgs。这些直接用apt把ros-humble对应包装齐就行,不需要自己从源码编,省时间也省心。

2.2 编译gtsam:最容易卡住的依赖

LIO-SAM的核心因子图优化依赖gtsam,这是一个专门做平滑和建图的C++库。ROS2移植版通常要求gtsam 4.x版本,部分系统源里自带的版本可能不满足要求,或者干脆没有这个包,所以更稳妥的做法是源码编译。

编译gtsam有几个注意点:cmake版本不要太老,安装Boost和TBB开发库,编译时建议设置-DGTSAM_BUILD_TESTS=OFF -DGTSAM_BUILD_UNSTABLE=OFF减少编译时间。我自己的机器上全核编译大概花了十几分钟,中间因为缺少libtbb-dev报过一次错,装上后重编就通了。这步看着简单,但环境不一致时最容易卡住。

2.3 编译lio-sam-ros2:常见坑点

从GitHub上拉取ROS2移植版后,放到你的ros2工作空间src目录下,用colcon build编译。编译前确保工作空间环境已source,并且上面的ROS2依赖都已经安装。

我遇到的第一个坑是Eigen和PCL头文件路径冲突。Ubuntu 22.04自带的PCL版本较新,跟LIO-SAM源码里某些旧的类型转换写法不一致,编译时会报no matching function for call。解决办法一般是升级源码里的转换写法,比如把pcl::fromPCLPointCloud2相关调用改成兼容新接口的形式,或者干脆用社区已经适配好的较新fork版本。如果不想折腾源码,优先选择活跃维护的fork,能少踩很多编译层面的坑。

编译通过后,先别急着跑算法,花十分钟看一下工程里的params.yaml和launch文件,搞清楚默认的topic名和后处理参数,这是接下来调数据的基础。

3. walking_dataset实战:从rosbag到第一张完整地图

3.1 数据集获取与rosbag格式转换

walking_dataset在LIO-SAM官方仓库的README里可以找到下载入口,下载后是一个ros1格式的bag文件。在ROS2里想直接播放它,第一步要做的就是格式转换。

ros2本身没有一键转换工具,社区常用的是rosbags这个Python库。安装后用命令行即可转换:rosbags-convert --src walking_dataset.bag --dst output_dir。转换过程会自动处理消息类型映射,把ROS1的topic转成ROS2格式。转换完用ros2 bag info查看convert后的目录,确认话题列表和时间戳信息都正常。

话题类型上有个细节:VLP-16在ROS1下可能发布的是velodyne_msgs/VelodyneScan原始数据包,但LIO-SAM需要的是解析后的点云话题(sensor_msgs/PointCloud2)。walking_dataset这个数据集本身已经发布了PointCloud2类型的点云话题,所以转换后直接能用。如果你以后自己录制VLP-16数据,需要先用velodyne驱动把原始包解析成点云再喂给LIO-SAM,这一步不能省。

3.2 修改params.yaml把topic对齐

LIO-SAM的ROS2移植版参数文件里,最核心的几项是:

pointCloudTopic: "points_raw" imuTopic: "imu/data" odomTopic: "odometry/imu" gpsTopic: "gps/fix"

不同fork版本命名可能略有差异,但核心概念一致。跑walking_dataset时,先执行ros2 bag info看看bag里实际的topic名。通常walking_dataset发布的是/points_raw和/imu/data,如果实际名称有出入,要把params.yaml里的topic配置改成bag里的真实名称。

这里有个容易忽略的点:topic名别带前导斜杠。LIO-SAM内部拼接topic时如果处理不当,带不带斜杠会影响匹配结果。我遇到过参数里写/points_raw导致订阅失败的情况,改成points_raw后一切正常。这类问题排查起来很隐蔽,建议一开始就养成不带前导斜杠的习惯。

3.3 启动、播放、验证建图效果

确认参数无误后,启动方式分两步。先在一个终端启动LIO-SAM:

ros2 launch lio_sam run.launch.py

再开另一个终端播放bag:

ros2 bag play walking_dataset_converted

建议先以0.5倍速播放一次,因为手持设备运动速度较快,第一次跑电脑CPU负载可能较高,慢速播放能让算法跟上数据节奏。打开rviz2后手动添加话题:PointCloud2选择map(或者cloud_registered)、Odometry选择odometry/imu路径、Path选择path。你会看到地图点云和轨迹实时累积。

判断建图成功有几个标志:地图边缘清晰、没有明显的双层重影;位姿轨迹连续平滑;回环闭合时地图没有大幅跳变。如果地图漂移发散,大概率是IMU数据没对齐或参数配置问题,这时先暂停,回头检查topic频率和消息内容,别急着改算法参数。

4. 从VLP-16迁移到MID360:驱动、时间同步与外参调优

4.1 装好livox_ros_driver2,理解MID360点云输出

MID360要用Livox官方驱动livox_ros_driver2。这个驱动支持ROS2 humble,在GitHub上直接拉源码编译即可,依赖项主要是Livox SDK。编译完成后,用launch文件启动,但启动前必须先改配置文件里的雷达IP地址。

MID360出厂默认IP一般是192.168.1.5,电脑网口需要设置在同一网段,比如192.168.1.50。修改好配置文件后启动驱动,用ros2 topic echo /livox/lidar --once检查是否有点云数据输出。

这里有一个重点:livox_ros_driver2默认发布的是Livox自定义点云类型,不是标准PointCloud2。LIO-SAM多数移植版本只认标准sensor_msgs/PointCloud2,所以要么在驱动配置里把pcl_data_type设置成同时发布标准点云,要么自己写一个转换节点把自定义类型转成PointCloud2。转换时注意保留intensity和ring字段,LIO-SAM去畸变依赖这些字段。

4.2 时间同步:MID360建图最隐蔽的坑

MID360内置IMU数据默认由驱动发布在/livox/imu,但如果您做过时间戳检查就会发现,点云中每个点的时间戳和IMU消息时间戳的基准并不完全一致。LIO-SAM在做去畸变时,需要把每一帧点云里每个点的时间偏移和IMU数据做关联,如果时间轴对不上,点云会整体扭曲,地图自然就飘了。

解决方法是开启驱动里的时间同步功能。在livox_ros_driver2的config文件里,把时间同步相关的开关设为true,让点云和IMU统一到近似绝对时间戳。开启后建议用ros2 topic hz /livox/imu和ros2 topic echo /livox/lidar | head再核对一次时间戳是否单调递增且接近当前时间。

实测下来,如果timeSync没开,LIO-SAM跑MID360十分钟后轨迹就开始漂移,地图呈螺旋状发散。开启后同样的数据,地图会立刻稳定下来。这个坑不亲自踩一遍真的很难发现。

4.3 外参设置与参数调优

LIO-SAM的params.yaml里有外参矩阵,包括extrinsicRot、extrinsicTrans和extrinsicRPY。如果你使用的是MID360内置IMU,IMU和激光雷达的物理外参通常比较小,初值可以设为单位阵和零平移。但如果你把IMU安装在别处,这里的值就必须改成实际测量或标定结果。

我个人强烈建议在跑LIO-SAM之前,先做一次IMU与激光雷达的外参标定。不开回环检测的时候,外参误差会直接表现为建图倾斜和轨迹弯曲。标定可以用常见的lidar-imu标定工具,也可以先在平坦场景下通过手动测量粗标定,后续用建图结果微调。

另外,scanPeriod这个参数也很关键。激光雷达通常以10Hz发布点云,scanPeriod就是0.1秒。如果你把MID360的发布频率调整为20Hz,这里就要改成0.05秒,否则去畸变计算的点云扫描周期错误,点云会变成“波浪形”,地图会非常模糊。检查发布频率最直接的方式是ros2 topic hz /livox/lidar。

5. Gazebo仿真验证:没有激光雷达也能跑通LIO-SAM

5.1 仿真环境搭建:URDF、传感器插件与模型

真机调试之前,用Gazebo做仿真验证是个好习惯。仿真能帮你验证launch文件、参数配置和rviz显示链路是否正确,也能在没有硬件的情况下熟悉整个工作流。

最直接的办法是构造一个包含激光雷达和IMU传感器的机器人URDF模型。在Gazebo里给模型添加gpu_ray传感器插件可以生成点云数据,添加imu插件生成IMU消息。Gazebo的点云和IMU话题可以随意配置,让它们和LIO-SAM需要的topic名一致即可。

Livox官方也提供了MID360的仿真模型和Gazebo插件,仿真输出的点云topic可以直接近似模拟真机的/livox/lidar和/livox/imu。你用gazebo加载机器人模型后,手动给机器人一个运动指令,比如绕圈,LIO-SAM就能实时订阅仿真点云和IMU,输出一个理想环境下的地图。

5.2 仿真和真机的差距到底在哪里

仿真环境里点云无噪声、IMU无漂移、时间戳完全同步、外参绝对精准,所以LIO-SAM几乎每次都能跑出漂亮的地图。但这恰恰是“假象”:如果你在仿真里一切正常,换到真机却纷纷出错,不用怀疑算法出了问题,问题一定出在数据链路上。

仿真最大的价值是帮你排除配置层面的低级错误。比如launch文件语法、params.yaml参数是否被正确加载、rviz2里话题显示是否正常,这些问题在仿真阶段暴露和修复的成本最低。但仿真无法帮助你验证真机的时间同步、点云噪声、IMU零偏等物理层面的问题,所以不要因为仿真跑通了就掉以轻心,真机调试该做的检查一步都不能省。

6. 常见问题与排查技巧实录

6.1 建图漂移、发散的排查顺序

建图漂移是玩LIO-SAM遇到最多的问题,也是最让人头疼的。我的排查顺序是这样的:先看数据再谈算法。具体来说:

  • 查看点云消息的frame_id是否和tf树一致
  • 用ros2 topic echo抽查点云和IMU的头部时间戳,确认没有跳变
  • 检查IMU频率是否稳定在设定值附近
  • 检查点云发布频率和scanPeriod是否匹配
  • 最后才考虑外参是否要重新标定

6.2 常见问题速查表

下面这张表是我实际调试中积累的典型问题和对应解法,供参考。

问题现象可能原因检查与解决方法
地图呈螺旋状发散IMU时间戳与点云时间不同步开启MID360驱动的timeSync功能,重新核对两路消息时间戳
地图轨迹正常但地图模糊scanPeriod与点云发布频率不匹配用ros2 topic hz查看真实频率,修正params.yaml
节点启动后立即崩溃params.yaml里参数类型或topic名称错误检查参数类型,确认点云topic有数据后再启动算法
rviz2里看不到点云和轨迹话题名或frame_id不对用ros2 topic list对比期望话题,查看消息frame_id
map建出来有轻微倾斜IMU与雷达外参不准确重新标定外参,或根据建图结果手动微调外参矩阵
回环闭合时地图跳变回环检测参数过于激进或地图噪声大适当降低回环阈值,检查点云去畸变是否正常
livox点云为空雷达IP配置错误或网口未连接确认lidar_ip配置正确,电脑IP与雷达同网段并能ping通

6.3 独家避坑技巧

有一个技巧是很多教程不会提的:在跑LIO-SAM之前,先用ROS2自带的工具把数据录成压缩bag,然后从bag回放调试算法。这样做的最大好处是,怀疑参数不对时可以反复用同一份数据测试,而不用反复搬动设备重新采集。我后面所有MID360的参数调试都是基于录制的bag完成的,效率提升非常明显。

另一个技巧是留意IMU数据要不要做低通滤波或减零偏处理。MID360内置IMU在静止状态下也会有一定的零偏,直接喂给LIO-SAM虽然能跑,但在长时间低速运动时会造成累积漂移。如果你发现静止放置雷达时地图还在缓慢移动,可以先做一次IMU零偏估计,把零偏减掉再进算法。

还有一个经验是关于tf树的。LIO-SAM会发布map到odom、odom到base_link的变换,但MID360驱动通常只发布livox_frame相关的变换。如果tf树不完整,rviz2里所有话题都会飘在原点。建议自己写一个静态tf发布节点,把base_link到livox_frame的固定变换发出来,问题立刻解决。

7. 从数据集到实机的路线复盘与扩展思路

整套流程走下来,我最深的体会是:LIO-SAM这类开源SLAM算法,代码层面的门槛其实不高,真正的门槛在于数据链路。walking_dataset能顺利建图,不代表换一个雷达就一定能顺利,因为传感器的时间戳机制、点云类型、外参都不一样。所以我才反复强调,先把数据链路检查清楚,再谈调参和算法优化。

就扩展思路而言,这套环境接下来可以做的方向很多。比如在LIO-SAM的基础上接入自定义地图保存逻辑,把建好的点云地图保存成PCD或八叉树地图(OctoMap),为后续导航避障做准备。也可以把GPS因子启用,在有GPS信号的室外场景进一步抑制漂移。ROS2的DDS机制天然支持多机通信,还可以把建图节点跑在机器人上,把地图通过topic实时传回地面站显示,这些都是工程上很实用的能力。

如果你也正在ROS2下折腾LIO-SAM或者MID360,希望这篇文章能帮你少走几天弯路。数据链路排查、topic对齐、时间戳同步、外参初值,这四个关键点搞定,你离一张干净的地图就不远了。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询