ARTICLE DETAIL

资讯详情

深耕编程入门与网站建设的一线实战洞察。

2D激光SLAM数据集实战:下载、测试与评估

2D激光SLAM数据集实战:下载、测试与评估 说句掏心窝的话2D激光SLAM入门这件事百分之八十的劝退点其实不在算法推导而卡在“手里没有像样的数据”上。自己拿真机录包先要搞定雷达、底盘、TF树和ROS环境一折腾就是好几天去网上下数据集不是链接失效就是不知道跑起来后该怎么看结果。我之前帮团队带过不少新同学也招过准备SLAM方向的人发现能把2D激光slam数据集真正用明白的人后面学建图、定位、导航都会顺很多。这篇文章我就把2D激光SLAM数据集的下载、测试、评估这套完整流程拆开讲清楚包括选哪种数据集、下载前要看哪些关键信息、怎么在Gmapping、Cartographer、Hector这些主流算法下跑通、地图质量又该怎么量化评价。内容适合正在学SLAM、准备SLAM面试或者工作中要做2D建图方案选型的朋友全程不依赖真实机器人一台普通电脑加一套ROS环境就能复现。1. 为什么一定要用数据集自采数据与公开数据的取舍1.1 数据集的真实价值复现、对比、定位问题实际做SLAM项目时最怕的就是“跑出来的效果说不清楚为什么好也说不清楚为什么差”。自己录的激进运动、雷达丢帧、轮子打滑这些干扰因素混在一起算法崩了你根本不知道该怪谁。公开数据集的价值在于它提供了一个固定的基准环境同一份激光帧、同一份里程计、同一份真值轨迹所有人跑出来的结果都具备可对比性。这个可对比性非常关键。比如你想判断Gmapping和Cartographer在走廊场景下的表现用同一份bag包各跑一遍谁的地图更直、谁的回环更闭合、谁的轨迹漂移更小一目了然。如果换成自采数据机器人两次走的路都不可能完全一致对比就没有意义了。还有一个特别容易被忽视的作用定位问题。假设算法在某个数据集上突然崩了你可以在固定数据上反复打断、重启、换参数直到复现问题为止。自采数据做不到这点因为场景是天然的测试状态很难回到完全相同的时刻。搞SLAM调试时间久了你会发现可复现性是最高优先级数据集天然自带这个属性。1.2 2D激光SLAM数据集的典型构成拿到一个数据集首先要看它的bag包里有哪几个话题。经典的2D激光SLAM数据集通常是这样一个结构/scan单线激光雷达的扫描话题数据格式为sensor_msgs/LaserScan周期一般是20Hz到40Hz不等。/odom轮式里程计话题nav_msgs/Odometry通常由机器人底盘驱动发布频率在50Hz左右。/tf变换树数据包含odom到base_link到laser这几个关键坐标系的位姿关系。/tf_static静态坐标变换一般是base_link到laser的固定变换以及base_footprint与base_link之间的变换。部分数据集还会带/imu话题sensor_msgs/Imu格式提供更多的姿态观测信息尤其适合给Cartographer这类多传感器融合算法使用。从数据文件的角度看公开数据集一般有两种分发方式。第一种是官方提供已经录制好的bag文件下载后直接rosbag play就行省事。第二种是提供原始数据包里的一组文件和对应的配置文件需要你自己用rosbag命令去打包或者用算法自带的工具解析。对初学者来说第一种更友好如果你想深入理解数据结构第二种更值得研究。1.3 主流公开数据集与适用场景圈内流传比较广的2D激光SLAM公开数据集大致可以分成三类选择时需要根据你的测试目的来定。第一类是室内结构化环境数据集比如经典的Freiburg医院走廊数据文件名类似47806_5001.bag这种风格场景是走廊加房间的医院环境包含规则墙面、直线过道和人流干扰。这种数据集非常适合入门和算法横向对比因为环境特征清晰地图可判读性强建的好不好一眼就看出来。第二类是室内办公环境数据比如Intel Research Lab等数据集环境有隔断墙、杂物、大面积开阔区激光扫描范围更复杂对算法在小闭环和大回环场景上的表现考验更充分。这类数据集适合验证算法的回环检测能力和长时间运行稳定性。第三类是服务机器人经常跑的“仿真录制包”很多ROS教程和开源课程会放出用Gazebo仿真环境录制的bag包含非常干净的/scan和/odom数据没有任何噪声。这类数据适合做流程试跑比如验证你的Launch文件和参数配置对不对但不太适合用来评价算法精度因为太理想了。选数据集有一个判断标准尽量找那些带明显几何特征的环境。墙角、门框、柱子、走廊拐弯这些地方是2D激光SLAM的关键结构没有这些特征算法分不清自己在哪地图质量会很差。你拿一份空旷操场的雷达数据给Gmapping跑结果必然是飞。2. 下载前必须搞懂的三件事话题结构、坐标系和时间基准2.1 用rosbag info拆解数据集的内部结构下载一个数据集之后不要急着解压就play。先花一分钟跑一条命令rosbag info 你的文件.bag这条命令会输出bag文件的路径、持续时间、消息数量、消息类型以及按话题统计的消息数据。我最关心的其实就是话题列表和消息类型这能直接告诉你这份数据里有没有算法需要的输入。比如一份数据输出长这样topics: /odom 5000 msgs : nav_msgs/Odometry /scan 2500 msgs : sensor_msgs/LaserScan /tf 9000 msgs : tf2_msgs/TFMessage看到这个结构心里就有底了。/scan是激光数据/odom是里程计/tf是坐标变换这套组合可以喂给Gmapping。如果话题里多了/imu那可能更适合跑Cartographer做IMU激光融合。如果数据里只有/scan而没有/odom那就别指望Gmapping了老老实实用Hector这类依赖高频激光匹配的算法。还有一个值得看的消息量比例。比如一个200秒的bag包/scan只有2000帧也就是10Hz这个频率对2D激光SLAM来说偏低了跑Gmapping的时候里程计更新阈值和粒子滤波的响应都会受影响。下载之前先看这个比例能省掉很多“算法怎么不工作了”的排查弯路。2.2 tf树与坐标系base_link与laser的耦合关系SLAM建图不是随便拿激光数据往上一堆就行的算法必须知道每一帧激光数据是在哪个坐标系、相对谁测量出来的。这就引出了tf变换树。一个典型的2D激光机器人tf树是这样map - odom - base_link - base_lasermap和odom之间的变换由SLAM算法自己在定位过程中维护odom到base_link由里程计推算base_link到base_laser一般是机器人结构决定的固定变换。打开一份bag包之前你要确认tf树是否完整。如果数据包里发布tf话题但缺少某个坐标系的变换算法启动后就会卡在tf_wait阶段反复报“Waiting for transform”错误。更隐蔽的问题是外参不对比如base_link到laser的平移或旋转填错了建图时就会出现激光点扫到墙上墙还是歪的这类现象。所以在真正跑算法之前看tf树是必须做的功课。可以直接用工具rosrun tf view_frames这条命令会生成一份PDF的tf树图打开看一眼层级关系缺谁补谁比对着终端日志瞎猜高效得多。很多人跑了一周Gmapping地图始终对不齐最后发现是数据发布者的base_laser配置和自己假设的不一致这种问题不看tf树根本想不到。2.3 use_sim_time数据集测试的隐藏开关这是大数据集测试里一个非常容易踩的坑。rosbag回放的是历史消息消息里的时间戳是录制时生成的和当前系统时间完全不同。如果按默认方式播放时间戳对不上算法会认为数据乱序或者过期表现就是地图频繁跳变、位姿初始化失败甚至直接不输出地图。解决办法是打开仿真时间模式让整个ROS环境以bag包里的时间为统一时钟。启动方式分两步rosparam set /use_sim_time true rosbag play --clock 你的文件.bag在Launch文件里也可以直接写死param name/use_sim_time valuetrue/这样rosbag在回放时会通过/clock话题发布仿真时钟所有订阅scan和odom的算法都会用这个时钟来对齐数据。这里插入一个我自己的教训use_sim_time只在bag回放时需要打开你在用真机调试时千万不能开着它否则节点之间的时间戳会按仿真时钟走真实传感器数据反而对不上。2.4 环境准备ROS版本与算法栈安装在开始跑之前先确认你的ROS环境。目前最常见的组合是Ubuntu 20.04配ROS Noetic也有不少人还在用Ubuntu 18.04配ROS Melodic。装算法包时注意版本匹配比如Gmapping的消息接口在不同ROS版本基本一致但Cartographer需要额外加官方源。小建议如果同时要跑Gmapping、Cartographer、Hector三个算法建议先装Gmapping和Hector因为它们依赖小安装快适合先跑通流程。等熟悉了数据结构和Launch文件写法再折腾Cartographer因为它编译慢、配置多新手上手容易卡住。sudo apt install ros-noetic-gmapping ros-noetic-hector-slamCartographer的安装稍微麻烦一点通常需要编译安装也可以直接找已经打包好的二进制版本。不管用哪种方式装完之后最好用官方自带demo先验证环境可用再拿自己的数据集去替换。3. 实操全流程从下载到建图可视化3.1 获取数据集文件下载数据集这块其实没什么神秘感但有几个实用技巧。很多国外大学和研究机构公布的数据集下载地址在国内访问速度很慢这种时候可以先看看有没有百度网盘或者国内镜像的版本。另外有一些bag包压缩得比较狠下载后要确认一下md5校验避免下到损坏的文件。我曾经下过一份十几GB的bag跑起来之后地图总是断断续续排查了半天才发现是文件在传输过程中损坏了白折腾一下午后来学乖了不管从哪下载先解压再校验校验通过再跑。还有一种取巧的思路直接用ROS社区里流传的demo bag这类文件通常体积小、数据规范专门是为了演示算法用的。对于第一次测试不要一上来就追求复杂数据集先找个几十MB的小包把流程跑通理解每一步的输出再换成大包深入调参效率会高很多。3.2 回放数据rosbag play的常用参数bag文件拿到手先不急着一股脑play把常用参数搞清楚rosbag play --clock -r 0.5 你的文件.bag-r参数控制回放倍速。第一次跑数据建议放慢到0.5倍速这样算法有足够时间处理每一帧数据rviz上的变化也看得清楚。如果你的电脑性能一般慢速回放还能避免CPU满载导致丢帧。还有一个很关键的参数-p可以只播放一部分数据段rosbag play --clock --start 10 --duration 60 你的文件.bag这句的意思是只回放从第10秒开始、持续60秒的数据段。当你想快速测试算法在某个拐角或者回环段的反应时用这个方式定位数据比每次从头播完整段要高效得多。回放的同时一定要开着rviz监视数据流。刚开始跑通流程时rviz是你的眼睛比看任何日志都有用。添加LaserScan、Map、RobotModel这几个Display就能看到激光数据和建图结果的实时变化。3.3 跑通Gmapping第一个地图的诞生Gmapping是基于粒子滤波的经典2D激光SLAM算法原理不复杂这里不展开讲但参数配置值得多说几句。下面这个Launch文件是我常用的最小可用版本launch node nameslam_gmapping pkggmapping typeslam_gmapping param namemap_frame valuemap/ param nameodom_frame valueodom/ param namebase_frame valuebase_link/ param namelaser_frame valuebase_laser/ !-- 按数据集实际情况改 -- param namemaxUrange value20/ param namemaxRange value30/ param nameparticles value30/ param namelinearUpdate value1.0/ param nameangularUpdate value0.5/ param nameminimumScore value50/ /node /launch几个关键参数我重点解释一下。map_frame、odom_frame、base_frame和laser_frame这四个必须和数据集的tf树对应上如果frame名对不上节点会一直报“waiting for transform”。minimumScore这个参数决定激光匹配的最低接受分数。默认50如果环境特征丰富可以调低到30左右如果环境空旷特征少建议调到100以上减少错误匹配。实际调的时候我会先跑一把看日志如果频繁弹出“scan matching failedusing odometry”就说明匹配分数阈值太高了往下调。particles代表粒子数量。粒子越多建图精度理论上越高但CPU占用也会暴涨。30粒子和80粒子在大型场景中差别明显但小办公室场景其实看不太出来。我先用默认值跑通再逐渐增加观察效果。跑起来之后rviz的Map话题上会实时出现栅格地图。第一次跑通的时候你可能会觉得“就这”但相信我看着激光帧在地图上慢慢铺开、墙线一点点对齐的时候那种心里有底的感觉是写多少理论推导都换不来的。3.4 换用Cartographer精度与调参初体验Cartographer是Google开源的多传感器融合SLAM方案它的鲁棒性比Gmapping强不少尤其在场馆、走廊这类对称环境里回环检测的能力明显更强。代价是配置复杂需要研究它的lua配置体系。跑Cartographer一般需要写两个文件一个lua配置文件和一个launch文件。lua文件里需要指定你数据的传感器配置核心参数包括map_builder { use_trajectory_builder_2d true, } trajectory_builder_2d { submaps_size 128, num_accumulated_range_data 1, min_range 0.3, max_range 30., use_imu_data true, }min_range和max_range要根据激光雷达的测量范围设置。如果数据集没有IMU数据需要把use_imu_data设成false否则节点会一直等着IMU话题不发定位结果。Cartographer相比Gmapping最大的坑在于它默认的多传感器融合逻辑比较复杂第一次跑数据时最容易出的问题是“点云不匹配”。如果你看到的submap是一团乱麻十有八九是传感器的内外参配置不对或者IMU方向装反了。调参的时候建议一次只改一个参数出来一张地图就保存一次否则很容易陷入“改了三行配置不知道是哪个起的作用”的状态。3.5 用Hector处理无里程计场景Hector算法最大的特点是只靠激光帧间匹配来估计位姿完全不需要里程计。它的适用场景很明确无人机、足式机器人、手持设备这些场景没有轮式里程计可用或者里程计精度太差。跑Hector之前要注意一件事因为Hector不依赖odom所以bag包里的odom话题对它是无用的它需要的是足够高频率、足够稳定的激光数据。如果数据集里/scan频率只有10HzHector建图会发飘但20Hz以上的数据就能跑出不错的轮廓。启动Hector的思路和Gmapping类似核心也是设置frame名字node pkghector_slam typehector_mapping namehector_mapping param namemap_frame valuemap/ param nameodom_frame valueodom/ param namebase_frame valuebase_link/ param namepub_map_odom_transform valuefalse/ /node注意设置了pub_map_odom_transform为false因为Hector不产odom如果你让它发布map到odom的变换而系统里又有真实的odom变换两套变换互相打架tf树就乱了。用Hector跑带里程计的数据集时你可以故意关掉里程计只看纯激光匹配的效果这会帮你在面试和工作里建立“传感器越多不一定越好关键是匹配要可靠”的认知。4. 地图质量怎么评估指标、可视化与对比4.1 主观判读的四个维度地图建出来第一件事是肉眼判读。别急着用一堆指标视觉判读虽然不严谨但往往是发现问题最快的方式。我一般从四个维度去品一张栅格地图。一是墙体的直线度。走廊和房间的墙在真实环境里是笔直的如果地图上墙体出现了波浪形扭曲要么是激光帧匹配不够好要么是里程计漂移没修正到位要么是雷达本身标定问题。二是闭环是否闭合。机器人绕着一圈走回到起点时地图上首尾相接的地方有没有错位。如果差了一截或者叠了两层说明回环没有成功检测到累计漂移没有消除这是最典型的质量问题。三是细节的完整性。墙角的直角、门框的宽度、桌角的轮廓这些细节在激光扫描下应该有明显、干净的栅格边界。如果细节模糊成一团说明点云匹配的精度不够或者栅格地图的分辨率设置得太低。四是轨迹和地图的一致性。把rviz里的轨迹显示打开看轨迹走向是否和地图结构相符。如果轨迹穿墙了或者在地图上画出了一条明显不合理的路径说明定位在某一段是丢失的即使地图最终看起来好像还行也不能信。4.2 量化评估思路轨迹对齐、回环检测与误差统计主观判读发现问题后要量化验证问题严重程度不然说不清是“有点丑”还是“不可用”。2D激光数据集通常不强制要求有ground truth但对于有轨迹真值的评测集最常见的方法是评估估计轨迹与真值的绝对姿态误差ATE和相对位姿误差RPE。这些指标可以使用开源工具evo来计算。基本使用流程是evo_ape kitti your_gt.txt your_est.txt -a evo_rpe kitti your_gt.txt your_est.txt -a如果你的bag包没有单独的轨迹真值也可以选择带有闭环的地图来间接估计。办法是找到地图上至少三个特征明显的点比如墙角、门框手动测量这些点之间的相对距离然后和实际地图中的栅格距离做对比估算比例尺下的位置误差。这个方法虽然粗糙但在没有真值的时候很实用至少能判断误差是厘米级还是分米级。还有一类更贴近工程实践的评估方式在一张已建好的地图上重新运行定位算法让机器人根据这张地图做重定位。如果在确定初始位姿后它能稳定输出连续、一致、不跳变的定位结果那这张地图的可定位性就是合格的。你建的图再好看如果机器人拿它定位时疯狂跳变那图也是废的。4.3 多算法横向对比的思路数据集最大的魅力就在这同一份数据三套算法各跑一遍结果放在一起对比。对比时不要光看最终地图要把运行过程中的CPU占用、内存峰值、卡顿情况一起记下来。比如Gmapping在低粒子数下CPU占用很低但长时间运行容易累积漂移Cartographer的CPU占用高一个量级但回环结果更稳Hector完全不吃odom但在快速旋转下会崩溃明显更适合类似无人机这类场景。另外别忘了对比建图时间和地图文件大小。有些算法为了精度牺牲了大量实时性这在嵌入式设备上可能是致命的。我见过有人用人人喊打的Gmapping跑出非常漂亮的地图也见过Cartographer参数没调对时建出来的图惨不忍睹。所以结论永远是“在特定数据条件下的表现”这比“A算法比B算法好”可靠得多。5. 常见问题与排查技巧实录5.1 建出来的地图是斜的/旋转的这是Gmapping里最常见的问题表现形式是走廊走完地图整体旋转了一个角度。排查思路先看坐标系确认数据集的odom话题是否真的给的是里程计消息而不是什么虚拟传感器。再看tf树中map到odom的变换有没有被算法正常发布。如果坐标系和tf都正常但地图仍然斜最可能的原因是里程计标定不准。轮直径误差、轮距误差、编码器分辨率都会让里程计在直行时偏转。这时可以尝试在Gmapping的launch里增加里程计外参补偿或者干脆改用Hector这类不依赖里程计的算法来验证看看地图是不是变正了。如果Hector下地图是正的基本可以锁定是里程计标定的锅。5.2 地图发飘或者跳变地图发飘通常分两种。一种是整体漂移机器人走到后面地图逐渐歪掉这是累计误差造成的Google Cartographer的submap和回环检测就是为了解决这个问题。另一种是局部跳变地图上同一面墙出现了双层轮廓某一段扫描结果突然平移了一段距离。局部跳变大概率是激光匹配失败引起的。这时候先看激光数据的频率和数据质量如果/scan话题上出现长时间的空闲间隔或者NaN值说明原始数据就有问题。再看运动速度机器人转弯太快时相邻两帧激光的重叠度过低Gmapping匹配不上就只能用odom做初始估计一错就跳变。可以尝试把线性更新阈值angularUpdate调小让算法更频繁地尝试扫描匹配。5.3 tf树报错常见报错是这类[ERROR] [xxx]: Could not get transform from base_laser to base_link这种错误基本都是frame名字对不上。tf树里发布的是base_laser但算法launch里写的是laser要么改数据发布端要么改算法配置端。另一个隐蔽的问题是两个node同时发布map-odom的变换比如Hector的pub_map_odom_transform没有关同时Gmapping也在发两个变换抢占tf就会造成tf树混乱。排查tf问题的首选工具是view_frames生成PDF图其次是用命令行工具rosrun tf tf_echo base_link base_laser这条命令会实时打印两个坐标系之间的变换如果输出为0且有“Listener timeout”字样说明等待不到变换大概率是发布端没有工作。5.4 时间不同步这其实是环境配置问题但我把它单独拎出来因为很多人会把时间不同步误判成算法问题。在rviz里看到激光点云拖影、地图滞后跟手、或者算法在启动时卡住十几秒不输出先检查一下use_sim_time是不是打开了。再往下想一层即使use_sim_time开了如果你的bag包录制时本身就没有发布/clock那算法还是等不到时间同步。这时需要确保rosbag play时添加--clock参数。我见过有人只开了use_sim_time但忘了在回放时加--clock结果是系统一直在等待时间基准屏幕上除了tf报错什么都出不来。5.5 CPU占用过高跑2D激光SLAM一般不会太消耗资源但Cartographer的submap更新在低端电脑上确实能让CPU飙升。如果CPU占用过高导致地图更新不及时可以优先做这么几件事降低激光订阅频率Cartographer在lua里有设置项可以控制输入点云的密度减小submap_size减小max_range让算法只处理有效测距范围内的点。Gmapping端的优化更直接把particles从30降到8CPU占用能下降一半以上在部分场景下地图质量几乎不受影响。但注意粒子数过低在回环场景下会导致定位发散这个需要结合你的数据特征去权衡。5.6 常见问题速查表问题现象可能原因检查顺序地图整体旋转里程计标定误差、坐标系配置错误1. tf树 2. 坐标系frame配置 3. 换Hector验证墙体波浪扭曲激光匹配精度不足、雷达参数设置错误1. min/max_range 2. 雷达扫描频率 3. 栅格分辨率回环处错位回环检测失败、累计漂移过大1. 运动速度 2. 粒子数 3. 换Cartographer对比地图跳变漂移激光匹配失败、odom误差1. 数据NaN检查 2. 匹配分数阈值 3. slow down回放tf等待超时frame不匹配、发布节点未启动1. view_frames 2. tf_echo逐个检查CPU占用过高算法配置过于激进1. 降粒子数 2. 降低激光输入频率 3. 减小max_range地图细节模糊栅格分辨率过低、激光数据太稀疏1. 提高分辨率 2. 检查数据频率启动后长时间无输出时间同步未配置1. use_sim_time 2. rosbag play --clock这套流程我前后带过不少新同事跑老实说能把一个bag包在三种算法下都跑通并清晰说出差异的人SLAM入门已经算是完成了大半。数据集这种资源看着不起眼但其实是最佳的调试靶场——你在上面花的时间最后都会转化成面对真实机器人时少踩的坑。最后分享一个我自己的调参习惯每跑一次实验就把launch文件和对应的输出地图截图存成一个带时间戳的文件夹一个月后你会感谢自己当初这个微小的记录习惯。
返回列表