MID-360+FAST-LIO2建图实战:ROS1/ROS2驱动配置避坑 简介激光雷达与惯性测量单元IMU融合的SLAM技术是移动机器人在未知环境中实现自主定位与建图的核心方案。以Livox MID-360为代表的混合固态激光雷达凭借非重复扫描与高密度点云特性为室内外复杂场景提供稳定感知基础而FAST-LIO2则通过迭代误差状态卡尔曼滤波紧耦合点云与IMU数据在低算力下输出干净地图。二者的工程落地依赖 Livox-SDK2 与 Livox-ros-driver2 驱动的正确配置尤其是在ROS1与ROS2环境下的版本匹配与话题对齐。本文从环境准备、驱动编译到算法部署完整梳理基于MID-360的实时建图流程总结网络配置、消息类型转换、外参调校等高频坑点适合机器人开发者快速搭建可复用的激光惯性导航系统。 去年我把一台轮式机器人的满血建图方案从零搭起来核心就是雷达到底用什么雷达、怎么驱动、怎么跑里程计。最后定下来的组合是Livox MID-360加上Livox-SDK2、Livox-ros-driver2以及FAST-LIO2。这套东西在圈子里讨论度一直很高但网上资料特别散版本也不统一我第一次装的时候卡了整整两天问题基本都出在SDK版本混乱和驱动消息类型对不上这两件事上。这篇文章就老老实实把我跑通的路径写清楚适合手里有MID-360、想在Ubuntu上做实时建图和定位的朋友参考不管你是ROS1还是ROS2环境都能顺着往下走。先说结论MID-360是一台混合固态激光雷达水平360度视场、垂直59度量程最远70米小体积、轻重量非常适合装在小车或者无人机上做感知。它和上一代Livox H系列最大的区别是不需要“往复摆镜”而是用旋转棱镜实现非重复扫描这样能在低速场景下积累出一个高密度点云覆盖近距离物体的轮廓特别清晰室内外都能用。FAST-LIO2则是港大MARSLab开源的激光惯性里程计框架核心是用迭代误差状态卡尔曼滤波器(IESKF)把激光点云和IMU数据紧耦合起来配合一个增量式ikd-Tree来维护全局地图对算力要求不高建图效果却很干净。把这三个东西串起来就是下面这篇文章的主线。1. 整体方案拆解为什么是这三件套1.1 每个组件的角色MID-360负责输出原始点云和IMU数据。注意它自带一颗BMI088六轴IMU这颗IMU在FAST-LIO2里非常关键因为FAST-LIO2默认会依赖IMU做运动补偿和状态预测没有IMU的纯激光模式虽然也能跑但精度和鲁棒性会掉一个档次。MID-360通过以太网口出数据默认情况下是一个点云数据流加一个IMU数据流点云类型是Livox自定义的livox_ros_driver2::CustomMsg不是标准的sensor_msgs/PointCloud2这一点后面会反复提到。Livox-SDK2是Livox设备在PC端的底层SDK负责网络通信、设备发现、点云解码这些事。MID-360必须用SDK2不能用前一代的Livox-SDK因为硬件协议栈不一样。Livox-ros-driver2则是基于Livox-SDK2封装的ROS驱动层把底层数据转成ROS话题同时处理一些坐标变换和时间戳。FAST-LIO2就是建图定位算法本体。它订阅雷达和IMU话题实时输出当前姿态和点云地图。它算法层面的一个优势在于直接把原始点云和IMU塞进一个滤波框架里处理不需要额外做畸变校正、不需要预积分也不像LOAM系列那样分那么多线程代码结构对新手友好得多。1.2 为什么选这个组合而不是LIO-SAM或CartographerLIO-SAM也可以接MID-360但它依赖GPS和回环检测的配置比较多在室内小场景里优势不大。Cartographer对雷达类型要求很宽松也能接MID-360但它在处理非重复扫描数据时需要额外做自适应体素滤波参数调起来比FAST-LIO2费劲。FAST-LIO2的操作思路很直接启动驱动启动算法看一眼Rviz里的地图完事。它对零基础用户特别友好调试项集中在yaml文件里而且社区活跃度很高遇到问题基本都能在GitHub的issue里搜到。1.3 部署流程总结完整流程分四步准备环境、编译Livox-SDK2、编译Livox-ros-driver2、编译并运行FAST-LIO2。如果你的需求只是让雷达出点云第一步做到第三个就能结束如果你要建图那就继续往下。这篇文章默认读者用的是Ubuntu 20.04或22.04ROS1 Noetic或ROS2 Foxy/Humble硬件就是一台普通的x86工控机或笔记本没有GPU也可以。2. 环境准备该装的依赖一个都不要省2.1 系统、ROS版本和CMake版本我在测试时主力环境是Ubuntu 20.04 ROS Noetic另外在Ubuntu 22.04 ROS2 Humble上也跑通过两个环境用的驱动是同一个源码包只是编译模式不同。系统选择上别太纠结只要别用太老的Ubuntu 18.04就行因为新版PCL和Eigen对18.04的支持已经不够顺手。编译前先把基础工具补齐sudo apt update sudo apt install git cmake build-essential sudo apt install ros-$ROS_DISTRO-pcl-ros ros-$ROS_DISTRO-eigen-conversions ros-$ROS_DISTRO-tf2-eigen如果是ROS2还需要额外安装sudo apt install ros-$ROS_DISTRO-rmw-fastrtps-cpp2.2 检测现有ROS环境检查环境变量是否正常最简单的方式是echo $ROS_DISTRO如果输出空说明你的ROS环境还没source需要在~/.bashrc里加上类似source /opt/ros/noetic/setup.bash这一行。2.3 创建并初始化catkin工作空间ROS1用catkin_makeROS2用colcon。这一篇文章提供两套编译方式先建工作空间mkdir -p ~/mid360_ws/src cd ~/mid360_wsROS1的初始化catkin_init_workspaceROS2不需要catkin_init_workspace直接cd ~/mid360_ws colcon build --symlink-install第一次colcon build会在src为空的情况下生成build、install、log目录先确认一下目录结构没问题就行。3. 编译Livox-SDK2底层库版本错一个上层全废3.1 为什么要强调SDK2Livox官方对早期雷达Horizon、Tele支持的是老版Livox-SDK到了MID-360和HAP必须切换到Livox-SDK2。两个SDK在设备发现协议和点云包格式上完全不同如果装错版本驱动层连设备都枚举不到。网上很多教程还在用老SDK照着抄很容易踩坑。3.2 编译和安装步骤cd ~/mid360_ws/src git clone https://github.com/Livox-SDK/Livox-SDK2.git cd Livox-SDK2 mkdir build cd build cmake .. -DCMAKE_BUILD_TYPERelease make -j$(nproc) sudo make install编译过程基本不会报错唯一需要留意的是cmake版本不能太低3.13以上就行。Ubuntu 20.04自带的cmake是3.16满足要求。安装完成后可以用下面这行命令确认SDK库是否被正确安装ls /usr/local/lib | grep livox正常情况下能看到liblivox_sdk2.so之类的文件。3.3 网络配置和设备发现MID-360默认通过网线连接工控机默认IP是192.168.1.50你的电脑有线网卡需要配一个同网段的静态IP比如192.168.1.100。这一步很多人忽略导致驱动一直提示找不到设备。检查方法是ping 192.168.1.50如果ping不通先看网线是不是直连再看电脑网络管理器里是否手动指定了静态IP。我遇到过一个问题Ubuntu的NetworkManager默认开了DHCP网线插上后自动获取不到地址雷达也不理你。改成Manual之后立刻就能发现设备。4. 编译Livox-ros-driver2ROS1与ROS2的切换开关4.1 获取源码和版本选择cd ~/mid360_ws/src git clone https://github.com/Livox-SDK/Livox-ros-driver2.git这个仓库本身同时支持ROS1和ROS2通过源码里的CMakeLists.txt来控制编译模式。在仓库根目录打开CMakeLists.txt找到类似这样的选项option(BUILD_ROS2 Build for ROS2 OFF)ROS1保持OFFROS2改为ON。4.2 ROS1下编译cd ~/mid360_ws catkin_make source devel/setup.bash编译过程中如果提示找不到livox_sdk2头文件回第3节检查SDK是否安装成功也可以把Livox-SDK2/build/install目录手动加入CMAKE_PREFIX_PATH。4.3 ROS2下编译先改CMakeLists.txt里的BUILD_ROS2为ON然后cd ~/mid360_ws colcon build --symlink-install source install/setup.bash这里有一个常见坑ROS2编译时如果之前已经编译过ROS1版本必须在build和install目录都清掉之后再重新编译否则会残留旧的CMakeCache导致无论如何都编译成ROS1模式。我因为这个浪费了半个小时。4.4 启动驱动验证点云MID-360对应的launch文件是msg_MID360.launchROS1下执行roslaunch livox_ros_driver2 msg_MID360.launchROS2下执行ros2 launch livox_ros_driver2 msg_MID360.launch启动后不要急着跑算法先验证数据# ROS1 rostopic hz /livox/lidar rostopic echo /livox/imu -n 1# ROS2 ros2 topic hz /livox/lidar ros2 topic echo /livox/imu --once如果/livox/lidar频率在10Hz左右说明驱动正常。如果hz输出一直是0大概率是网络配置问题或者设备没上电去查IP地址和网线连接。4.5 驱动话题名和消息类型先记住三件事点云话题是/livox/lidar消息类型是livox_ros_driver2::CustomMsgIMU话题是/livox/imu消息类型是sensor_msgs/ImuRviz中显示点云需要手动把Fixed Frame设为livox_frame订阅话题选/livox/lidar但Rviz不能直接显示CustomMsg所以如果只是想快速看一眼点云用一个转换节点把CustomMsg转成PointCloud2更省事。Livox驱动包里本身就带了这个节点启动时加一个参数就行roslaunch livox_ros_driver2 msg_MID360.launch point_cloud_2:true这样会额外发布一个/livox/points话题消息类型是sensor_msgs/PointCloud2Rviz里直接添加它就能看到点云。5. 编译FAST-LIO2核心算法注意话题名一致5.1 源码获取FAST-LIO2官方仓库路径是hku-mars/FAST_LIO。默认分支是ROS1版本ROS2环境需要使用ros2分支。下载方式cd ~/mid360_ws/src git clone https://github.com/hku-mars/FAST_LIO.git cd FAST_LIO git checkout ros2 # 如果是ROS2环境5.2 依赖检查FAST-LIO2编译依赖PCL和Eigen还有livox_ros_driver2。如果不是在同一工作空间里编译的需要在FAST-LIO2的CMakeLists.txt里手动指定livox_ros_driver2的路径。最省心的做法是把livox_ros_driver2和FAST_LIO都放在同一个工作空间的src目录下一起编译。5.3 ROS1编译FAST-LIO2cd ~/mid360_ws catkin_make source devel/setup.bash如果编译报错找不到livox_ros_driver2/CustomMsg.h多半是因为Fast-LIO源码里include的是livox_ros_driver/CustomMsg.h而新驱动包名带2。打开src/FAST_LIO/src/laserMapping.cpp把include替换成livox_ros_driver2/CustomMsg.h再把包名相关的cmake依赖改一下。5.4 ROS2编译FAST-LIO2cd ~/mid360_ws colcon build --symlink-install --packages-select fast_lio livox_ros_driver2 source install/setup.bashros2分支的话题类型和处理逻辑和ROS1略有不同但用法基本一致。5.5 配置mid360参数文件FAST-LIO2仓库的config目录下默认有mid360.yaml打开看几个关键项common: lid_topic: /livox/lidar imu_topic: /livox/imu time_sync_en: falselid_topic和imu_topic一定要和驱动发布的话题名一致我自己踩过坑驱动话题是/livox/lidar配置文件里写的是/livox/lidar看起来一样但我当时用的是转换后的话题名结果FAST-LIO2一直等不到数据。接下来是外参preprocess: lidar_type: 1 scan_line: 4 blind: 2.0lidar_type: 1表示Livox CustomMsgscan_line: 4在MID-360上通常设4或6不需要特别精细。blind是盲区半径2米以内的点会被过滤掉避免车身自身结构噪点干扰。IMU外参mapping: extrinsic_li: translation: x: 0.0 y: 0.0 z: 0.0 rotation: x: 1.0 y: 0.0 z: 0.0 w: 0.0extrinsic_li表示雷达到IMU的外参单位是雷达系到IMU系的变换。对于MID-360这种一体化设备出厂时雷达和IMU的相对关系固定源仓库默认填的1,0,0,0表示无旋转实际如果雷达水平安装这个值基本不用改。5.6 启动FAST-LIO2先用Rviz可视化参数启动roslaunch fast_lio mapping_mid360.launch然后再开一个终端启动驱动roslaunch livox_ros_driver2 msg_MID360.launch或者反过来先驱动后算法顺序不重要。重要的是两个终端都要source过工作空间。正常启动后Rviz里订阅/cloud_registered话题就能看到实时叠加的彩色点云地图同时算法会发布/Odometry话题里面是每帧的位姿。6. 实操过程从驱动到建图的完整跑通记录6.1 第一步用RViz检查原始点云启动驱动后在Rviz里添加PointCloud2话题/livox/pointsFixed Frame改为livox_frame这一步主要是确认雷达能出数、方向是否正确。拿着雷达在手里晃一晃点云应该跟着动。如果看到点云是反的或者偏转90度不要慌这是正常现象因为雷达坐标系的Z轴朝上而Rviz默认视角是XY平面调整一下视角就行。6.2 第二步跑FAST-LIO2建图算法启动后先让雷达静止5到10秒让初始化收敛。然后慢慢移动雷达或小车速度不要一下拉太高尤其是在刚启动的头几秒里IMU的bias还没有估计稳动作太大会导致地图直接飞掉。我习惯的做法是按S型路线来回走一遍争取把环境的各个方向都扫到建出来的图会明显更均匀。6.3 第三步保存地图FAST-LIO2本身不自动保存地图需要手动从Rviz里导出点云或者用pcl_ros保存Rviz里在/cloud_registered话题上右键选择“Save Point Cloud as Map”或者直接记下点云数据用命令行工具转换更推荐的方式是订阅/cloud_registered并调用pcl的io接口保存pcd文件我提供一个简单的保存节点思路写一个ROS节点订阅/cloud_registered维护一个全局点云收到std_srvs/Empty服务调用时把点云保存为pcd。这样在户外大场景里可以随时手动保存不用开着Rviz。完整的代码在FAST-LIO2的issue里也能搜到很多用户上传过。6.4 稀疏地图输出和ROS2下的可视化差异ROS2下没有原生的rviz叫法但rviz2用法几乎一样。启动FAST-LIO2 ros2分支后同样添加/cloud_registered话题即可。唯一要注意的是Rviz2默认的坐标框架是map而FAST-LIO2发布的地图层是camera_init把Fixed Frame改掉就能对齐。7. 进阶需求双雷达融合与倾斜安装坐标对齐标题里提到了两个很常见的扩展需求一个是双MID-360融合一个是倾斜安装时的坐标对齐这两个问题在实车部署时一定会遇到。单独说明一下我的处理经验。7.1 双雷达融合的两种思路先说结论双雷达融合建议不要把两路原始CustomMsg直接塞进FAST-LIO2因为FAST-LIO2默认只支持一路雷达输入。有两种常见做法思路一在驱动层外自己写一个融合节点把两路点云按外参变换后合并成一路PointCloud2再用一个中间节点把PointCloud2包成FAST-LIO2能接受的CustomMsg。这种方式的好处是算法完全不用改缺点是多了一次格式转换会有一定性能开销。思路二直接改FAST-LIO2的源码让它同时读取两个雷达话题在预处理阶段把两帧点云合并成一个点云再进入滤波器。这个方法工作量不大因为FAST-LIO2的预处理部分本身就是对点云做操作多订阅一个话题、多写一个回调函数把两帧时间戳对齐后做拼接就行。我在实际项目里用的是思路二代码改动大概100行以内。核心步骤是在laserMapping.cpp里加第二个点云订阅器订阅/livox/lidar_2在预处理线程中把两帧点云合并同时用各自的外参变换到车体系注意时间戳必须对齐如果两个雷达触发时间不一致点云会错位7.2 倾斜安装时的坐标系外参标定MID-360在某些车型上没法水平安装只能倾斜朝前或朝上。这时候雷达坐标系和车体系之间存在一个固定旋转如果不把这个旋转量告诉算法建出来的地图会整体歪掉。处理分两步第一步是测量安装角度用角度尺或者直接通过点云法向量估算。你可以在车体水平地面上放几个箱子用雷达扫一遍观察地面点云在雷达坐标系下的倾斜程度然后用PCL的SACSegmentation拟合地面平面平面法向量与雷达Z轴的夹角就是安装俯仰角。第二步是把计算出的角度转换成四元数填到外参里。如果倾斜只发生在俯仰方向那么roll 0 pitch -15° # 以实际测量为准 yaw 0用tf的quaternion_from_euler转成四元数填入extrinsic_li的rotation字段。如果雷达和IMU是一体的MID-360这个外参其实是雷达到IMU的通常安装倾斜也不会改变雷达和IMU的相对关系所以重点检查的是初始姿态角设置是否正确也就是mapping里的初始位姿。如果发现地面上有固定偏差即使外参对了还是有几厘米误差那多半是IMU和雷达的安装支架存在轻微形变这种情况只能重新紧固安装没有别的办法。7.3 时间同步MID-360支持PTP时间和GPS时间同步普通家用场景没有PTP主时钟雷达和工控机都走本地时钟即可。不过FAST-LIO2在做激光和IMU融合时时间戳精度直接影响结果。我的经验是如果只是演示或者一般场景不用做任何时间同步如果要跑长时间或者高精度测绘把工控机配置成PTP主时钟雷达作为从时钟能明显减少运动畸变。8. 常见问题与避坑技巧速查很多朋友加我微信问的第一句话都是“我编译怎么又挂了”这里把几个高频问题统一列出来按照我排查的经验给结论。问题现象可能原因解决方案编译Livox-ros-driver2时报找不到livox_sdk2SDK2没安装或没编译重新执行sudo make install确认/usr/local/lib下存在liblivox_sdk2.so启动驱动后设备一直offline网线没插好或IP不在同网段静态IP改为192.168.1.100ping 192.168.1.50测试点云话题有数据但Rviz不显示Fixed Frame设置不对把Fixed Frame改为livox_frameFAST-LIO2启动后地图一点不更新话题名不匹配rostopic list查实际话题逐一对照yamlFAST-LIO2建图漂移明显IMU外参不准或初始化没收敛检查extrinsic_li静止启动等待5秒以上IMU话题没数据驱动launch里IMU参数被打开了检查msg_MID360.launch里的imu_enable选项有一点特别想提醒不要在Rviz里同时订阅/cloud_registered和/livox/points去看同一片区域因为这两者帧率不一样视角不同看多了会误以为地图飘了。我自己调试时习惯只看/cloud_registered地图稳定后偶尔切到原始点云确认一下细节。另外FAST-LIO2跑起来之后CPU占用率通常在30%到60%之间如果你发现它飙到100%并且地图卡顿先去查点云话题频率如果频率稳定在10Hz那多半是ikd-Tree需要删除的冗余点太多可以尝试提高voxel_resolution或者把blind调大一点减少近距离噪点。9. 几个我后来才想明白的细节写到最后分享一些不太容易被教程覆盖到的小体会。第一个是编译顺序。很多初学者喜欢一次性catkin_make所有包结果报错后一大堆依赖分不清。我的习惯是分三轮做第一轮只编译驱动livox_ros_driver2第二轮只编译FAST_LIO第三轮再把所有包一起编译。这样出了问题能迅速锁定是哪个包的问题。不要嫌麻烦效率反而最高。第二个是不要迷信param文件里的默认参数。mid360.yaml里的voxel_resolution默认是0.5室内小房间可以改成0.2走廊大场景改回0.5否则地图会显得很粗糙或者太密导致计算缓慢。这个参数没有一个万能值一定要结合场景跑几遍再定。第三个是雷达的安装方向。MID-360的圆锥视场是向上偏的也就是说它的有效覆盖范围是从水平面到上方约52度。如果你想让雷达看到地面附近的小障碍物安装时最好让雷达稍微倾斜向下一点但倾斜角度不宜超过15度否则地面点占比过高会干扰平面拟合和里程计初始化。第四是IMU方向。MID-360内置IMU的坐标系和雷达坐标系默认对齐不需要额外标定。但如果你用的是独立外置IMU那extrinsic_li要非常认真标定差1度的外参误差建图二十分钟后就能看到明显的累积漂移。这套方案我现在还在用MID-360在室内外切换场景下的表现比想象中稳定。如果你手里也有同款雷达还在卡编译或者建图飘的问题照着这个流程先跑一遍多半能解决。剩下那些奇怪的边角问题基本都属于传感器安装工艺或者场景本身的结构问题那已经不是代码层面的坑了。本文还有配套的精品资源点击获取