尧图网站设计 尧图网站设计YAOTU DESIGN
ARTICLE DETAIL

资讯详情

深耕网站设计与一线实操的经验洞察。

四大主流2D激光SLAM算法同台实测:谁才是室内建图最优解?

四大主流2D激光SLAM算法同台实测:谁才是室内建图最优解? 先说结论如果你是刚入坑ROS的小车玩家或者正在给实验室/公司的移动底盘选建图方案这篇文章就是给你写的。2D激光SLAM这些年虽然被3D方案抢了不少风头但在室内导航、扫地机器人、AGV这类场景里单线激光雷达加两三种经典2D算法依然是性价比最高、最难翻车的组合。问题是网上一搜全是Gmapping好还是Cartographer好这种口水贴很少有人把四种主流算法放在同一台机器、同一条路线上用同一包原始数据跑完再逐帧对比。我这次干脆把Gmapping、Hector SLAM、Karto SLAM和Cartographer全装到一台底盘上用同一条室内通道反复测了三天把建图效果、参数影响、翻车点一并记录下来。文章里我会先捋清楚四种算法各自的原理流派和适用边界再给出我在实车上踩过的参数坑和调优经验最后附上常见问题的排查实录。无论你是想快速用手边雷达做一张能用的栅格地图还是想理解图优化和粒子滤波到底差在哪这篇都能让你少走弯路。1. 四种算法的整体设计思路与选型逻辑1.1 为什么偏偏是这四种算法2D激光SLAM的公开实现有很多但真正在ROS生态里被反复验证、社区资料齐全、随便拉一台带激光雷达的小车就能跑起来的绕不开这四位Gmapping、Hector SLAM、Karto SLAM和Cartographer。这四者背后其实是三种完全不同的技术流派。Gmapping基于粒子滤波Rao-Blackwellized Particle Filter它用一群带权重的粒子去猜测机器人可能的位姿轨迹再根据激光观测和里程计输入不断更新权重最后把概率最高的轨迹作为最优解。它的核心卖点是轻量、够用在小场景、低算力的设备上表现极其稳定所以直到今天依然是很多教学小车和简单AGV的默认选择。Hector SLAM走的是扫描匹配Scan Matching路线它不依赖里程计只靠激光雷达当前帧与已建立地图的匹配来估算机器人位姿内部用高斯牛顿法迭代优化。好处是部署极简单不用管底盘编码器、不用管轮径校准哪怕你手搓一个不能精确测轮的底盘也能直接建图。缺陷也很明显没有里程计约束长走廊和重复纹理环境下特别容易飘。Karto SLAM是图优化Graph-based SLAM的代表作。它把机器人的位姿序列看成节点把激光匹配得到的相对约束看成边建图过程实际上是在不断求解一个非线性最小二乘问题让整条轨迹在全局上尽量自洽。图优化比粒子滤波的思路更接近现代SLAM的形态但Karto开源版本的回环检测比较朴素没有完整的闭环策略。Cartographer是Google开源的重量级方案同样是图优化框架但它引入了Submap子图的概念激光帧先被匹配到当前子图上子图积累到一定帧数后再参与全局回环优化。这种局部先攒图、全局再修正的设计让Cartographer在大面积和复杂回环场景下精度明显优于前三者代价是配置复杂、计算量大、调参门槛高。1.2 建图效果到底比什么很多人对比SLAM算法只盯着地图像不像这其实不够全面。建图效果至少要从五个维度看栅格地图的全局一致性。绕一圈回来走廊有没有错位、门框有没有重影这是最直观的精度指标。差的算法在回环闭合时会把地图劈成两半好的算法能把同一面墙拼成一条直线。对传感器和里程计的依赖程度。Gmapping没里程计基本没法用Hector没雷达频率几乎就废Cartographer既吃激光也吃IMU这些依赖决定了你手里那台底盘能不能跑。实时性与资源占用。树莓派上跑Gmapping轻轻松松跑Cartographer就经常掉帧CPU占用能到百分之八九十。参数敏感度。有些算法默认参数就能跑出不错的地图有些算法你得调一整天。对工程落地来说耐造比天花板精度更重要。退化场景表现。长走廊、玻璃墙、动态行人、窄门洞这些场景最考验算法下限。我实测下来没有哪个算法是全能王每个都有自己的死穴。带着这五个维度去做对比就不会被单张漂亮的截图带偏。2. 实验环境搭建与数据采集2.1 硬件选型与底盘配置我做这组对比用的是一台普通的差速轮移动底盘轮子直径65mm编码器精度不高属于廉价教学底盘的主流水平。车载主控是Intel NUCi5-8259U跑Ubuntu 20.04和ROS Noetic。激光雷达用的是单线机械式雷达扫描频率10Hz测距半径12米角度分辨率0.36°左右。这套配置的意图很明确尽量贴近多数人手里的设备水平避免用高端传感器掩盖算法差异。有一点值得提如果你手头的底盘没有轮式里程计也别急着放弃后面Hector和Karto的对比部分会专门讲无里程计的情况。但如果你的目标是评估Cartographer我建议至少要有轮式编码器或IMU否则它很多回环参数发挥不出来测出来的结果会误导你。2.2 录制数据包的三个关键习惯想公平对比四种算法最稳的做法不是在实车上跑两次而是录一包rosbag然后离线回放给各个算法各跑一遍。这样输入完全一致差异全在算法本身。我总结三个关键习惯先把TF树理顺。四种算法都需要scan话题但Gmapping要odom到base_link的变换Cartographer还要imu数据如果有的话。启动前一定要确认TF树完整否则进算法之前就会报tf超时。推荐先单独跑一次tf_monitor确认频率稳定。录制时的运动方式很重要。不要原地旋转不要只走直线最好走S形路线并且每隔一段就回到已知区域制造闭环。机器人线速度我控制在0.3m/s左右角速度不超过0.5rad/s这样能保证激光帧间重叠度充足。单独录一段退化场景数据。找一段超过10米的连续走廊没有任何特征物专门用来测试Hector和Gmapping在这种场景下谁先歪。没有这段数据后面很多对比结论其实立不住。2.3 指标记录方法我用的评测方式很简单四个算法各跑三遍同一包数据记录每轮建图的耗时、发布地图的CPU占用、最终地图的栅格数量以及最关键的——回环闭合后地图的错位程度。错位程度怎么量化我在地图里选了三个固定参照点比如门框两侧和墙角用map_server保存地图后用图像工具量出墙线偏移像素数再换算成米。这个办法虽然土但比肉眼看起来挺准要客观得多。3. 核心算法原理解读与参数要点3.1 Gmapping粒子滤波的老将先聊Gmapping。它的工作原理可以理解成一群投票者猜机器人位置。每个粒子都代表一条可能的轨迹和对应的地图每来一帧激光算法会根据粒子预测的位置与激光观测的匹配程度给粒子打分然后按分数重新采样分数低的粒子被淘汰分数高的粒子被复制。最终所有粒子投票出来的轨迹就是机器人的估计位姿。这个机制决定了Gmapping有两个鲜明特点一是极度依赖里程计因为激光帧间匹配在空旷场景太容易退化了没有里程计引导粒子会发散二是它天然适用于小场景因为粒子数量是有限的场地越大需要的粒子数就越多计算量呈指数上涨。我这边实测下来Gmapping在小房间和短通道场景的建图质量非常能打地图干净、重影少。关键参数有两个particles默认30通常够用如果场地超过100平米建议加到40~60。太多粒子会让CPU爆表太少粒子在回环处容易漏匹配。minimumScore这个值控制激光匹配的可信度门槛。默认0.0太宽松导致在相似环境下误匹配地图容易叠出重影。我调高到0.3后重影明显减少。Gmapping的另一个优势是参数少、容错率高。我自己在树莓派3B上跑过CPU占用不到30%很适合算力受限的小车。3.2 Hector SLAM没有里程计也能建图的猛将Hector SLAM是我个人很喜欢拿来应急的方案。它完全不读/odom只靠激光帧和地图的匹配来做位姿估计。匹配的思路是假设当前位姿不动激光扫描点打到已有地图上的占用概率最大那么这位姿就是对的。为了让这个最大成立Hector用高斯牛顿法迭代搜索并且在多分辨率地图金字塔上从粗到细地找避免陷入局部最优。这个设计听起来很优雅但也埋了一个大坑没有全局约束只有逐帧累积。当机器人走过一段长走廊时激光看到的墙面都是重复的弧形截面扫描匹配很难判断我到底走到哪了误差就会沿着走廊方向累积最终地图末端严重歪斜。我在走廊场景里测Hector时走了15米之后墙线直接偏出20多厘米。所以Hector真正适合的场景是小型场地、无里程计底盘、需要快速建一张粗糙地图来应急。它的两个关键参数map_resolution地图分辨率默认0.05米。想跑更精细的地图就调到0.025但匹配计算量会翻四倍。map_update_angle_thresh和map_update_dist_thresh控制地图更新的频率。调小可以让地图更跟手但太频繁会让地图不断刷新、细节反而糊掉。用Hector还有个心得把激光雷达的扫描频率拉高对它有奇效。10Hz的雷达和20Hz的雷达建图效果差距肉眼可见因为高频激光能减少帧间位移匹配更容易收敛。如果你的雷达支持100Hz以上频率Hector的可用度会高很多。3.3 Karto SLAM图优化的中坚力量Karto SLAM在我眼里是四种算法里最中庸也最稳定的一个。它的思想是用图来表达机器人的一段轨迹图中的节点是机器人不同时刻的位姿图中的边是相邻位姿之间的约束由激光匹配或里程计得到。建图过程不是一个点一个点地猜而是在所有约束都不被破坏的前提下整体调整所有节点位置让整条轨迹的累计误差最小。这个整体调整是Karto和Gmapping最大的区别也是它在大场景下不容易飘的原因。图优化本质上是稀疏最小二乘问题现代的图优化库跑几百个节点都是毫秒级的。但Karto也有自己的短板。它的开源实现里回环检测非常简单粗暴只有当机器人回到已知区域附近时才会尝试添加回环边而且这个回环的搜索范围有限。如果机器人在长走廊里绕了一个大圈才回来Karto可能压根检测不到回环地图照样错位。Karto的核心参数没那么玄学但有一个直接影响精度scan_matcher_search_size或类似命名激光匹配的搜索窗口大小。默认较小如果地图容易重影可以适当调大让匹配器有更大范围寻找最优解。correlation_search_space_size相关性搜索空间在Cartographer里也有类似概念。这个值越大越不容易漏匹配但计算量暴增。我实测Karto在中等面积的室内场景比如100平米的办公室表现非常均衡比Gmapping在大场地更稳定比Hector在走廊更强壮。如果你不想花大量时间调参Karto的默认参数通常就能给出一个中上水平的地图。3.4 Cartographer重量级的精度担当Cartographer是这四种里唯一为大规模、高精度、回环强约束而生的算法。它的核心概念是Submap激光帧先在一个局部子图上做匹配局部优化子图积累一定数量后才被固定下来与此同时算法后台会持续把当前子图与之前所有子图做回环检测全局优化如果发现当前观测和历史观测有重叠就会在全球范围内调整所有子图的位姿让整个地图自洽。这个机制带来的好处是回环检测一旦生效误差会被拉回去地图的封闭性远超前三种算法。我在一个有回环的走廊场景里测Karto和Gmapping在绕回起点时地图都出现不同程度的错位Cartographer几乎完美闭合。代价也有三处。第一是配置极其繁琐2D的LUA配置文件里几十个参数新手看了就头大。第二是计算量巨大在NUC i5上回环检测打开时CPU占用长期维持在70%以上树莓派基本跑不动。第三是参数极度敏感尤其是loop_closure相关的字段调不好反而会让地图越建越糊。如果你准备用Cartographer我建议从这几个参数入手num_subdivisions_per_scan每帧扫描被切分的段数。默认1就行别乱改。loop_closure相关的min_score回环匹配的最低得分阈值。默认0.6左右调太低会产生错误回环调太高则检测不到回环。max_range激光最大有效测距。如果你的雷达能测12米但场地只有8米宽把max_range砍到10米能显著减少异常点地图更干净。map_builder里use_online_correlative_scan_matching这个选项推荐打开它能让前端匹配在天花板、玻璃等退化场景下更鲁棒代价是速度稍微变慢。3.5 小结四种算法怎么选从原理层面快速总结一下定位差异Gmapping是靠里程计带路、粒子投票猜位置的小场景之王Hector是无里程计也能跑、但长走廊必歪的应急方案Karto是图优化里最中庸、场景适应性最好的万金油Cartographer是回环最强、但配置和算力门槛也最高的高精度方案。选算法不要只看精度表要结合你的底盘、场地、算力三件事一起做决定。4. 实测建图效果对比与调优记录4.1 同场景同rosbag的量化对比先放结论。我把录好的那包室内场景数据依次回放给四种算法采用同一份雷达数据记录建图后的视觉效果和资源占用。场地大约120平米包括一条8米长的走廊、两间开阔办公室、若干门洞和一个明显的回环折返路线。指标GmappingHector SLAMKarto SLAMCartographer地图墙线重影轻微严重走廊端轻微几乎无回环闭合误差中等约0.15m很难闭合最终偏移0.4m中等约0.12m良好约0.05m长走廊表现稳定但缓慢漂移快速发散稳定稳定CPU占用35%45%50%85%关键依赖必须要有odom完全不用odom但吃激光频率需要odom需要odomIMU这组数据基本符合原理推演Gmapping和Karto在中小场景势均力敌Cartographer凭借回环优化稳压一头Hector则在长走廊场景直接拉胯。唯一让我意外的是Karto在回环闭合上的表现比预期好它在绕回起点后虽然有点小错位但没出现两半地图这种致命伤。4.2 分场景细说谁在什么情况下翻车在开阔办公室里四种算法都能建出轮廓清晰的图Hector和Gmapping的差异不大。但在有玻璃隔断的地方Hector会偶尔把玻璃反射点当成障碍物地图上多出一条雾状墙Gmapping因为有理粒子滤波的平滑作用反而能容忍这些异常点不会太受影响。到了走廊场景Hector的退化表现得非常明显。因为没有里程计约束它只能靠匹配墙面的相似轮廓来猜测前进量走到一半时算法会突然认为刚才那段已经来过了把地图往回折导致走廊末端出现一个断崖式的错位。Karto和Cartographer因为有里程计参与不会出现这种灾难性失败但Gmapping在直行段也会出现缓慢漂移只是漂移量不至于把地图彻底毁掉。最考验算法的是回环场景从办公室出发沿走廊走到尽头穿过另一个房间再绕回起点附近。Cartographer在这个环节的优势被完全放大因为它的回环检测会在回到起点时拉住整张地图前期累积的轨迹误差被一次性修正Gmapping和Karto由于回环检测能力弱只能靠前端匹配硬扛最终地图在起点附近出现了几厘米到十几厘米的裂缝。4.3 调参实战我踩过的那些坑调参是这次测试里最耗时间的环节。先说Gmapping最容易犯的错误是把particles调得很大。我试过粒子数调到80以为能提高精度结果CPU占用翻倍建图速度变慢地图却没变好。后来才明白粒子数增加只对高度不确定的场景有帮助在特征丰富的室内场景30~40个粒子已经完全够用。Hector最坑的参数是map_resolution。我一度调到0.025想追求高精度结果机器人在转弯时地图疯狂抖动因为分辨率越高匹配搜索空间越大单个栅格对应面积小激光噪声就会被放大。后来回到0.05再加上multi_res的层级匹配抖动才消失。记住Hector不适合调高分辨率它的强项是快速出图不是精细出图。Karto的参数相对温和但有一个细节容易被忽略scan_buffer_size或minimum_add_scan_shift这类控制什么时候才把新扫描加入地图的参数。如果值设得太小算法会在原地不断添加节点导致图里的节点数量爆炸后端优化越来越慢如果设得太大算法又会漏掉一些关键位置地图信息不完整。我建议的调试顺序是先改搜索窗口再动匹配阈值不要一上来就调图优化参数。Cartographer的调参是个无底洞我只说两个最实用的经验。第一看到地图上出现斜向条纹或者断层时优先检查前端匹配的参数尤其是translation_match_rotation_weight和rotation_weight这两个权重控制位移和旋转在匹配中的比重。第二如果地图出现整片偏移而不是局部错位问题多半在后端回环试着把loop_closure_min_score调低0.05~0.1让回环更敏感但小心低阈值会产生错误回环建出鬼影地图。4.4 一个容易被忽略的时间同步问题四种算法放在一起对比时间同步成了最容易翻车的环节。rosbag回放时如果激光时间戳和里程计时间戳不同步Gmapping和Karto的匹配就会收到错位的输入地图上会莫名出现很多细小毛刺。解决办法不是在算法里调而是在录制时刻意检查rostopic hz的频率稳定性以及用tf2的time travel检查工具排查TF时间戳是否存在跳跃。我这次测试时发现只要雷达驱动节点和底盘驱动节点启动顺序不同时间戳偏差就可能到几十毫秒对10Hz的雷达来说足以让建图结果产生可见误差。5. 常见问题与排查技巧实录5.1 地图重影和错位最常见的抱怨就是地图上有两道墙。排查顺序是三句话先看回环有没有闭合再看里程计有没有漂最后查外参标定。回环没闭合时地图末端和起始区域之间会出现错位裂缝里程计漂移时整张地图呈缓慢弯曲的香蕉形外参标定不对时墙线会出现固定的平行双影而不是随轨迹变化的错位。第三步需要你检查base_laser到base_link的TF是否准确很多廉价雷达装上去并不完全水平一个2°的安装倾角就会让远处点云产生几十厘米的偏移。5.2 算法运行卡顿和CPU爆满如果你跑Gmapping卡顿先看粒子数跑Cartographer卡顿看看是不是num_subdivisions_per_scan或扫描频率太高了。有个容易被忽略的点是激光雷达的scan_time参数。有些雷达驱动发布scan时会附带不规范的scan_time导致SLAM内部的时间插值混乱CPU无谓消耗。用rosbag info检查数据包的时长和消息数如果消息频率明显高于设定值先修驱动再调算法。5.3 长走廊时地图倾斜这个问题基本锁定Hector或者Gmapping在低特征场景下的累积误差。解决思路有两种要么换用带回环检测的算法Karto/Cartographer要么在硬件层面加IMU给算法提供一个绝对重力方向的参考避免横滚和俯仰方向的累积漂移。对我手里的这款底盘来说加了一个便宜的9轴IMU并将数据接入/imu话题后Gmapping在走廊里的表现立刻稳定了不少。5.4 地图锯齿严重地图边缘齿状严重通常是占用栅格的阈值设置问题。Gmapping和Karto分别有free_thresh和occupied_thresh默认值在不同版本ROS包里并不一致。如果你看到地图上明明平整的墙面变成锯齿可以尝试把占用阈值调高0.05左右让栅格更保守地判定障碍物。注意这个操作也会把细小的障碍物过滤掉如果你要检测电线杆之类的细目标就别调太高。5.5 回环闭合失败Cartographer比较常见的问题是回环检测到但优化没生效表现为地图突然闪一下然后恢复原样。这个多半是global_sampling_ratio或者图优化迭代次数不足导致的。我试过把optimization里的迭代次数从10提到20回环闭合的成功率有肉眼可见的提升。如果你用的是Karto回环失败大概率是因为搜索空间太小把correlation_search_space_resolution调小比如0.01能让回环在更精细的尺度上找到匹配。6. 不同底盘下的选择建议6.1 没有里程计的底盘手搓小车、麦克纳姆轮玩具底盘、或者轮子打滑严重的机器人都算这一类。直接上Hector是最快的路径但必须配合高频率激光雷达以及尽量小的场地。如果你的场地超过50米进深别挣扎了老老实实加装轮式编码器或IMU否则不管用哪个算法都救不了你。我这边用没里程计的底盘跑Hector在20米以内的场地效果还行再远就只能靠人工搬回来了。6.2 低算力平台树莓派3B、Jetson Nano这种算力受限的平台Gmapping依然是最优解。Karto在树莓派上勉强能跑但回环优化时会有明显卡顿Cartographer就别想了前端匹配加回环检测会把CPU吃满地图发布频率降到1Hz以下基本不可用。如果你的平台是Jetson Nano级别又特别想要Cartographer的精度可以尝试把激光频率从10Hz降到5Hz牺牲部分实时性换取帧间计算量下降。6.3 需要长期稳定运行的商用项目如果是AGV、巡检机器人这类7x24小时运行的场景我强烈建议直接上Cartographer或Karto并且一定要做好回环检测的配置。Gmapping长期运行会出现粒子耗散问题粒子多样性下降后地图质量会逐渐劣化。这不是Gmapping不行而是粒子滤波本身的迭代特性决定的——它更适合有限时间的建图任务不擅长无限期工作。7. 一些容易被人忽略的小细节7.1 雷达安装位置这个细节很少被人提起但对所有2D SLAM算法影响都很大。激光雷达安装位置越靠近底盘旋转中心建图时转弯导致的帧间位移越小匹配越容易收敛。如果雷达离旋转中心很远每次原地旋转都会让激光中心画一个很大的圆弧相邻帧之间的点云重叠度急剧下降匹配成功率也会跟着跌。7.2 地图保存与复用不管用哪个算法建图最终保存的pgm文件要配合yaml里的resolution参数一起用。我见过不少人在map_server加载地图时发现地图尺寸不对其实就是resolution填错了。还有一点如果你计划做后续的AMCL定位保存地图之前最好手动清理一下噪点用图像工具把孤立的小块擦掉这对AMCL的粒子收敛有明显帮助。7.3 不同算法的组合使用我见过不少老手在实际项目里并不只依赖一种算法而是先让Hector快速出一个全局轮廓再用Cartographer在线建图补充细节。这样既避免了Hector在长走廊翻车又能利用它的低延迟特性做实时避障。如果你在建图过程中发现某个区域反复出现重影也可以考虑在这个区域刻意放慢速度让算法有更多帧数进行匹配优化。8. 从这次对比中得到的几点体会折腾了三天踩了无数坑最后沉淀下来几条比较实在的体会。对室内小车来说Gmapping的够用和稳定依然很有价值不值得为了追新而盲目上Cartographer而如果你面对的场景有大量长走廊和回环需求不想花时间调参Karto的默认参数反而能给你一个超出预期的结果。Hector更像一个偏科生用对了地方高效省事用错了场合就是灾难。Cartographer的强大是真实的但它需要你付出配置和算力的成本还要有耐心去理解它那一堆参数之间的耦合关系。最后再分享一个小技巧除非你在做精确到厘米级的工业项目否则别为了追求地图精细度而把分辨率调到0.025以下。栅格地图的分辨率越高单帧激光的噪声越容易被放大反而导致地图更脏。0.05米分辨率在绝大多数室内场景下已经是精度和鲁棒性的甜点区。先用这个分辨率跑通流程再根据需要决定要不要往细了调这样能在排查问题时省下大量时间。
返回列表