
做移动机器人这行手里没几个能打的传感器组合出去跑测试基本等于盲人摸象。速腾16线激光雷达在国产雷达里属于入门槛最低、资料最多、社区反馈也最成熟的一档价格合适16线点云密度虽然不像32线、64线那么夸张但在室内建图、园区巡检、小范围室外环境下完全够用。我前后在ROS Melodic环境里把速腾16线和FAST-LIO2跑通从驱动配置到最终保存点云地图中间踩了不少坑有些坑网上教程根本不会写。这篇就完整记录整个过程包括驱动怎么装、launch怎么改、FAST-LIO2哪些参数必须动以及遇到问题怎么定位适合刚入手速腾16线、想在ROS Melodic上跑FAST-LIO2建图的朋友直接照着做。先说结论这套组合完全可以跑通而且实时性不错只要雷达驱动给的话题正常、IMU数据正常、外参没有明显误差FAST-LIO2建出来的图很干净不需要额外装一堆乱七八糟的依赖。唯一要注意的是激光雷达坐标系和IMU坐标系的初始外参以及雷达和IMU的时间戳是否同步这两个点决定了建图是稳定收敛还是不停飘。1. 整体方案与系统架构为什么是速腾16线 FAST-LIO21.1 速腾16线在整套系统中的定位速腾16线官方型号一般是RS-LiDAR-16属于机械旋转式激光雷达水平360度扫描垂直方向有16个线束量程大概在100米左右近距离盲区小点频大约30万点每秒。这类雷达输出的原始数据是一圈一圈的极坐标点经过驱动转换成PointCloud2格式。在FAST-LIO2这类算法里它充当的是感知前端负责持续输出环境结构的几何信息而算法内部的IMU紧耦合和迭代卡尔曼滤波会把这些点云和载体运动状态融合起来输出机器人自身的姿态和全局一致的点云地图。为什么选16线而不是更高线数核心原因是性价比和算力门槛。16线雷达在FAST-LIO2里的表现并不会比32线差出一个量级因为FAST-LIO2核心卖点就在降采样和特征提取它不像传统LOAM那样强依赖线束密度反而更依赖点云局部几何特征的连续性和IMU的配合。我做下来的感觉是16线在空旷环境确实会有点稀疏但在楼内走廊、实验室、停车场这类结构化场景足够看清墙体和柱子的几何关系。1.2 为什么用ROS Melodic以及需要注意的系统版本组合ROS Melodic对应的Ubuntu版本是18.04这是很多中低配工控机在跑的老搭档。选择Melodic主要是因为速腾官方驱动rslidar_sdk对ROS1的兼容性做得比较好FAST-LIO2本身也提供ROS1的launch方式不需要额外适配ROS2省去不少麻烦。系统组合上我推荐用Ubuntu 18.04 ROS Melodic Eigen 3.3.4 PCL 1.8这些版本之间配合很成熟。如果你用的是Ubuntu 20.04加ROS Noetic也能跑但编译依赖的路径和包名略有差异不能照搬下面的命令。我这边踩过最明显的一个坑是在ROS Melodic下编译FAST-LIO2时系统自带的Eigen版本和代码要求的Eigen版本不一致导致程序跑起来后时不时报内存对齐错误后面通过更新Eigen到3.3.7解决了。1.3 整套系统的数据流和消息链路在开始动手之前先理清楚整个系统的消息链路后面出问题了定位也快。整套建图系统里核心节点只有两个一个是速腾驱动节点rslidar_sdk_node负责把雷达原始网络数据包解析成点云话题另一个是FAST-LIO2节点fastlio_mapping负责订阅点云话题和IMU话题输出里程计和累积点云地图。速腾驱动默认输出的点云话题名一般是/rslidar_pointsIMU话题如果使用雷达自带惯性模块部分版本支持或者外接IMU需要你自己确认话题名。FAST-LIO2的launch文件里默认订阅的是/velodyne_points和/imu/imu所以要么改驱动的话题名要么在FAST-LIO2的launch里做remap我实际用的是remap方式不动驱动配置这样最简单。数据链路拆开就是这样的雷达通过网线连接到工控机配置好静态IP后驱动接收UDP数据包并解析成点云。点云话题同时被RViz和FAST-LIO2订阅。IMU数据三轴角速度加三轴加速度以固定频率发布FAST-LIO2利用IMU做运动补偿和状态预测。FAST-LIO2输出/aft_mapped_to_init里程计和/cloud_registered实时点云RViz里叠加显示。这套链路里任何一环断了表现出的症状都是建图启动后不更新、地图发散、点云错位。所以先把驱动跑通用RViz看到实时点云再启动FAST-LIO2是最稳的顺序。2. 速腾16线雷达驱动配置从源码编译到看到点云2.1 编译rslidar_sdk前需要准备的依赖速腾官方驱动现在统一叫rslidar_sdkGitHub上可以拉到源码。它依赖libpcap、yaml-cpp、PCL和ROS纯净的ROS Melodic环境通常缺libpcap和yaml-cpp不提前装好编译到一半就会报错。我建议在编译前先把这些依赖一次性装完sudo apt-get update sudo apt-get install -y libpcap-dev libyaml-cpp-dev libeigen3-dev libpcl-dev pcl-tools这几个包的作用分别是libpcap负责抓取雷达的UDP网络包yaml-cpp负责解析驱动配置文件PCL是点云处理的底层库。ROS Melodic环境一般已经装了PCL相关依赖但保险起见还是执行一次。源码编译我采用的流程是放到catkin工作空间里编译这样可以直接用roslaunch启动。先创建工作空间再把驱动源码放进去mkdir -p ~/catkin_ws/src cd ~/catkin_ws/src git clone https://github.com/RoboSense-LiDAR/rslidar_sdk.git cd ~/catkin_ws catkin_make source devel/setup.bash这里注意一个常见的坑如果git clone的速度很慢或者之前clone过老版本的rslidar_sdk建议先看一下仓库目录下是否有config.yaml.example文件。新版本的驱动目录结构是config/config.yaml老版本可能在src/rslidar_sdk/config目录下。路径不对会直接导致启动的时候找不到配置节点闪退。2.2 修改雷达参数IP地址、模式和数据源选择rslidar_sdk的核心配置文件是config.yaml里面控制雷达型号、数据来源、网口配置。速腾16线出厂默认的电脑IP一般是192.168.1.102雷达默认IP是192.168.1.200子网掩码255.255.255.0。首先把工控机的有线网口手动设置成这个网段。配置文件里我实际改过的地方主要有三处lidar_type填RS16确认是16线雷达类型。udp_port默认6699这个要和雷达的配置一致一般不用动。config_version新版本填2点几类型选择全部配在config.yaml里。启动驱动的launch文件在rslidar_sdk/launch/rslidar_sdk.launch里面基本不用改。启动方式roslaunch rslidar_sdk rslidar_sdk.launch正常情况下终端会刷出雷达参数信息并且在后续不断打印收到的数据包点数。如果启动后没有任何输出检查网线连接和IP配置用ifconfig确认有线网卡地址是192.168.1.102然后ping一下雷达IPping 192.168.1.200能ping通才说明网络链路通畅剩下的事才是看驱动参数。2.3 验证点云话题确认能正常显示打开新终端启动RVizrosrun rviz rviz添加PointCloud2显示话题选/rslidar_pointsFixed Frame选rslidar驱动配置里frame_id默认写成rslidar。如果能看到一圈一圈的点云并且雷达转动时点云跟着变化说明驱动已经通了。这里我遇到一个频率不高但很恶心的问题点云能显示但只有一半或者每隔几个角度就缺一块。后来排查发现是供电问题雷达通过POE供电时功率不足导致局部角度丢包。换成功耗充足的电源之后问题消失。如果你点云也出现规律性缺口先不要怀疑算法先查供电和网线质量。还有一个小细节用RViz显示时如果点云颜色全白看不清距离层次把PointCloud2的Color字段设置成Intensity或者Z轴高度映射看起来会直观很多。3. FAST-LIO2编译与配置核心参数必须搞清楚3.1 编译依赖清单和安装顺序FAST-LIO2是一个纯C的算法项目依赖Eigen、PCL、Sophus、livox_ros_driver官方说明里虽然会安装但如果你只用速腾16线其实不需要livox驱动不装也能编译过只是需要改CMakeLists里对livox_ros_driver的引用。实际上我更推荐不装livox_ros_driver省掉一个编译环节也能避免系统里多一个不知道什么时候会起冲突的驱动。我在编译前安装的依赖是sudo apt-get install -y libeigen3-dev libpcl-dev ros-melodic-pcl-ros ros-melodic-cv-bridge libgoogle-glog-dev libgflags-devSophus需要单独从源码编译因为FAST-LIO2的代码里用到了Sophus的SO3类cd ~/catkin_ws/src git clone https://github.com/strasdat/Sophus.git cd Sophus mkdir build cd build cmake .. make -j4 sudo make install必须注意Sophus版本别太新我用的是早期版本太新的版本在CMake方式下的编译接口有变化可能导致FAST-LIO2编译时找不到find_package(Sophus)的cmake模块。如果遇到这个问题直接在Sophus仓库里checkout一个旧一点的tag即可。3.2 编译FAST-LIO2源码FAST-LIO2的源码路径是hku-mars/FAST-LIO克隆下来之后放到工作空间里cd ~/catkin_ws/src git clone https://github.com/hku-mars/FAST-LIO.git cd ~/catkin_ws catkin_make这里我踩了个大坑直接catkin_make时会因为livox_ros_driver的依赖而编译失败报错找不到livox_ros_driver下的头文件。由于我们用的是速腾不是Livox所以需要改一下CMakeLists.txt把和livox_ros_driver相关的链接先屏蔽掉。比较快的办法是在CMakeLists.txt里把find_package(livox_ros_driver ...)这一行注释掉并把后面target_link_libraries里依赖livox_ros_driver的库也注释掉改完保存再catkin_make就过了。如果你不想改源码也可以先编译livox_ros_driver2编译很快只是多花几分钟。但个人觉得没必要速腾和Livox的数据获取方式完全不同哈尔滨工业大学的代码里livox部分只影响Livox雷达的驱动接口不影响点云订阅的通用代码。3.3 launch文件修改点云话题重映射与IMU话题对齐FAST-LIO2编译通过后重点看launch目录下的mapping_velodyne.launch这个文件原本是为Velodyne雷达准备的但速腾16线输出的点云话题格式和Velodyne非常接近所以直接在这个launch基础上改是最省事的。改动点集中在三处点云话题remap把/velodyne_points映射成/rslidar_points。IMU话题remap把/imu/imu映射成你实际IMU的话题名。参数文件路径确保指向对应的yaml配置文件。举个例子我的launch文件里核心部分改成了这样node namefastlio_mapping pkgfast_lio typefastlio_mapping outputscreen param nameconfig_file typestring value$(find fast_lio)/config/velodyne.yaml / /node先不管参数文件launch文件里还会写remapremap from/velodyne_points to/rslidar_points/ remap from/imu/imu to/imu/data/注意IMU话题名一定得用你实际发布的那个话题名不要凭感觉写成/imu/imu。如果外接IMU的话题是/imu/data_raw那这里就写/imu/data_raw不匹配的话FAST-LIO2启动后一直等待第一条IMU消息控制台看起来像卡死了。3.4 参数文件里的关键项lidar_type、外参、降采样分辨率FAST-LIO2的参数文件是config/velodyne.yaml里面最关键的几项是lidar_type这个参数控制点云格式解析方式。对于速腾16线我们选的是1表示通用Velodyne类型。不要选0Livox类型选了之后点云会被解析成完全错误的数据。common:lid_topic表示点云订阅话题launch里已经remap了这里保持默认也可。imu_topicIMU话题名要和launch里的remap保持一致。preprocessblind设置雷达盲区过滤半径。速腾16线近距离点比较密我把blind设为0.5太小时雷达底座自身会被扫进地图。point_filter_num每多少个点取一个。默认2或3点太密时可以提高点太稀疏就保持1。mappingfilter_size_surf降采样体素大小我用的0.15可以理解成地图点最小间隔。太大地图轮廓粗太小计算负载高。acc_cov、gyr_covIMU加速度和角速度噪声协方差。如果你用的是雷达自带的低端IMU需要适当调大这两个值否则IMU权重过高会导致轨迹发散。extrinsic_est_en外参在线估计开关默认1打开后IMU和雷达外参会在线修正对装歪的情况有一定容错。extrinsic_T、extrinsic_R初始外参雷达坐标系到IMU坐标系的平移和旋转。默认是unit矩阵如果你只是把雷达和IMU固定在一起没有精确量过安装位置可以先保持零平移单位旋转打开在线估计也能跑。很多人一上来就问外参到底怎么填。我的经验是先按默认单位阵跑一次看建图是否稳定如果有明显的地面倾斜或墙体分层再测量雷达中心和IMU中心的位置差把平移量填进extrinsic_T旋转部分尽量靠机械结构保证水平。外参乱填反而会让系统一开始就发散。4. 保姆级运行流程从驱动到地图保存全步骤4.1 启动前的传感器连接检查在正式运行前把传感器状态过一遍能在后面省很多事。先检查雷达和IMU是否都通电并在正常工作。用rostopic list可以快速看到当前所有话题rostopic list确认存在/rslidar_points和你的IMU话题后再分别看一眼数据频率rostopic hz /rslidar_points rostopic hz /imu/data点云频率一般是10HzIMU频率从100Hz到400Hz不等只要不是0Hz就说明数据在持续进来。这里值得多说一句FAST-LIO2对IMU频率非常敏感如果IMU只有50Hz效果会明显变差。我实测200Hz以上表现最好如果外接IMU频率不够可以在驱动里做插值或直接换一个频率更高的IMU。4.2 按顺序启动雷达驱动和FAST-LIO2先启动雷达驱动roslaunch rslidar_sdk rslidar_sdk.launch驱动正常后新开终端启动FAST-LIO2source ~/catkin_ws/devel/setup.bash roslaunch fast_lio mapping_velodyne.launch启动后终端会打印一堆参数接着会显示当前处理频率和点云点数。如果一切正常终端会有类似Processing time和点数量的滚动输出。这时候启动RVizrosrun rviz rviz打开后添加PointCloud2显示话题选/cloud_registeredFixed Frame选camera_init。同时可以添加Path显示话题选/path这样能够直观看到机器人的运动轨迹。如果看到实时点云随着移动不断累积并且轨迹平滑没有跳变说明建图已经跑起来了。4.3 采集过程中必须注意的操作习惯FAST-LIO2建图效果很大程度上取决于采集时的运动模式。我的建议是移动时速度不要太快角速度变化要平缓避免急加速和急转弯尤其是刚开始算法收敛阶段尽可能让雷达视野内有足够的静止环境特征。如果一开始就直接快速旋转很容易导致点云配准错误地图直接飞掉。采集时可以手持设备或者把小车开到目标区域但无论哪种方式都要避免遮挡雷达的360度视野。速腾16线对遮挡比较敏感如果雷达一侧被身体挡住点云就缺一大块FAST-LIO2在缺线束时建图质量会下降表现为局部地图扭曲。还有一点很关键启动后不要原地反复快速旋转要先让设备静止几秒钟让FAST-LIO2初始化完成。我的习惯是启动建图节点后静止5秒观察终端输出的频率和RViz里的点云有没有稳定累积然后才开始移动。这个习惯帮我在很多次实验中避免了建图初期的发散。4.4 保存建图结果PCD文件的导出方法建图完成后地图数据存在FAST-LIO2节点内部的全局地图变量里默认不会自动保存。保存地图的操作在RViz里直接完成在左侧Displays面板找到MapAccumulate这个显示项右键选择Save Map As输入文件名后就会保存为PCD文件。我实际导出时用的比较多的是通过命令行方式在另一个终端执行rosrun pcl_ros pointcloud_to_pcd input:/cloud_registered不过这个命令保存的是实时点云不是全局累积地图如果你想保存完整建图结果还是用RViz的Save Map As最方便。导出PCD后可以用pcl_viewer或者其他点云处理软件打开pcl_viewer map.pcd能正常看到完整的三维点云就说明建图流程完整结束了。4.5 把PCD转成通用格式以便后续使用有时候建完图需要转成八叉树地图、栅格地图或者用于路径规划PCD只是第一步。我常用的转换思路是先把PCD做体素滤波或者直通滤波去掉离群点和杂点然后根据实际需要转成OccupancyGrid或者直接用octomap_server生成三维栅格地图。如果只是想看效果pcl_viewer足够但如果想用于导航建议用octomap_serverroslaunch octomap_server octomap_server.launch它可以直接订阅/cloud_registered话题实时把点云转换成OctoMap速度很快。这一步我建议等建图结束时再启动因为实时转换会稍微占用一点CPU影响建图性能。5. 避坑全记录典型问题、排查思路和解决方法5.1 雷达驱动启动了但RViz没有点云这种情况先不要慌按照链路从底层往上层排查。第一步确认网口IP和雷达IP在同一个网段ping一下雷达IP看网络通不通。第二步用rostopic list确认/rslidar_points话题是否存在如果话题存在但没数据用rostopic hz /rslidar_points看频率频率是0说明驱动节点没有收到网络包通常是防火墙拦了UDP数据或者网口配置错误。另一个常见原因是rslidar_sdk的config.yaml里配置了错误的lidar_type或数据源。比如把数据源配置成pcap回放模式却连接的是真实雷达那自然收不到数据。把config.yaml里的msg_source改成1在线模式lidar_type改成对应的雷达型号保存后重新启动驱动就能看到点云。5.2 FAST-LIO2编译失败的几个高频报错编译FAST-LIO2时最容易遇到这几个问题找不到Sophus。这个很典型需要确认Sophus是否真的编译并安装成功可以在终端执行ls /usr/local/lib/cmake/Sophus看看是否存在对应cmake文件没有就重新编译Sophus并sudo make install。找不到livox_ros_driver相关头文件。就像前面说的使用速腾时直接注释掉CMakeLists里livox相关的依赖。Eigen版本导致的报错提示static assertion failed之类的可以先删除系统自带的Eigen再源码安装一个新版本的Eigen或者直接在项目里用ROS自带的Eigen3包。编译问题通常都是环境问题把报错信息完整看一遍多半能定位到哪个依赖没装好。5.3 建图运行几分钟后地图开始飘地图飘的原因很多我遇到的最主要两类一是IMU和雷达的初始外参误差太大二是雷达和IMU数据的时间戳不同步。先说外参。如果IMU的安装方向和雷达坐标系没有对齐比如IMU的Z轴指向了雷达的X轴方向那么即使开着外参在线估计系统也需要较长时间才能收敛中间很容易发散。我的建议是尽量保证IMU和雷达坐标系完全对齐安装时用直尺量准位置把extrinsic_T填进去旋转部分最终靠在线估计去微调。时间戳不同步的影响往往被低估。FAST-LIO2做紧耦合融合时对点云时间戳和IMU时间戳的一致性要求很高。速度不会说谎如果时间戳偏移很大要么在驱动里做时间戳同步要么在FAST-LIO2的代码里调整时间补偿参数。我实际遇到的情况是外接IMU输出的时间戳是UTC而雷达时间是单调递增两者差了整整8小时导致算法里所有时间比较全部错乱表现就是地图跑成麻花状。解决方案是写一个小的时间戳重映射节点统一成同样的时间基准。5.4 点云显示有重影或者墙体变厚墙体变厚一般说明点云配准不够紧根本原因往往不是算法参数而是雷达自身在运动过程中出现了震动或者滑移。手持设备时手臂的颤抖会让相邻帧点云产生轻微错位反映在建图里就是墙体变厚或者物体边缘模糊。这种情况的解决办法首先是固定传感器用手推车时尽量让雷达安装座稳定。其次可以减小点云降采样的间隔比如把filter_size_surf从0.15改成0.1让算法使用更密集的点云进行配准。不过这会增加计算消耗实测在i5处理器上也能流畅运行只是占用更高一些。如果你在终端里看到Processing time明显上升但地图精度也提升了这个是正常现象。5.5 一个问题速查表常见状态对照为了快速定位问题我把常见现象和对应方向整理成了下面这个表排查的时候可以对着看。现象可能原因排查方向启动后无点云网口不通或话题未匹配ping雷达IP检查话题名和IP网段点云只有半边供电不足或网线丢包换电源和网线看是否规律性缺角FAST-LIO2启动后一直等待IMU话题不匹配或时间戳不同步检查IMU话题名和话题频率地图发散或者跳变外参错误或运动过激核对IMU与雷达坐标关系采集时缓慢移动地图有重影雷达抖动或降采样过大固定传感器缩小filter_size_surfCPU占用持续过高点云密度过大增大point_filter_num适当降低点云频率这个表是我在实际使用中不断积累出来的每次遇到问题我都会先对着表过一遍能节省不少时间。5.6 记录一个我印象最深的时间戳问题这个坑我特别想单独拿出来说。当时用速腾16线雷达驱动力内置的IMU数据FAST-LIO2启动后一切正常但跑了几分钟整个地图突然像被“掰弯”了一样越到后面越歪。我看了很多参数试了各种外参组合都没用后来把点云和IMU数据录制到rosbag里离线逐帧分析才发现IMU的header.stamp跳变和雷达点云的时间戳根本不是同一个时钟源。解决方案不复杂我在IMU驱动的输出端做了一个时间同步节点用雷达点云帧的时间作为基准把IMU数据的时间戳近似对齐到最近的雷达帧时间上。改完之后同样的采集路径再跑一遍地图就不再飘了。这个经历让我养成了一个习惯任何传感器组合开工前先写一行rostopic echo看一眼时间戳数值是否合理能用一分钟验证的时间就不要用半小时调试去填坑。6. 实操心得与后续扩展建议这套速腾16线加FAST-LIO2的组合我用了很长一段时间整体稳定性在国产雷达方案里是能打的。比起很多只用rosbag离线跑算法的教程拿到真实雷达数据后你才会发现驱动配置、网络通信、时间同步这些底层问题才是真正消耗时间的地方。我的核心建议是先确保点云和IMU这个话题链路通畅可靠再看算法参数顺序反了会让你一直在错误的方向上浪费时间。后续如果你想把建图结果用到导航上建议在保存PCD的基础上再准备一套地面平面提取和点云滤波流程因为FAST-LIO2输出的地图里有大量噪声点和动态物体点不处理直接丢给move_base使用代价地图会被污染。先用VoxelGrid降采样再用RANSAC提取地面把地面和过高点过滤掉剩下的点云转成2D栅格地图这样和传统导航栈对接就很顺了。最后再说一个小技巧采集时不妨在场景里放几个有明显特征的物体比如箱子、柱子或者墙角建图结束后用RViz里的测量工具量一下这些物体的尺度和位置如果和实际一致说明整套系统的精度是达标的这对判断数据是否有效、参数是否合适非常有用。