简介:本资源是一份面向机器人、自动驾驶与无人机领域研发工程师及高校研究者的高精度LiDAR-SLAM系统集成实战指南,聚焦Mid-360激光雷达在Ubuntu 18.04平台上的完整部署链路:从Livox SDK2驱动安装、Livox-ROS-Driver2数据接入,到FAST-LIO2紧耦合定位算法的编译配置与实时建图测试。资源以单个HTML文档形式呈现(共1个文件,21KB),内容结构清晰,覆盖环境依赖、源码编译、参数适配、话题发布验证及FAST-LIO2运行调试等关键环节,尤其包含Mid-360点云格式适配、IMU时间同步、rviz可视化配置等易错细节的排错思路与实测参数。目前已有873人学习下载,适合具备ROS基础和C++编译经验的中高级开发者快速落地LiDAR惯性里程计方案。 第一次拿到Mid-360的时候,我第一反应是"这雷达怎么这么小"。机身比巴掌还小一圈,但配上FAST-LIO2跑起来的建图效果,完全不像这个体积该有的表现。后来陆陆续续给好几台巡检车和AGV都配了这套组合,到现在已经算是我装机清单里的默认项了。
在开始之前先明确一下这篇内容能帮你解决什么问题:从零开始,在一台x86工控机上搭好mid360的驱动链路,把点云数据接进FAST-LIO2,完成实时建图并输出里程计。适合正在做移动机器人、无人机、室外测绘,以及刚入坑SLAM的研究生和工程师参考。涉及的主要组件是Livox-SDK2、Livox-ros-driver2、FAST-LIO2,都是目前官方和社区用得最广的版本,不是那些被改到面目全非的魔改分支。
1. 项目概述与方案选型思路
1.1 mid360为什么值得选
先说说选择mid360的原因。它是一颗非重复扫描的固态激光雷达,垂直视场角是-7°到+29°,视场覆盖比绝大多数机械式单线雷达要大得多。虽然单帧点数不算多,但它有个特性——随着时间积分,视场内的覆盖密度会显著增加,这一点对特征提取非常友好。FAST-LIO2在做特征匹配时用到的surface和edge特征,对时间积累后的点云密度要求其实不算高,这就让"非重复扫描+紧耦合LIO"成了天然搭配。
另一个关键点是它内置了一颗IMU。FAST-LIO2需要IMU做运动补偿和状态预测,mid360内置IMU直接省去了外接IMU的安装和同步问题。实测下来内置IMU的零偏稳定性和噪声水平虽然比不上专门的高端IMU,但对建图里程计来说是够用的,前提是别在剧烈振动环境下指望它输出高精度姿态。
1.2 为什么是FAST-LIO2
FAST-LIO2的定位很明确:紧耦合LiDAR-惯性里程计。它不是单纯的LOAM那种"先后端优化"路线,而是把点云配准和IMU状态估计塞进同一个迭代ESEKF框架里。好处是,在快速旋转、剧烈运动这些场景下,有IMU的前向预测做支撑,点云配准不容易丢。
而且这套代码对平台要求不高,我试过在Jetson Orin NX、i5-8250U这类低功耗CPU上也能跑到10Hz以上的实时帧率。另外它的外参模块做得比较友好,mid360的安装方式变动之后,只需要改配置里的R和T,不需要改代码。对快速验证方案的人来说,这能省下大量时间。
1.3 整体架构
整条数据链路是这样的:mid360通过以太网将点云和IMU数据发给主机,主机上运行Livox-SDK2和Livox-ros-driver2,把UDP数据流转换成ROS的PointCloud2和Imu消息,再交给FAST-LIO2做紧耦合状态估计与建图,最终输出/Odometry和/cloud_registered。
这里要特别注意,Livox-SDK2对应的是driver2,它俩是一套新架构,和很多老教程里写的livox_ros_driver(对应SDK1)不是同一个东西。mid360虽然也能在老driver下工作,但功能没有新架构完整,部署时果断选SDK2+driver2才是正路。
2. 硬件准备与基础环境
2.1 硬件清单
一套可以稳定运行的方案,硬件其实不用很豪华。我用过的最低配组合是:
- mid360雷达本体(含原装网线)
- 一台x86工控机或普通笔记本(Ubuntu 20.04 + ROS1 Noetic)
- 千兆交换机或雷达直连主机网口
- 12V供电适配器(有的开发板上还建议单独配隔离电源)
雷达自带的网线说实话有点短,现场布局紧的话建议提前备一根质量好一点的六类网线,传输距离控制在100米以内,这基本是跑以太网雷达的常识,但总有人栽在这上面。
2.2 网络与IP配置
mid360出厂静态IP是192.168.1.50,这一点非常关键。我见过太多人的"雷达不开机"其实是本机IP没配对。你需要把主机的网口配置成192.168.1.x网段,比如192.168.1.102,掩码255.255.255.0,不需要设网关。直连或走交换机都行。
配置完可以用一条命令确认链路:
ping 192.168.1.50 -c 3如果ping不通,先检查网线、网口,再看防火墙。Ubuntu上偶尔需要关闭ufw:
sudo ufw disable另外,雷达的UDP数据包使用2368号端口,主机端不需要主动开端口,但网卡如果启用了泛洪过滤,偶尔会丢包。这个地方先留意,后面第7节还会专门讲丢包怎么排查。
2.3 系统与依赖安装
雷达驱动和FAST-LIO2都依赖ROS,建议直接用Ubuntu 20.04 + ROS1 Noetic,这是目前社区兼容性最好的组合。如果你用18.04 + Melodic,也没问题,但很多三方依赖编译时会遇到麻烦。
系统基础依赖按顺序装:
sudo apt update sudo apt install git cmake build-essential \ libeigen3-dev libpcl-dev ros-noetic-pcl-ros \ ros-noetic-cv-bridge ros-noetic-image-transportEigen和PCL是FAST-LIO2的硬性依赖,缺了编译必炸。Sophus在FAST-LIO2的仓库里以submodule形式带了一份,后面编译时会提到,不需要自己额外装。这里多提一句,装依赖的时候别图省事一次装一堆,容易把ROS的python依赖搞乱,我遇到过一次装ros-noetic-desktop-full后和自定义的python包冲突的情况,教训就是基础环境越干净越好。
3. Livox-SDK2与Livox-ros-driver2编译部署
3.1 源码准备与版本匹配
这里我给一个明确的建议:直接从Livox官方GitHub拉取仓库,别用第三方打包的版本。
git clone https://github.com/Livox-SDK/Livox-SDK2.git git clone https://github.com/Livox-SDK/Livox-ros-driver2.git由于网络原因,如果拉取超时,可以改用仓库在Gitee上的同步镜像,或者直接在网页端下载zip包再解压。但版本要盯住:SDK2和driver2要配套,别一个用release一个用latest,遇到API不匹配大概率是版本错位。
两个仓库克隆下来之后,先确认一下目录结构。driver2里有ros1和ros2两个子目录,我们用的是ROS1,编译时进入ros1目录下的package即可。很多人不看README直接编译,结果在ROS2目录里编译报一堆错,白白浪费时间。
3.2 编译SDK2
SDK2的编译很简单:
cd Livox-SDK2 mkdir build && cd build cmake .. make -j4 sudo make install编译过程中如果报缺少依赖,最常见的是没有安装cmake或者没有curl库:
sudo apt install libcurl4-openssl-dev装完再重新编译一次。SDK2装到系统之后,后续driver2编译时才能找到它。SDK2相比SDK1的主要变化是网络通信层和点云格式处理做了重构,对mid360这类新雷达支持更稳定,所以不要想着用老SDK1硬凑。
3.3 编译ros-driver2
把driver2放进你的ROS工作空间:
mkdir -p ~/catkin_ws/src cd ~/catkin_ws/src git clone https://github.com/Livox-SDK/Livox-ros-driver2.git cd ~/catkin_ws catkin_make如果你习惯catkin build,也可以,但要注意driver2的package里有个支持ROS2的目录结构,用catkin build会比catkin_make更干净一些。编译结束后记得source:
source ~/catkin_ws/devel/setup.bash编译通过后,先不急着启动,去config目录下看看配置文件。
3.4 配置driver参数
driver2的配置文件在src/livox_ros_driver2/config/,默认叫livox_lidar_config.json。一块雷达最小化配置长这样:
{ "lidar_configs": [ { "broadcast_code": "000000000000001", "enable_connect": true, "lidar_ip": "", "cmd_port": 56000, "msg_port": 56000, "pcl_data_type": 1, "frame_id": "livox_frame", "lidar_net_info": "192.168.1.50", "host_net_info": "192.168.1.102" } ], "config_path": "", "enable_lidar_sync": false }broadcast_code是个坑点。每颗mid360机身铭牌上有一串16位广播码,填进去是稳定连接的关键。如果不填或填全0,driver也能尝试自适应连接,但在多雷达环境下就会出乱子,所以务必填实。
pcl_data_type这个字段要注意:1表示输出点云,2表示输出点云+IMU。FAST-LIO2需要IMU数据,所以这里必须设为2。很多人在这个字段上栽过跟头,设成1之后启动FAST-LIO2,程序一直等IMU数据,看起来像死锁,实际上是数据根本没发出来。
host_net_info也要对上主机的IP地址。如果雷达和目标主机跨网段,或者host_net_info填的是网关地址,都会导致收不到数据。
如果一台主机带两颗mid360,那么lidar_configs数组里要写两个条目,每个条目配不同的广播码,frame_id也要区分,比如第一颗用livox_frame,第二颗用livox_frame_2。
3.5 验证数据链路
启动driver2:
roslaunch livox_ros_driver2 msg_MID360.launch如果一切正常,会看到类似[Livox-LiDAR] Connect to Lidar 000000000000001 successfully的日志。然后开另一个终端,验证点云:
rostopic hz /livox/lidar正常能看到10Hz左右。再看一下IMU:
rostopic echo /livox/imu -n 3如果有点云没IMU,回去检查pcl_data_type。有IMU没点云,检查广播码和网络。
这里就完成了雷达侧的第一步部署。雷达数据已经进入ROS生态,接下来是FAST-LIO2的编译和对接。
4. FAST-LIO2编译配置
4.1 源码准备
FAST-LIO2的源码在港大MaRS实验室的GitHub仓库:
cd ~/catkin_ws/src git clone --recursive https://github.com/hku-mars/FAST_LIO.git这里--recursive不能省,仓库里带了Sophus、ikd-Tree和livox_ros_driver2的submodule。如果没有递归拉取,后面编译Sophus的时候必然报错。如果clone时submodule没拉全,可以单独补:
cd FAST_LIO git submodule update --init --recursive另外要注意,FAST_LIO里这个livox_ros_driver2 submodule和你自己拉的那个driver2,在编译时会冲突吗?实际上FAST_LIO的CMakeLists里通过find_package(catkin REQUIRED COMPONENTS livox_ros_driver2)寻找已安装的driver2,并把它的pkg作为依赖,而不是直接用它submodule里的那份。所以你必须确保工作空间里先成功编译了driver2,否则FAST_LIO的cmake阶段就会挂掉。
4.2 编译环境排查与编译
进入FAST_LIO目录,确认package.xml里依赖项齐全,然后回到工作空间根目录编译:
cd ~/catkin_ws catkin_make -j4如果编译时提示找不到livox_ros_driver2这个package,多半是因为driver2没有成功编译,或者没有在同一个工作空间里。可以先用:
rospack find livox_ros_driver2确认能找到。找不到就去检查driver2是否source了。
还有一类常见问题是Sophus没编出来。检查~/catkin_ws/src/FAST_LIO/src/thirdparty/Sophus目录是否为空,如果是,说明submodule没拉全,执行上面那条git submodule update命令即可。
编译成功的标志是build目录下出现了fastlio_mapping这个可执行文件。此时别急着跑,先改配置。
4.3 配置文件修改
FAST-LIO2的配置在FAST_LIO/config/目录下,推荐直接用mid360.yaml。打开后重点改以下几项:
common: lid_topic: "/livox/lidar" imu_topic: "/livox/imu" time_sync_en: falselid_topic和imu_topic要和你driver发布的话题名一致。我在默认配置上第一次跑的时候,发现lid_topic写的是/livox/lidar,而driver2发布的是/livox/lidar_1,如果不注意,程序会一直等数据。
IMU配置:
preprocess: lidar_type: 1 scan_line: 4 blind: 0.5lidar_type: 1表示livox系列雷达,这个不能动。scan_line: 4是mid360每帧4条扫描线的含义,注意如果用的是双雷达融合后的合成点云,scan_line这里不一定等于4,要看你的处理节点怎么合并的。
外参配置这块是重头戏,单独开一节说。
5. mid360坐标系对齐与倾斜/双雷达部署
5.1 为什么会有倾斜雷达和坐标对齐问题
mid360的垂直视场只有-7°到+29°,也就是说它天生"往上看"。如果你把雷达水平装在小车顶部,那么近处地面和车周围的一圈盲区会比较大。很多方案为了兼顾地面和障碍物,会把mid360向前倾斜30°到60°安装,这样既能照到车前的地面,又能看到远处的障碍物。
问题就来了——雷达的几何坐标系是跟着雷达外壳方向走的,一旦安装姿态变了,输出点云的坐标系也变。FAST-LIO2默认把雷达坐标系当成"X前Z上"的约定系,如果雷达本身是斜的,就必须在配置里告诉它真实的旋转量,否则建出来的地图会整个歪掉。
5.2 坐标系约定与外参矩阵修改
先说清楚mid360的坐标系定义。Livox的官方定义是:X轴从雷达正面窗口向外,Y轴由右手定则决定,Z轴垂直向上。注意,很多人以为mid360的X轴是朝向标签纸方向,实际上并不一定,不同型号的label方向有差异,最好以官方文档和点云观察为准。
FAST-LIO2里外参由两段配置决定:
calib: # extrinsics from lidar to imu R_ext: [1, 0, 0, 0, 1, 0, 0, 0, 1] T_ext: [0, 0, 0]这里R_ext是雷达坐标系到IMU坐标系的旋转矩阵,T_ext是平移。mid360内置IMU在雷达内部,理论上原点和雷达重合,所以平移基本是0。如果雷达水平安装且和驱动代码默认方向一致,R_ext保持单位阵没问题。
但如果你把雷达前倾了45度(绕Y轴旋转45度),那么旋转矩阵就是:
cos(45°) 0 sin(45°) 0 1 0 -sin(45°) 0 cos(45°)也就是说,配置里要填:
R_ext: [0.7071, 0, 0.7071, 0, 1, 0, -0.7071, 0, 0.7071]这里有个容易写反的地方:FAST-LIO2的R_ext表达的是"雷达坐标系到IMU坐标系的旋转",如果雷达前倾,意味着雷达的Z轴在世界系下也跟着前倾,所以旋转矩阵的sin符号要仔细推导,不是随手填进去。稳妥的做法是:先在Rviz里看雷达点云,确认当前点云坐标系下哪个轴朝前、哪个轴朝上,再根据旋转公式填入。
我可以给一个偷懒但可靠的方法:先用单位阵跑一次,点开Rviz的Axes显示,看雷达点云的X轴实际朝哪个方向;如果雷达是倾角安装,你会看到地面点云的平面方向和Axes明显不垂直。这时按轴角或者欧拉角把R_ext补上,重新启动就行。别指望一个公式搞定所有安装方式,每台车的安装都不一样,必须自己验证一遍。
5.3 双雷达融合配置
双激光雷达融合的需求,在巡检和测绘项目里越来越常见,一般是为了补足视场或者提高建图鲁棒性。但FAST-LIO2的代码默认只订阅一个lidar topic,怎么接进第二颗雷达?我这里说一种最简单、最不容易出错的方案:合并点云后再送出。
思路是这样:把两台mid360接在同一个host上,分别配置为不同的广播码和端口,driver2会各自发布/livox/lidar和/livox/lidar_1两个topic。写一个小节点,订阅两个PointCloud2,按时间戳对齐后合并成一个PointCloud2,再转发给FAST-LIO2。合并前后的tf和外参都要在同一个坐标系下表达。
一个关键点:两颗雷达之间的外参标定。如果你只是粗略合并,两台雷达的点云在远处可能对不齐。严谨的做法是用标定板或手眼标定获取两台雷达之间的RT,再把第二颗雷达的点云变换到第一颗雷达坐标系下合并。这里我建议先用ICP做一个初始对齐,再人工微调,工程上够用。
合并节点的核心逻辑可以用这段伪代码表示:
// 伪代码,实际代码需要处理消息时间同步和坐标系变换 void callbackLidar1(const PointCloud2::ConstPtr& msg1) { latest_cloud1 = transformToFrame(msg1, lidar1_T_base); mergeAndPublish(); } void callbackLidar2(const PointCloud2::ConstPtr& msg2) { latest_cloud2 = transformToFrame(msg2, lidar2_T_base); mergeAndPublish(); }代码的细节不多,但时间戳对齐是避不开的坑。两个雷达的数据并非严格同时到达,差值超过50ms就要考虑丢弃或插值。时间戳不对齐,合成的点云会出现"重影",FAST-LIO2解算时地图直接糊掉。我在实际项目里用过的最省事方案是:在合并节点里用message_filters::ApproximateTimeSynchronizer做近似时间同步,效果比手动对齐稳妥得多。
另外,双雷达融合后,如果两颗雷达的视场有重叠,那个区域的点云密度会是别处的两倍,特征提取时可能产生权重偏差。解决办法也不复杂,在合并节点里对重叠区域做一次体素降采样,把密度拉均匀,我习惯用PCL的VoxelGrid在这片区域设0.3米的网格。
5.4 IMU时间同步问题
FAST-LIO2对IMU时间戳的分辨率要求挺高。mid360内置IMU的时间戳和点云时间戳在driver2内部已经做了对齐,所以直接用没问题。但如果你外接IMU,时间同步就麻烦很多,需要硬件PPS或GPRMC。我建议一开始就使用内置IMU,省去同步负担。
如果发现FAST-LIO2启动后一直不输出里程计,检查IMU消息的时间戳是否连续:
rostopic echo /livox/imu/header/stamp注意观察时间戳是否为递增且稳定的频率,如果跳动严重,多半是供电问题或网线质量差导致数据丢包。
6. 实机建图与效果调试
6.1 启动流程
先启动雷达驱动:
roslaunch livox_ros_driver2 msg_MID360.launch确认点云和IMU都在发之后,再启动FAST-LIO:
roslaunch fast_lio mapping_mid360.launchlaunch文件里默认会加载mid360.yaml,如果改了配置文件名,记得同步改launch。启动后的一瞬间,程序会开始接收数据,但里程计不一定马上输出——它得等IMU初始化稳定。IMU初始化的过程是这样的:FAST-LIO2内部用静止或者低速晃动过程中的IMU数据估计零偏和重力方向,如果传感器一直不动,初始化可能很慢或者不准确。
所以我每次上电后的标准操作是:拿到遥控器,先把小车手动晃动十几秒,然后再起步,让IMU快速收敛。这是一个很容易被忽略但影响很大的实操细节。
启动时还有个细节:launch里如果写了output="screen",FAST-LIO2会打印每帧处理时间、特征点数等信息。我建议第一次跑的时候保持这个配置,方便看程序是否在正常迭代。等到正式跑任务时再改成output="log",避免日志刷屏影响性能。
6.2 Rviz查看与地图质量评估
启动后打开Rviz:
rosrun rviz rviz -d ~/catkin_ws/src/FAST_LIO/rviz_cfg/loam_livox.rviz正常能看到两个关键topic:
/Odometry:里程计位姿/cloud_registered:注册后的点云(也就是实时地图)
评估建图质量,我看三个地方:地面是否平、墙面是否直、长时间运动后是否回环对齐。如果墙是弯的、地面是波浪的,代表位姿漂移,需要回头看IMU和特征提取。另外,Rviz里可以顺手打开/path查看轨迹平滑度,轨迹抖动明显说明IMU噪声或外参有问题。
6.3 调参建议
FAST-LIO2里比较常用调参项我列一下:
filter_size_surf:面特征体素滤波尺寸,默认0.5,如果地图噪声大可以适当减小到0.3,但会明显增加CPU占用。filter_size_map:全局地图体素尺寸,默认0.5,改小会提升地图细节,改大减少内存。max_iteration:最大迭代次数,默认3,抖动大时可以提高到5,但延迟会上升。time_sync_en:如果雷达和IMU时间戳来自不同硬件,设true,但内置IMU一般不用。
每次只改一个参数,记录前后对比,这是调参的基本纪律。我见过不少同学一次改三四个参数,出了问题根本不知道是谁引起的。
另外,如果建图过程中发现地图漂移比较大,可以先用一个小场景、短时间的bag包回放来复现问题。录制bag用:
rosbag record /livox/lidar /livox/imu /tf回放时再做参数调整,比现场边跑边改高效得多。
7. 常见问题与排查技巧实录
这里整理一份我从实战里攒下来的排查清单,基本覆盖了这套方案里80%的翻车场景。
| 现象 | 可能原因 | 排查/解决方法 |
|---|---|---|
| ping不通192.168.1.50 | 主机IP没配对、网线质量问题 | 检查网口IP和掩码,换一根六类网线 |
| driver2启动即退出 | 广播码不对或lidar_ip配置错误 | 核对雷达铭牌广播码,填到json |
| 有/livox/lidar没/livox/imu | pcl_data_type设成了1 | 改成2并重启driver |
| 有IMU没点云 | 雷达被其他进程占用、broadcast code填错 | 关闭其他占用节点,核对广播码 |
| FAST-LIO2启动后一直等数据 | topic名不匹配或时间戳异常 | rostopic list对比实际topic,确认lid_topic/imu_topic |
| 建图地图整体歪斜 | 外参R_ext不对 | 用Rviz确认雷达坐标系方向,修正旋转矩阵 |
| 双雷达 |
本文还有配套的精品资源,点击获取