ARTICLE DETAIL

资讯详情

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

2D激光SLAM数据集从选型到跑通建图完整指南

2D激光SLAM数据集从选型到跑通建图完整指南 很多研究SLAM和机器人的朋友一开始最容易卡住的地方反而不是算法本身而是手里没有一台能用的机器人、没有雷达、没有编码器最后连一处像样的测试环境都搭不出来。这个阶段我一直建议走一条捷径先用公开的2D激光SLAM数据集把环境、工具链和算法流程全部跑通再回头碰实物。2D激光SLAM数据集几乎成了社区里默认的标准试验田不管是用Gmapping、Cartographer还是Hector都能在公开数据上快速复现出建图效果逻辑也很清晰一张bag文件替代整台机器人一次下载解决传感器驱动、坐标系变换和里程计来源问题。这篇文章就把我从数据集的选型、下载、预处理到真正跑通建图的完整过程整理出来全是自己实测过的步骤和踩过的坑希望能帮你少走几步弯路。1. 为什么需要一份像样的2D激光SLAM数据集1.1 数据集能帮你解决哪几个实际问题先说说我自己的体会。最早学SLAM的时候我天真地以为只要有代码和论文就能跑起来结果在真实机器人上折腾了一周光校准里程计就花了大半时间。后来我换了个思路先不去动实体转用公开数据集做验证所有精力都集中在SLAM算法本身效率一下子拉高了很多。数据集解决的核心痛点有三个设备门槛2D激光雷达价格不低机器人底盘、编码器、IMU也不是人人都有。用数据集可以把传感器成本直接清零一台普通电脑就能跑。复现一致性你在数据A上跑出来的效果别人用同一份数据也能复现。评测算法、横向对比、写论文、准备面试都需要这样的公共标尺。调试效率真实机器人测试一次要充电、要清场、要防碰撞。而bag文件可以循环播放、慢放、快放甚至暂停在某个位置反复观察调试一个参数只需要几秒钟就能看到效果。1.2 数据集测试的三大典型应用场景从我的观察看大家下载2D激光SLAM数据集基本逃不过下面三种需求。算法验证场景。拿到一套新算法第一步就是用标准数据集看它能不能跑通效果大致处在什么水平。比如Gmapping和Cartographer在同样的Intel数据集上出来的地图质量就有明显差异这就成了评估算法能力的第一手依据。参数调优场景。同一份bag播放十遍每次只改一个参数观察地图的变化这是调参数最快的办法。比如Gmapping的particles从30调到80地图空洞和重影的改善程度肉眼可见这种反复试验只有在数据集上才方便实施。求职面试场景。现在SLAM方向面试很常问你跑过哪些数据集用的是什么算法地图效果怎么样。如果你能明确说出自己跑过哪些2D激光数据集、踩过什么坑、调过哪些参数这段经历在面试官眼里比空谈论文有价值得多。2. 主流2D激光SLAM数据集盘点与选型思路2.1 经典数据集横向对比ROS官方的Datasets页面长期维护着一批经典2D激光数据集社区常用的大致有下面这几类我按自己的使用体验整理了一张表数据集场景类型主要传感器是否含里程计是否含真值难度Intel Research Lab室内办公环境单线激光、里程计是部分有入门Freiburg 079室内走廊房间单线激光、里程计是部分有入门MIT CSAIL室内办公/实验室单线激光、里程计是否中等ACES Building室内长走廊开阔区激光、IMU、里程计是部分有中等DARPA Urban Challenge室外道路场景激光、GPS、IMU是是进阶这里面Intel Research Lab算是最经典的入门数据很多SLAM算法仓库的示例代码都拿它做演示bag文件不大场景结构清晰跑Gmapping约几十秒就能出图特别适合新手建立原来SLAM是这么回事的直观感受。有一点要提醒KITTI数据集虽然在国内外的搜索热度都很高但它本质上偏向视觉和3D激光设备是多线激光加相机场景是自动驾驶道路跟2D激光SLAM这个主题并不完全匹配。如果你想做的是单线激光室内建图优先选上面的经典2D数据集而不是KITTI。2.2 一份合格数据集必须包含的四个要素数据集质量参差不齐下载前最好先确认四点第一必须是装好的rosbag文件。2D激光SLAM的通用容器是ROS的bag格式里面按时间顺序记录了各种话题消息。拿到手就应该是.bag结尾的文件而不是一堆散落的原始数据。第二必须有清晰的TF坐标树。激光雷达数据要投影到机器人坐标系上必须知道laser和base_link之间的相对位姿。一份合格的数据集至少要提供odom到base_link的变换最好还能看到完整链路map - odom - base_link - laser。第三必须有稳定的里程计信息来源。多数2D SLAM算法需要里程计作预测模型比如Gmapping对里程计的依赖就很强。如果数据里只有激光、没有编码器里程计很多算法跑不起来这一点在下载前要看清说明。第四最好能带真值或评价依据。如果你要做定量评测比如计算轨迹误差就需要真值数据。如果不做量化分析只是看看建图效果真值可以忽略这个时候就靠眼睛判断地图里门、墙、柱子有没有对齐环路闭合处有没有重影。2.3 初学者怎么在这么多数据集里做选择我的建议是遵循由易到难、由小到大的原则。第一步先拿Intel Research Lab这种室内小场景跑通全流程环境结构简单bag可循环播放方便反复试参。第二步换Freiburg 079这类带走廊和折返的数据验证算法在开阔且重复纹理环境下的表现看看会不会出现漂移。第三步如果手里还有余力再去挑战ACES或者带IMU的数据测试激光与惯性数据融合的能力。另外一个不错的选择是自己生成数据集如果你装了Gazebo仿真环境可以在仿真场景里给机器人装上激光雷达录制一份完全可控的bag数据。这种方式特别适合做ros2 gazebo slam的联调因为场景、障碍物位置、运动轨迹全都能自己设计测试边界情况时非常方便。3. 数据集下载与准备全流程3.1 下载方式与文件整理下载数据集一般有几种渠道。最常用的是ROS官方Datasets页面上面分类整理了大量机器人数据集的官方直链很多研究机构和大学的实验室也会在GitHub仓库直接挂出bag文件的下载地址。如果是服务器或者远程机器建议直接用命令行工具# 以Intel数据集为例使用wget下载 wget http://example.org/datasets/intel.rosbag.zip # 如果你习惯用curl也可以这样 curl -O http://example.org/datasets/intel.rosbag.zip下载完之后先别急着播放养成检查文件完整性的习惯。很多bag文件是压缩包先解压再用ls -lh看一眼文件大小是否和页面说明一致防止下载截断。解压命令因压缩格式而异zip包就直接用unzipunzip intel.rosbag.zip我习惯在训练和调试前建一个干净的工作目录专门存放数据集比如~/slam_dataset/里面再按数据集名称分子目录。这样做的好处是后面跑多个数据集时文件不会混在一起也方便在脚本里引用路径。3.2 用rosbag info摸清数据底细拿到bag文件后第一步永远是用rosbag info看清楚里面有什么。这条命令的重要性再怎么强调都不为过它相当于手术前的全面检查。rosbag info intel.rosbag输出结果一般长这样path: intel.rosbag version: 2.0 duration: 142.1s start: Mar 06 2023 10:00:00.00 end: Mar 06 2023 10:03:22.10 size: 124 MB messages: 28500 types: sensor_msgs/LaserScan [90f2d4b0c9e07f7d2b8d0e0e0e0d3a5b] 15200 nav_msgs/Odometry [d2c9a4e0b3f0d5b8a9b0c4e8f0a1d3b7] 12000 tf2_msgs/TFMessage [c8a0d3e0a2b1f5c7e8d9a0b3c4e5f6a7] 1300 topics: /odom 12000 msgs : nav_msgs/Odometry /scan 15200 msgs : sensor_msgs/LaserScan /tf 1300 msgs : tf2_msgs/TFMessage这一段信息里有几个关键点要抓住duration决定了数据集时长topics说明数据里有哪些话题types则告诉你每个话题的消息类型。你可以用这个信息快速判断这份数据里有没有/scan、有没有/odom、有没有/tf。如果三者齐全跑主流2D SLAM算法基本没问题。再进一步可以看/scan话题的具体消息结构rosbag info intel.rosbag | grep -A 5 /scan或者干脆用rostopic echo在播放时实时查看rosbag play intel.rosbag rostopic echo -n 1 /scan看一眼输出的angle_min、angle_max、angle_increment和ranges数组长度就能知道激光雷达的扫描范围是270度还是360度角分辨率是多少这些参数在配置SLAM算法时直接决定能不能完整感知周围环境。3.3 播放数据集前必须做好的三个关键设置bag播放听起来简单但细节处理不好很容易埋下隐患。我总结了三个必须做的设置。第一个是时间同步use_sim_time。数据集里记录的时间戳是当年录制时刻的时间不是现在的时间。如果你直接播放程序拿到的系统时间会和bag时间对不上导致SLAM节点的帧间变换计算紊乱。正确做法是让ROS使用bag里的模拟时间rosparam set /use_sim_time true或者更推荐在启动launch文件时直接设置param name/use_sim_time valuetrue/然后播放bag时带上--clock参数让节点能获取到模拟时间源rosbag play --clock intel.rosbag第二个是循环播放-l参数。调试参数时总希望同样的数据反复跑这时候就加-l参数让它循环播放。要注意循环播放时在衔接点处数据会产生跳变如果建图到一半跳回起点可能导致轨迹不连续。所以循环播放适合前期观察话题数据是否正确正式建图时更好用单次播放。第三个是播放速率-r参数。默认情况下bag按原始录制速度播放即-r 1.0。如果电脑性能不够SLAM节点处理不过来可以把速率降到-r 0.5甚至-r 0.3给算法留足计算时间。反之如果只是想快速验证流程也可以用-r 2.0加速播放。# 以一半速度播放同时发布模拟时钟 rosbag play --clock -r 0.5 intel.rosbag4. 从零跑通2D激光SLAM建图完整实操4.1 环境准备与依赖安装测试SLAM数据集需要一套完整的ROS环境。以Ubuntu 20.04为例我推荐直接安装ROS Noetic的桌面完整版里面已经包含RVIZ、TF、坐标变换等核心组件sudo apt update sudo apt install ros-noetic-desktop-full接下来安装常用的2D SLAM工具包。Gmapping和navigation相关的包可以直接通过apt安装sudo apt install ros-noetic-gmapping sudo apt install ros-noetic-cartographer-ros sudo apt install ros-noetic-navigation安装完成后把ROS环境配置加入~/.bashrc这样每次打开终端就不用重复配置echo source /opt/ros/noetic/setup.bash ~/.bashrc source ~/.bashrc这里我建议所有SLAM工具装在一个新鲜的ROS环境里尽量不要混装多版本ROS或频繁更新系统依赖不然很容易出现依赖冲突这种问题排查起来特别耗时。4.2 最小可复现流程bag Gmapping RVIZ这是我最推荐新手先跑通的第一条完整链路所有环节加起来不超过10分钟。先打开第一个终端启动roscore如果使用launch文件则不需要roscore新开一个终端设置模拟时间并播放bagrosparam set /use_sim_time true rosbag play --clock /path/to/intel.rosbag再开一个终端启动Gmapping。最简单的做法是直接用现成的launchroslaunch gmapping slam_gmapping.launch但实际使用中slam_gmapping.launch默认订阅的话题名和bag里的话题名不一定对得上我一般会自己写一个最小launch文件命名为test_gmapping.launchlaunch node namegmapping pkggmapping typeslam_gmapping outputscreen param namebase_frame valuebase_link/ param nameodom_frame valueodom/ param namemap_frame valuemap/ remap fromscan toscan/ param nameparticles value30/ param nameminimumScore value50/ /node /launch注意remap fromscan toscan/这一行如果bag里的激光话题名不是/scan就改成实际话题名。如果bag里的里程计话题是/odometry而不是ROS默认的/odom同样可以加一行remap fromodom toodometry/。再来一个终端启动RVIZrosrun rviz rviz在RVIZ界面的左下角点击Add按话题添加/map类型为nav_msgs/OccupancyGrid再添加/scan和/tf就能实时看到激光点云和地图构建过程。启动的顺序有一点小心得最好先让bag播放起来再启动Gmapping节点这样算法一启动就能收到数据不会出现启动即等待的空窗期。如果反着来Gmapping启动后没有数据部分实现可能会在初始化阶段卡住。整个流程跑完RVIZ里会呈现出一个逐渐完整的二维栅格地图先是扫描线铺开然后地图边缘慢慢闭合。看到这个过程的一瞬间你对SLAM整个流程的理解会立刻清晰起来。4.3 升级一下用Cartographer跑出更高质量的地图Gmapping出来得快但地图细节和环路闭合效果一般。想追求更高精度的建图结果我推荐试试Google开源的Cartographer。它在2D激光SLAM上采用了子图加回环检测的思路对里程计的依赖比Gmapping小建图效果也更稳。Cartographer跑自定义bag要准备两样东西一个URDF模型描述机器人外形和雷达安装位置一个launch文件。URDF文件示例保存为laser.urdf?xml version1.0? robot namelaser_sensor link namebase_link/ link namelaser/ joint namebase_to_laser typefixed parent linkbase_link/ child linklaser/ origin xyz0 0 0.1 rpy0 0 0/ /joint /robotCartographer启动文件示例保存为test_cartographer.launchlaunch param name/use_sim_time valuetrue/ node namecartographer_node pkgcartographer_ros typecartographer_node outputscreen remap fromscan toscan/ param namemap_frame valuemap/ param nameodom_frame valueodom/ param namebase_frame valuebase_link/ param nametracking_frame valuelaser/ param namepublished_frame valueodom/ /node node namerviz pkgrviz typerviz/ /launch启动方式和Gmapping类似先播放bag再启动Cartographer。Cartographer的配置项很多测试阶段不需要全部改明白把上面几个frame参数确认好再保证/use_sim_time为true基本就能跑出结果。后续再按需调整map_builder里的分辨率、子图大小等参数。如果手里连现成的bag都没有还可以用Gazebo仿真自己录制数据集。在仿真环境里给机器人模型挂上激光雷达手动控制或调用导航功能走一圈用rosbag record /scan /odom /tf把话题记录下来就得到了一份属于你自己的可控数据集。这样做的好处是场景、路径、噪声都能自己定制非常适合做ros2 gazebo slam的联合调试也方便验证算法在不同环境下的鲁棒性。5. 我踩过的坑常见问题与排查思路5.1 TF树不完整算法直接罢工这是我第一次跑数据集时遇到频率最高的问题。表现是SLAM节点启动后一直报Transform error地图始终是一张白纸。TF坐标变换树是整个SLAM系统的血管如果bag里缺少某个关键变换比如odom到base_link算法就不知道机器人当前在世界坐标系的什么位置自然没法建图。排查方法分两步走。先看话题里有没有TF数据rostopic echo /tf有数据的话再生成TF树的可视化文件rosrun tf view_frames打开生成的frames.pdf检查这棵树是否包含map、odom、base_link、laser这些关键节点以及节点间的连接关系是否合理。如果bag里只缺一小段变换比如缺少base_link到laser的TF可以用static_transform_publisher补上rosrun tf2_ros static_transform_publisher 0 0 0.1 0 0 0 base_link laser但如果bag里压根没有odom就需要考虑换算法或者用其他方式补里程计这个就不是加一行命令能解决的了。5.2 时间戳不同步地图开始漂移第二个高频问题是时间不同步。症状是地图建着建着走廊宽度忽大忽小或者明明走的是闭合路径地图上的终点却和起点错开一大截。绝大多数情况下这是因为没有启动模拟时间。具体表现是RVIZ里激光点云正常显示但就是飘因为算法拿到的激光时间戳和当前系统时间对不上帧间变换全程错位。解决方式前面已经提过播放bag时务必加上--clock并且所有需要同步的节点都设置/use_sim_time为true。一个容易忽略的小坑是如果某个launch文件里单独设了use_sim_time为false哪怕全局设了true也会被覆盖所以调试时统一在bag播放端和节点端都检查一遍。5.3 参数不匹配的典型症状与调参方向数据集跑通之后大家最爱干的事就是调参。我总结了几类典型症状和对应的调参方向供你参考。地图出现大量噪点和空洞通常是粒子数太少或者激光匹配得分阈值过低。Gmapping里调高particles比如从30调到60调高minimumScore到100以上地图会干净不少。地图边缘有重影或错位多半是里程计噪声模型设置得过于乐观或者优化频率不够。Cartographer里可以调低trajectory_builder_2d的linear_velocity_limit让算法对高速运动更保守同时检查loop_closure相关参数是否开启。计算资源占用过高如果电脑风扇狂转地图刷新卡顿先降低播放速率-r 0.5再把occupied_space_cost或体素分辨率调大一些。地图分辨率越高计算量越大建图效果并不一定线性提升需要找一个平衡点。地图中间出现奇怪的放射线或跳变这往往不是SLAM算法本身的问题而是bag里激光数据本身就带有传感器噪声。比如某些数据集录制时经过了玻璃墙或金属反光面激光打到上面会产生错误的测量值导致地图上出现假墙。这种问题优先检查原始/scan数据看对应角度上的距离是否出现突跳。5.4 常见问题速查表我把平时被问得最多的几个问题整理成一张速查表收藏起来能省不少事。现象可能原因快速排查与解决SLAM节点启动后没有地图输出话题名不匹配rostopic list对比话题用remap重映射报错Transform errorTF树缺失某个变换rosrun tf view_frames查看静态TF补全地图漂移、重影严重时间未同步播放bag加--clock确保use_sim_time为trueGmapping建图特别慢粒子数过多或数据量过大先降播放速率再调低粒子数激光点云在RVIZ里看不到话题名错误或Frame错误检查/scan名称和Fixed Frame设置地图保存后加载乱码RVIZ显示设置问题用map_saver另存加载时选择正确地图话题文件播放到一半中断内存不足或文件损坏重新下载或分段播放验证地图与真实场景尺寸对不上栅格分辨率设置不合理调整地图分辨率参数确认激光传感器的角度范围和距离范围这里单独说一下地图保存。很多人建完图不知道怎么把地图导出来其实ROS自带工具rosrun map_server map_saver执行后会生成map.pgm和map.yaml两个文件前者是图像格式的地图后者是描述文件记录分辨率、原点位置等参数。这也是后续做自主导航比如配move_base必须准备的成果物。最后再分享一点个人经验数据集跑通的标志不是你看到了一张完整地图而是你对数据从头到尾流经了哪些节点、每个节点做了什么事有了具体的感知。我在实际使用中养成的习惯是拿到任何一份新bag先不急着接算法而是花几分钟用rosbag info把话题、时长、频率全部摸一遍再rosbag play --clock放两圈期间在RVIZ里盯着/scan看数据是否稳定、有没有丢帧确认数据健康之后才启动SLAM节点。这个小习惯帮我省掉了大量调试时间也让我在换数据集时基本不会踩不知道数据里有什么的坑。最后再分享一个小技巧调试参数时不要一次性改三四个变量。每次只改一个参数跑一遍bag对比地图变化再决定下一步。这样虽然看起来慢但每一步都在积累可复用的经验调参调多了你对算法参数的敏感度会明显提升。2D激光SLAM数据集测试这条路走通一次之后后面换算法、换数据集、甚至自己录数据都是水到渠成的事。
返回列表