ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

从零跑通FAST_LIO:Ubuntu 20.04 + ROS Noetic + Livox数据集完整避坑指南

从零跑通FAST_LIO:Ubuntu 20.04 + ROS Noetic + Livox数据集完整避坑指南 在SLAM圈里FAST_LIO 是用 Livox 雷达做 LiDAR-Inertial 里程计时绕不开的那个开源方案。很多团队入手 Livox Avia 或者 Mid-360 之后第一件事就是想把 FAST_LIO 跑起来看效果。理想中的流程很简单clone 源码、catkin_make、roslaunch、rosbag playRVIZ 里开始长地图。但实际上从编译到跑通数据集中间能翻车的点实在太多——驱动版本选错、消息包没生成、话题名对不上、外参方向反了随便中一个都能耗掉一下午。这篇文章就把我在 Ubuntu 20.04 ROS Noetic 环境下从零编译 FAST_LIO再配合 Livox 官方数据集做实测的完整过程写下来重点记录那些编译报错和数据集回放阶段的坑。文章不打算写成逐行注释的源码解读而是按照实际操作顺序来讲先讲环境怎么铺再讲驱动怎么选然后讲编译阶段哪些报错最典型最后讲数据集回放时怎么排查问题。这篇东西适合已经会基本 ROS 操作、但第一次碰 FAST_LIO 的人也适合编译已经通过、但换了自己录的 bag 后地图乱飞的人。后面提到的命令和配置我都验证过版本以 Ubuntu 20.04 ROS Noetic 为准。1. 环境准备把 Ubuntu 20.04、ROS Noetic 和算法依赖一次理清1.1 为什么这个组合最省事先说版本选型。Ubuntu 20.04 对应的 ROS 1 发行版是 Noetic这也是 ROS 1 的最后一个长期支持版本。FAST_LIO 的 master 分支主要面向 ROS 1官方 README 里给的编译说明也是基于 catkin 工作空间那一套。你当然可以在 Ubuntu 22.04 上用 Docker 或者源码编译 ROS 1但那样会引入很多额外的环境变量问题完全不值得。如果只是想快速把 FAST_LIO 跑起来Ubuntu 20.04 ROS Noetic 就是最稳的组合。我见过有人直接在 Ubuntu 20.04 上装 ROS 2 Foxy然后去编译 FAST_LIO 的 ROS 2 分支。这条路本身能走通但你要额外处理 livox_ros_driver2 的 ROS 2 构建参数还要面对 FastDDS 的 DDS 发现问题对新手来说太痛苦。所以这篇只讲 ROS 1 路线。还要提醒一句装系统的时候别用那种精简版服务器镜像最好用带桌面环境的 Ubuntu 20.04.6 Desktop。FAST_LIO 的调试依赖 RVIZ没有图形界面后面看效果会非常别扭。另外服务器版可能缺 build-essential、cmake 这类基础工具虽然可以事后补但没必要给自己添麻烦。1.2 依赖库逐个装齐系统准备好之后先把基础编译工具链装上sudo apt update sudo apt upgrade sudo apt install build-essential cmake git接下来是 ROS Noetic 本身。官方推荐的是 desktop-full 安装因为里面有 RVIZ、tf、pcl_ros、rviz 插件这些后面一定会用到的东西。如果只装 ros-noetic-ros-base后面你会发现缺这个缺那个装依赖的时间比省下来的时间还多。装完 ROS 之后有个动作特别容易被忽略把 ROS 环境写进.bashrc。echo source /opt/ros/noetic/setup.bash ~/.bashrc source ~/.bashrc很多人编译时找不到roslaunch、找不到catkin_make根本原因就是当前 shell 没有 source ROS 环境。这个我在后面还会反复强调因为每个新开终端都有可能踩。再单独装几个 FAST_LIO 编译时会用到的库sudo apt install libeigen3-dev libpcl-dev sudo apt install ros-noetic-pcl-ros ros-noetic-eigen-conversions ros-noetic-cv-bridgeEigen 是矩阵运算库FAST_LIO 的卡尔曼滤波部分离不开它PCL 负责点云处理。Ubuntu 20.04 自带的 PCL 版本是 1.10Eigen 是 3.3.7和 FAST_LIO 的兼容性没问题。Sophus 这个库主要提供 SE3/SO3 的李群李代数封装如果编译时提示找不到 Sophus可以装sudo apt install ros-noetic-sophus有些版本的老教程会建议你从源码编译 Sophus但既然 ROS 官方仓库里有现成包直接用 apt 装更省事。这里不需要纠结“是不是最新版”FAST_LIO 用的是很基础的接口稳定比新版本更重要。1.3 创建 catkin 工作空间依赖装完创建工作空间mkdir -p ~/fastlio_ws/src cd ~/fastlio_ws catkin_make这个动作会把工作空间初始化一遍生成devel和build目录。做完之后记得 source 一次source devel/setup.bash注意一点catkin_make执行成功和你能用roslaunch找到这个工作空间是两码事。如果你不 sourcedevel/setup.bash即使编译成功新终端里照样找不到fast_lio这个包。我通常会把source ~/fastlio_ws/devel/setup.bash也追加到.bashrc这样每个终端只要正常source ~/.bashrc就能直接用。2. 源码与驱动搭配FAST_LIO 版本和 Livox 驱动的对应关系2.1 先搞清楚 livox_ros_driver 和 livox_ros_driver2 的差别很多人在这一步就懵了。Livox 官方维护了两个 ROS 驱动仓库名字一个叫livox_ros_driver一个叫livox_ros_driver2。它们的消息类型不同、话题默认名称不同甚至编译方式也不同。简单区分一下老一代驱动livox_ros_driver主要对应早期固件和 Livox Mid-40、Mid-100 那批设备消息类型是livox_ros_driver/CustomMsg。新一代驱动livox_ros_driver2则主要面向 Avia、Mid-360 这些设备也支持模拟器底层 SDK 换成了 Livox SDK 2消息类型仍然叫CustomMsg但包名不同。FAST_LIO 新版本的配置文件中雷达话题写的是/livox/lidarIMU 话题写的是/livox/imu这两个默认话题就是从livox_ros_driver2来的。所以结论很直接如果用的是近两年的 FAST_LIO master 源码、拿的是 Avia 或 Mid-360 数据集就用livox_ros_driver2。如果你翻出来一个 2021 年之前的旧版本 FAST_LIO 仓库那个可能对应老驱动配置里话题名会是/livox/points。我建议直接用最新版 master别从网上随便找个老的中文教程改来改去版本错位是最难排查的问题之一。2.2 手动编译 livox_ros_driver2把 FAST_LIO 源码和 Livox 驱动都放到工作空间的 src 目录下cd ~/fastlio_ws/src git clone https://github.com/hku-mars/FAST_LIO.git git clone https://github.com/Livox-SDK/livox_ros_driver2.git注意livox_ros_driver2 克隆下来之后不要直接急着对整个工作空间跑 catkin_make。这个驱动比较特殊它在编译前需要先执行一个构建脚本生成针对 ROS 1 的接口文件cd ~/fastlio_ws/src/livox_ros_driver2 ./build.sh ROS1这个脚本本质上是在当前目录下生成ros1相关的消息和服务定义让后续 catkin 编译时能找到livox_lidar这个消息包。如果你跳过这一步直接 catkin_make大概率会看到类似“找不到 livox_ros_driver2”或“缺少 livox_msgs”的报错。这不是 FAST_LIO 的问题是驱动自己的构建顺序要求。执行完./build.sh ROS1后回到工作空间根目录整体编译cd ~/fastlio_ws catkin_make如果一切顺利你会看到 FAST_LIO 和 livox_ros_driver2 都编译通过。编译完成后再次source devel/setup.bash然后用rospack find fast_lio验证一下包路径能被找到。2.3 两个驱动同时出现在工作空间的后果这是我在帮别人排查时遇到最迷的问题之一。有人电脑上原来装过老版本 FAST_LIO工作空间里已经有一个 livox_ros_driver后来为了跑新数据又下载了 livox_ros_driver2 丢进同一个 src 目录。结果 catkin_make 报错Multiple packages found with the same name: livox_ros_driver两个驱动的 CMakeLists 里定义的包名都是livox_ros_drivercatkin 不允许同名字的包同时存在。解决办法也很简单把老驱动从 src 目录移走只保留一个。如果你需要同时用两种驱动跑不同设备别省事建两个独立的工作空间各自 source。混在同一个工作空间里后面还会有各种隐性问题比如消息类型覆盖到时候报错更难看。3. 编译阶段的高频报错与现场排查3.1 找不到 livox_ros_driver2 包编译第一步最容易遇到CMake Error: Could not find a package configuration file provided by livox_ros_driver2 with any of the following names: livox_ros_driver2Config.cmake这个报错通常有两个原因。第一个是你还没运行./build.sh ROS1导致驱动里的接口没生成find_package 阶段自然找不到配置。第二个是你确实运行了脚本但当前终端没有 source 工作空间或者你根本没在当前目录下编译。我在不同终端之间切来切去的时候踩过这个坑明明源码都在src里只是忘了在新终端source devel/setup.bashCMake 就找不到已经编译好的包。这里有个排查小技巧编译前先单独编译一次 livox_ros_driver2确认它成功了再编译整个工作空间。如果通过catkin_make整体编译时报错至少能确定问题不在 FAST_LIO 而在驱动侧。单独编译的方法cd ~/fastlio_ws catkin_make --pkg livox_ros_driver2如果这一步通过再试catkin_make。分步编译看起来多了一行命令但能让问题隔离得特别干净。3.2 编译过程中被 Killed 或卡死FAST_LIO 编译时最消耗资源的是 PCL 相关的头文件和模板实例化尤其是mapping.hpp那一堆模板代码。低配电脑、虚拟机、双系统下面内存不够很容易看到c: internal compiler error: Killed (program cc1plus)这不是代码写错了是内存不够编译器进程被系统 OOM killer 杀了。解决办法最直接的是限制并行编译任务数catkin_make -j2-j2表示同时编译两个任务对内存占用能压下来不少。如果你内存本身就不到 8G建议直接catkin_make -j1虽然慢一点但基本能稳定编完。另外不要在一个已经开了几十个标签页、里面还有 Chrome 的电脑上硬着头皮编关掉浏览器再编译效果立竿见影。还遇到过一种情况编译到 99% 时突然失败提示磁盘空间不足。FAST_LIO 的 build 目录和 devel 目录加起来可以到好几个 G如果当初给 Ubuntu 分区只留了 20G很容易卡在这。用df -h看一下根目录剩余空间不够就清理 apt 缓存或者直接给虚拟机扩容。3.3 Sophus、Eigen 版本导致的头文件报错编译报错常见系列还有fatal error: sophus/so3.hpp: No such file or directory这类问题在 2023 年之后的新版本 FAST_LIO 上少一些因为作者已经把部分依赖整理得比较干净。但如果你 clone 的是某些历史提交版本Sophus 头文件路径不对是常有的事。我前面建议装了ros-noetic-sophus它的头文件在/opt/ros/noetic/include/sophus正常情况下 ROS 的 include 路径会自动把它带上不用手动配置。如果编译还报错检查一下这个目录是否存在ls /opt/ros/noetic/include/sophus没有就重新装一次ros-noetic-sophus。Eigen 那边更典型的问题是报“找不到 Eigen3”但 Eigen 其实已经装了这是因为 CMake 默认搜索路径里没有/usr/include/eigen3。你可以直接指定catkin_make -DCMAKE_PREFIX_PATH/usr/include/eigen3不过说实话在 Ubuntu 20.04 默认环境下只要装了libeigen3-dev和ros-noetic-eigen-conversionsFAST_LIO 很少会因为 Eigen 报错。真遇到了先确认这两个包装齐没有。3.4 编译成功但运行时报找不到包编译全部通过你兴冲冲地执行roslaunch fast_lio mapping_avia.launch然后收到RLException: [mapping_avia.launch] is not a launch file name或者Resource not found: fast_lio这不是编译的锅是当前 shell 环境没 source。每次新开一个终端如果你没有把source ~/fastlio_ws/devel/setup.bash写进.bashrcROS 就不知道工作空间里有哪些包。我见过太多人编译成功之后卡在这里白白怀疑人生半小时。解决办法就一行source ~/fastlio_ws/devel/setup.bash顺手再验证rospack find fast_lio能输出路径就说明包环境对了。我个人的习惯是把 source 语句追加到.bashrc末尾之后只要终端一开所有包都能直接找到。唯一的副作用是如果同时有多个工作空间后面的 source 会覆盖前面的所以顺序要自己想清楚。4. 数据集回放从 rosbag 到 RVIZ 的完整链路4.1 官方数据集怎么拿、怎么检查FAST_LIO 作者在项目主页的 README 里放了几个实测数据集的下载地址有 Google Drive 链接也有百度网盘链接。如果你下的是 Avia 的数据集文件一般是.bag格式体积从几百 MB 到几个 G 不等。先把 bag 下载到本地别急着播放先用一条命令看清楚里面是什么rosbag info your_dataset.bag这条命令输出的信息量很大时长、帧数、话题列表、消息类型、频率。我最关心两件事雷达话题叫什么IMU 话题叫什么。Avia 数据集里通常会有/livox/lidar点云数据类型是livox_ros_driver2/CustomMsg/livox/imuIMU 数据类型是sensor_msgs/Imu如果你下载的数据集是别人用老驱动录的话题名可能变成/livox/points或者/ls120/lidar这种自定义名字。不要想当然一切以rosbag info的输出为准。这一步能帮你在后续少掉一半头发。还有一个容易被忽略的问题bag 的录制时间。如果 bag 里的时间戳是很久以前的而你当前系统时间跟它差了好几年直接播放可能因为时间跳变导致 FAST_LIO 初始化失败。这个问题后面会讲怎么处理。4.2 话题名和外参配置必须对齐打开 FAST_LIO 的配置文件比如src/FAST_LIO/config/avia.yaml你会看到这样的结构common: lid_topic: /livox/lidar imu_topic: /livox/imu这两个字段的值必须和你 bag 里的实际话题名一致。如果rosbag info显示雷达话题是/livox/points那你就把lid_topic改成/livox/points或者不改配置在 launch 文件里加 remap。我倾向直接改 yaml因为 remap 用多了容易乱。外参的坑比话题名更隐蔽。avia.yaml里还有两个关键字段mapping: extrinsic_T: [-0.011, -0.02329, 0.04412] extrinsic_R: [0.999905, 0.000318448, -0.0137521, ...]extrinsic_T是雷达在 IMU 坐标系下的平移单位是米extrinsic_R是旋转矩阵按行展开。FAST_LIO 默认认为lidar - IMU的外参。如果你的数据集来自官方作者一般会在 README 或者配置注释里写清楚这套外参直接用即可。但如果你用的是从别处下载的、或者自己标定得到的数据集外参与默认值不匹配跑出来的地图会出现两层重影、轨迹扭曲或者初始化发散。这里我分享一个职场经验任何和传感器外参相关的怀疑先做“清零测试”。把extrinsic_T全部设成 0旋转近似单位阵看系统是否还能跑出大致形状。如果清成 0 之后形状变得比原来还离谱说明默认外参本身是对的问题出在别的地方如果清成 0 之后反而更稳那说明原来的外参标定有问题。这个测试不严谨但能帮你在没有标定工具的情况下快速定位方向。4.3 实时播放的几个实用操作配置改好之后开两个终端。终端一roslaunch fast_lio mapping_avia.launch终端二rosbag play your_dataset.bag正常情况下终端一会开始打印初始化信息内容类似于收到了多少雷达点、IMU 频率多少。RVIZ 窗口会自动弹出地图开始一点点长出来。这里有几个非常实用的操作细节第一播放速度太快的处理。如果你的电脑性能一般FAST_LIO 处理不过来终端上能看到大量丢帧地图开始飘。这时候别急着想是不是参数问题先把 bag 放慢一点rosbag play -r 0.5 your_dataset.bag-r 0.5表示以一半实时速度播放给算法留出计算余量。实测中大部分“地图乱飞”其实是处理速度跟不上不是算法本身的问题。第二时间戳异常的处理。如果 FAST_LIO 一直在等数据或者输出时间倒流可以考虑让 bag 提供系统时间rosbag play --clock your_dataset.bag同时把 launch 文件里use_sim_time设为 true。这样 ROS 系统时间会跟着 bag 走不会因为当前系统时间与录制时间差太多而出现诡异问题。但要注意这个用法在多个节点之间容易造成时间基准混乱跑单个算法时没问题跑多传感器融合时要谨慎。第三RVIZ 没点云的处理。打开 RVIZ 后什么都没有先检查左下角 Global Options 里的 Fixed Frame 是不是camera_init。FAST_LIO 的地图坐标系就是camera_init如果 RVIZ 里固定坐标系是map或者其他名字点云自然显示不出来。再检查 Displays 面板里有没有添加 PointCloud2 显示话题选/cloud_registered颜色可以选 Intensity。5. 真跑起来以后初始化、参数微调与常见病判断5.1 初始化阶段为什么容易飘FAST_LIO 是紧耦合的 LiDAR-Inertial 系统IMU 在启动阶段要完成零偏估计。如果你启动算法之后立刻播放 bag而 bag 一开始就是剧烈运动系统可能因为初始零偏没收敛就发散。表现为地图刚出现就开始裂缝或者轨迹直接冲到天上去。最稳的用法是让 bag 开始前有一段静止数据。官方数据集基本都照顾到了这一点前几秒往往是静止状态。但如果你自己录制数据录制时务必先把雷达和 IMU 放在静止状态至少三到五秒这段静止数据对于系统初始化至关重要。启动时也建议先roslaunch等系统完全跑起来之后再rosbag play别两个命令同时敲下去。5.2 地图重影和稀疏的排查顺序跑通第一个 bag 之后很多人会发现地图并不是想象中那么干净普遍问题有两个重影和稀疏。先说重影。如果你看到墙体有两层首先怀疑外参标定值不对尤其是extrinsic_R的旋转部分。其次怀疑时间戳对齐有问题雷达和 IMU 的时间戳如果存在固定延迟系统会把同一面墙重复投影两次。FAST_LIO 的配置文件里有时间戳相关的开关比如timestamps: true它负责把点云中每个点的时间戳与 IMU 时间戳对齐。如果你用的 bag 里时间戳本身不可靠把这个开关换成 false 可能会有改善但也会牺牲部分精度。再说稀疏。点云看起来稀稀拉拉原因是预处理时做了降采样。配置里的point_filter_num表示每隔多少个点保留一个默认值是 4 或者 5。数值越大点越稀、CPU 压力越小数值越小点越密、计算越慢。实时运行时如果你的 CPU 性能不够可以适当调大这个值。我自己的经验是跑数据集的时候没必要动它默认就行实时上雷达再接设备时再针对 CPU 占用来调。还有一个容易被忽略的点雷达检测距离限制。配置里的det_range如果设得比较小远处的墙点会被过滤掉看起来也像“点云很稀疏”。检查一下这个值是否覆盖了你的使用场景室内 50 米基本够用室外园区道路建议调到 100 米以上。5.3 实时使用 LVX 雷达和跑数据集的区别这两件事看起来都是“把点云喂给 FAST_LIO”但实际上差别很大。数据集回放时你不需要关心雷达 IP、网卡配置、时间同步这些硬件问题因为 bag 已经替你录好了。但如果你要把 FAST_LIO 接到真实环境、实时跑起来就得多花不少功夫。首先雷达需要和工控机组成局域网。Livox 设备的默认 IP 一般是192.168.1.5之类的静态地址你需要把电脑网卡设置为同一网段。具体 IP 以型号说明书为准不要照抄网络上的教程因为不同型号默认参数会变。其次实时模式需要启动驱动节点roslaunch livox_ros_driver2 msg_MID360.launch或者对应 Avia 的 launch 文件。然后确认驱动发布的话题名和 FAST_LIO 配置文件里一致。如果驱动的话题名和配置文件不一致要么改 yaml要么在 rqt_graph 里重新映射。最后实时运行时的 IMU 时间戳和点云时间戳来自同一个硬件时钟源通常比 bag 回放更稳定。但这也意味着你必须把传感器固件升级到较新版本老固件的 Livox SDK 2 兼容性问题很多跑起来会出现半小时后突然断流这种怪毛病。5.4 看 rqt_graph 判断数据链路是否健康还有一个调试技巧能帮你在百思不得其解时快速找到问题。启动 FAST_LIO 和 bag 播放后新开一个终端rqt_graph这个工具会把当前 ROS 节点和话题的发布订阅关系画成图。FAST_LIO 正常运行时的链路大致是/bag播放器把原始点云和 IMU 数据发布出来/fast_lio节点从对应话题订阅然后经过处理发布/cloud_registered、/path、/Odometry这些结果。如果你在 rqt_graph 里看到fast_lio节点存在但话题输入明显不对比如 IMU 话题没有连线那就是配置里话题名没对上如果你看到两个节点之间连线上有黄色警告说明消息类型或 QoS 不匹配。这个工具能帮你把“配置问题”和“算法问题”区分开不用靠猜。最后再分享一点个人习惯我在实际调试 FAST_LIO 时有个固定流程现在也推荐给你先编译、再回放官方数据集、再回放自己录的数据集、最后才接实车。每一步都以前一步通过为前提不要在第一步没跑通时就急着接实车。编译阶段是最容易解决的问题和答案都非常明确数据集回放阶段可以暴露 80% 的配置问题实车阶段的问题才真正需要算法层面的调试。另外一个小建议每次修改 yaml 或 launch 文件后没必要重新编译直接重启 roslaunch 就行。但如果你动的是 C 源码比如改了预处理逻辑或滤波参数那一定要重新catkin_make否则运行的还是旧版本。这个区分看似基础我却见过不少人改了代码没编译盯着终端怀疑了半天为什么“代码没生效”。调试机器人算法本来就很考验耐心能少踩一个坑是一个坑。
返回列表