ROS2激光SLAM算法对比实战:GMapping与Cartographer仿真解析

发布时间:2026/8/31 10:22:47
ROS2激光SLAM算法对比实战:GMapping与Cartographer仿真解析 简介本资源是一套面向机器人方向本科生与研究生的ROS2 SLAM算法对比仿真实践包适用于毕业设计、课程设计及期末大作业等教学场景旨在解决SLAM算法在ROS2平台上的部署、测试与性能评估难题。压缩包共476个文件85.1MB涵盖72个SDF世界模型、71个配置文件config、148个DAE三维模型、94个PNG纹理贴图、26个JPG环境图像、11个Python节点脚本、8个YAML参数配置及Docker相关文件Dockerfile、docker-compose.yml等完整支撑turtlebot3_rtab与turtlebot3_burger双仿真环境搭建与多算法对比实验。已有45人学习下载资源内置RTAB-Map等主流SLAM算法的ROS2接口实现、RVIZ可视化配置、PGM地图输出及Software GET Assessment评估框架参考文档PDF目录结构按功能模块划分清晰便于快速定位建图、定位、参数调优与结果分析各环节代码与配置。1. 项目整体脉络与设计思路前阵子整理了一版基于ROS2的SLAM算法对比仿真环境正好赶上ROS2 Humble在机器人圈子里普及率越来越高很多朋友手里有雷达、有机器人底盘却卡在“SLAM算法到底该选哪个”这个问题上。GitHub上各种仓库星罗棋布论文里的指标天花乱坠但实际跑起来什么表现只有仿真里遛一遛才知道。这个项目说白了就是干一件事在一套统一的ROS2仿真环境里把主流的2D激光SLAM算法都跑一遍用相同的地图、相同的传感器噪声模型、相同的机器人运动轨迹来对比不同算法在构图质量、计算资源消耗、鲁棒性上的差异。压缩包里的内容包含完整的Gazebo仿真世界、机器人URDF模型、雷达参数配置、各SLAM算法的launch文件以及一套地图精度评估脚本。我选择仿真而不是直接用实体机器人做对比原因很现实实体实验的复现成本太高不同时间、不同光线、不同地面材质都会引入额外变量对比结果很难归因到算法本身。仿真环境可以精确控制噪声模型。Gazebo里给激光雷达加上高斯噪声、给里程计加上漂移这些噪声水平是可以量化的A算法和B算法的差异就完全来自算法本身。可以批量跑实验。一个场景跑完换个场景继续跑不需要人工干预夜间挂着跑就行。项目适合这几类人参考刚入门ROS2、想把SLAM整体流程跑通的新手已经在用某个算法、想评估是否要切换方案的开发者以及做毕设或课程项目、需要实验数据支撑的学生。我尽量把整个环境搭建、参数调优、结果分析的过程都讲透文中涉及的配置和脚本都是实际跑过的版本。2. 环境选型为什么是ROS2 Humble配Gazebo2.1 ROS2发行版选择与依赖安装ROS2的发行版选择是个容易被低估的决策点。目前主流的Humble长期支持版2024年5月前维护、Iron短期支持版、Jazzy新LTS各有拥趸。做SLAM仿真对比我建议直接上Humble原因不复杂绝大多数SLAM算法的ROS2版本是在Humble上验证过的生态最完整。Cartographer、GMapping、SLAM Toolbox这些核心包的二进制版本在Humble上可以直接apt安装省去源码编译的很多坑。Iron的二进制包虽然新但部分第三方算法包没有跟上源码编译时经常遇到ABI不兼容。Jazzy刚出的时候很多包还没适配等生态成熟还要一段时间。安装过程网上教程很多我只强调几个容易出错的地方。如果是从零开始装建议用apt方式而不是源码编译除非你确实需要修改ROS2核心代码。安装完成后务必确认环境变量已经写入~/.bashrc否则每次开终端都要手动source。提示安装完成后先跑一下ros2 run demo_nodes_cpp talker和ros2 run demo_nodes_py listener验证基础通信是否正常别急着装仿真环境。基础没通后面排错会很崩溃。2.2 Gazebo仿真器的版本匹配问题ROS2 Humble对应的是Gazebo 11即gazebo_ros_pkgs的Humble版本。这里有个容易踩的坑很多人会去装Gazebo Classic的独立版本然后发现ROS2的话题根本连不上因为gazebo_ros2插件只认ROS2接口版本匹配的Gazebo。安装建议直接执行sudo apt install ros-humble-gazebo-ros-pkgs这个包会连带装好Gazebo 11本体和ROS2的桥接插件。装完后可以用gazebo --version确认版本号再用ros2 pkg list | grep gazebo确认ROS2接口包是否就位。有一个经验值得单独说如果你用的是虚拟机Gazebo的性能会非常拉胯。SLAM仿真涉及大量传感器数据计算虚拟机里的3D加速一般都不行画面帧率低还是小事关键是仿真时钟会变慢。/clock话题的时间戳和真实时间对不上SLAM算法的里程计积分就会出问题地图直接建歪掉。所以能用物理机绝不用虚拟机这是跑仿真实验的第一条铁律。2.3 仿真世界的构建与传感器建模仿真环境的核心是“一个能复现SLAM挑战的空间”。我设计了一个35米乘25米的室内场景包含标准的长直走廊和大转角用于考验SLAM的全局一致性。多处相似纹理的区域几乎相同的墙角结构用于考验回环检测能力。一些窄通道宽度仅比机器人宽40厘米用于考验雷达在这种场景下的退化情况。几根细柱子用于考验算法对细长物体的保持能力。这些挑战不是随便加的都是实际建图中最常翻车的场景。走廊场景最容易暴露累积漂移问题相似区域会对回环检测算法造成干扰窄通道里雷达的多路径效应会导致测距跳变。机器人模型我用的是差分驱动底盘上面搭载一个2D激光雷达。雷达的仿真参数如下参数数值说明扫描范围0.1m ~ 30m覆盖仿真世界最大尺度扫描角度360度全向扫描角分辨率0.5度720个扫描点扫描频率10Hz常见商用雷达的频率高斯噪声标准差0.01m模拟真实传感器的测距噪声更新速率10Hz与扫描频率一致雷达噪声水平设置到1厘米这个数值参考了入门级商用雷达如RPLIDAR A1的标称精度。如果设得太低算法表现会过于理想化起不到对比筛选的作用设得再高部分算法会因为传感器退化直接失效对比就无法完成了。1厘米是个相对公平的中间值。里程计方面给轮式编码器叠加了随时间和运动距离增长的小角度漂移。这个很关键因为纯编码器里程计在长距离运动时一定会累积误差。我设置的漂移率为每米0.5度的偏航角误差模拟的是没有陀螺仪辅助的底盘。3. 核心算法选型与原理梳理3.1 GMapping粒子滤波的老牌选手GMapping是2D SLAM里出了名的老牌算法核心思路是Rao-Blackwellized粒子滤波。每个粒子携带一个地图假设和一个机器人位姿假设。随着机器人运动粒子不断根据观测数据更新权重权重高的粒子会繁殖权重低的粒子会被淘汰最终收敛到最可能的地图和轨迹组合。在ROS2里跑GMapping可以直接用ros-humble-slam-gmapping包launch文件里主要需要调这几个参数particles粒子数量默认30。粒子越多对复杂环境的表达能力越强但计算量也线性增长。这个仿真场景我推到60个粒子效果已经有明显提升。minimumScore激光匹配的最低得分阈值默认0.0。调高可以避免错误的激光匹配导致地图被污染但设太高会导致正常匹配也被拒绝。我实测在仿真里设到0.3左右比较合适。linearUpdate和angularUpdate触发扫描匹配的最小位移和转动。默认分别是1.0米和0.5弧度对于室内场景有点太粗糙我缩小到0.2米和0.1弧度地图质量提升明显。maxUrange激光最大有效距离默认是80米。仿真场景里雷达的有效距离是30米这个参数保持默认就行但对某些传感器特性不好的实体雷达把它调小有时候反而能提升性能因为远距离的点噪声太大反而影响了匹配。GMapping在ROS2里跑起来有个比较明显的特征CPU占用率高。因为这个粒子滤波器是纯CPU计算每个粒子都要独立维护一张地图栅格。60个粒子的配置下我这边四核处理器跑得满负荷但这在可接受范围内毕竟粒子滤波本身就是计算密集型的。3.2 Cartographer图优化的现代流派Cartographer是Google开源的项目核心思路是图优化。它把激光扫描匹配的结果作为图的节点位姿把相邻节点之间的约束和回环检测得到的约束作为图的边然后通过非线性最小二乘来优化所有节点的位姿从而获得全局一致的轨迹。这个思路和粒子滤波最大的差异在于粒子滤波靠“广撒网”来覆盖不确定性图优化则靠“算精确”来消除不确定性。Cartographer在回环检测上花了大力气它还维护了一个子图submap集合每次新的扫描先和当前子图匹配同时也会和历史子图做匹配如果发现回到了此前到过的区域就会建立一个回环约束。在ROS2里用Cartographer通常是源码编译因为ros-humble-cartographer的二进制包有时候版本不够新。编译依赖有abseil、ceres-solver、protobuf等建议参考官方文档一步步来。配置上我用的核心参数如下TRAJECTORY_BUILDER_2D.min_range 0.1 TRAJECTORY_BUILDER_2D.max_range 30. TRAJECTORY_BUILDER_2D.use_online_correlative_scan_matching true TRAJECTORY_BUILDER_2D.ceres_scan_matcher.occupied_space_weight 10. TRAJECTORY_BUILDER_2D.ceres_scan_matcher.translation_weight 10. TRAJECTORY_BUILDER_2D.ceres_scan_matcher.rotation_weight 30. -- 回环检测相关 POSE_GRAPH.optimize_every_n_nodes 35 POSE_GRAPH.global_sampling_ratio 0.003 POSE_GRAPH.constraint_builder.sampling_ratio 0.3 POSE_GRAPH.constraint_builder.min_score 0.55这里有几个调参经验可以分享use_online_correlative_scan_matching实时相关扫描匹配很关键。它会在当前位姿附近做一次暴力搜索找到最优的初始位姿再交给Ceres进行精细优化。这个机制能显著提升匹配的鲁棒性缺点是耗时增加。在仿真环境里计算资源充足开着没问题。如果实体机器人主控性能弱这个选项建议关掉以保实时性。rotation_weight设为30明显高于平移权重是因为激光匹配在旋转上的不确定度更大提高旋转权重可以让优化器更重视角度误差的消除。global_sampling_ratio控制全局回环检测的采样密度。设得太高会显著增加计算量设得太低可能错过回环。0.003这个值在室内中等场景是个比较稳妥的起点。实测下来Cartographer在回环的场景里表现非常出色。机器人绕一圈回到起点时它能明显修正之前累积的漂移地图的全局一致性比GMapping好上一个档次。代价就是配置复杂度高心智负担重。3.3 SLAM Toolbox兼顾建图与定位的实用派SLAM Toolbox是Karto SLAM的ROS2延续版本核心也是图优化。它最大的优势是支持“建图完成后继续定位”也就是说同一个地图可以保存下来下次启动时直接加载然后在这个已有地图上进行定位。不用重新建图。这个特性在真实场景中价值极高毕竟生产环境不可能每次都让机器人重新扫描一遍全场。SLAM Toolbox的一个突出设计是地图的“程序化修改”可以在线进行地图的手动修正、删除错误区域、替换局部地图。比如建图时某个区域混入了动态物体的痕迹可以在GUI里圈选删除重新优化。这在另两个算法里是做不到的。它的配置主要在mapper_params里我用的关键设置slam_toolbox: ros__parameters: use_scan_matching: true minimum_travel_distance: 0.1 minimum_travel_heading: 0.05 scan_buffer_size: 120 scan_buffer_maximum_scan_distance: 15.0 link_match_minimum_response_fine: 0.6 link_scan_maximum_distance: 5.0 loop_search_minimum_response_coarse: 0.55 loop_search_minimum_response_fine: 0.6 correlation_search_space_dimension: 0.5 correlation_search_space_resolution: 0.01 correlation_search_space_smear_deviation: 0.03scan_buffer_size决定了保存多少帧历史扫描数据用于回环搜索。设得越大能找到更早的回环但内存和搜索时间都会涨。120帧在10Hz的雷达频率下等于12秒的历史在这个尺寸的空间里是够用的。correlation_search_space_resolution是相关性搜索的栅格分辨率设成0.01米意味着搜索空间的最小粒度是1厘米。这个值设得太粗回环检测的精度会受影响设得太细计算开销增加。SLAM Toolbox在这个场景里的表现非常稳CPU占用比Cartographer低不少建图质量也比较干净是三个算法里最“实用”的一个。对于真实项目我个人会优先推荐它作为默认方案。3.4 一个对比表格直观认识三个算法维度GMappingCartographerSLAM Toolbox核心原理粒子滤波图优化回环检测图优化回环检测CPU占用高较高中等地图全局一致性一般长走廊易漂移优秀回环修正明显优秀接近Cartographer配置复杂度低高中等是否支持定位复用否部分支持支持良好适合场景小场景快速建图大场景高精度建图工程落地首选4. 实操过程从launch文件到地图对比4.1 启动仿真环境与机器人模型整个实验流程的第一步是启动Gazebo仿真世界。我写了一个整合的launch文件一次性拉起仿真器、机器人模型和状态发布节点。机器人模型用URDF描述关键部分是雷达和底盘的连接关系以及传感器插件。雷达的Gazebo插件配置需要注意坐标系雷达的frame_id必须和后续SLAM算法期望的雷达坐标系一致否则TF树会对不上。gazebo referencelaser_link sensor typegpu_ray namelaser_sensor pose0 0 0.1 0 0 0/pose update_rate10/update_rate ray scan horizontal samples720/samples resolution1/resolution min_angle-3.14159/min_angle max_angle3.14159/max_angle /horizontal /scan range min0.1/min max30.0/max resolution0.01/resolution /range noise typegaussian/type mean0.0/mean stddev0.01/stddev /noise /ray plugin namelaser_controller filenamelibgazebo_ros_ray_sensor.so ros remapping~/out:scan/remapping /ros output_typesensor_msgs/msg/LaserScan/output_type frame_namelaser_link/frame_name /plugin /sensor /gazebo我特意用了gpu_ray类型而不是ray类型。GPU光线模拟用显卡并行计算每条射线的碰撞检测速度快很多。如果你的机器没有可用的GPU或驱动配置有问题仿真帧率会直线下降这时候退回ray类型用CPU跑虽然慢但稳定。4.2 跑通GMapping并查看地图启动GMapping的命令很简单ros2 launch slam_gmapping slam_gmapping.launch.py use_sim_time:trueuse_sim_time:true这个参数是仿真实验的命门。它告诉所有ROS2节点使用/clock话题上的仿真时间而不是系统时钟。如果漏了这一步SLAM算法拿到的雷达时间戳和TF变换的时间戳会对不上系统直接报Lookup would require extrapolation错误。跑起来后用RViz2可视化。添加Map显示话题选择/map。我会同时添加TF显示和LaserScan显示这样建图过程中能看到雷达的实际扫描是否和地图匹配。GMapping建图的过程非常直观地图从机器人周围开始随着移动逐渐向外扩展。如果机器人走得太快会发现地图上出现明显的拖影或重影这是因为粒子滤波器还没来得及收敛新的扫描就被暴力匹配到了错误的位置。控制好移动速度让雷达在每一帧之间不要产生太大的位姿跳变。4.3 跑通Cartographer并保存地图Cartographer的启动相对复杂一些因为需要加载lua配置文件ros2 launch cartographer_ros cartographer.launch.py \ use_sim_time:true \ configuration_directory:/path/to/config \ configuration_basename:my_robot_2d.lua启动后Cartographer会实时构建地图并发布到/map话题。值得注意的一点Cartographer在运行过程中发布的地图是子图的拼接结果并不完全等于最终优化后的地图。真正的高质量地图是在回环优化完成后通常会在轨迹结束时触发一次全局优化才生成的。如果想确保退出前完成一次全局优化可以在建图完成后发送一个/finish_trajectory服务请求。否则直接CtrlC进程最后一部分的地图可能没有经过全局优化边缘会有一点畸变。保存地图用ros2 run nav2_map_server map_saver_cli -f cartographer_map这会生成cartographer_map.pgm栅格图像和cartographer_map.yaml元数据文件。其中yaml文件里的resolution字段是每像素代表的米数默认0.05米也就是5厘米每像素记得保留这个元数据后续评估地图精度时要用到。4.4 跑通SLAM Toolbox并验证定位复用SLAM Toolbox启动ros2 launch slam_toolbox online_async_launch.py \ use_sim_time:true \ slam_params_file:/path/to/mapper_params_online_async.yamlSLAM Toolbox的异步模式比同步模式更适合和仿真环境配合。异步模式下回环优化在独立线程中进行不会阻塞当前帧的处理这样即使优化耗时长一些建图主循环也只是延迟不会完全停摆。同步模式online_sync更适合计算资源充足、需要确定性行为的场景。建图完成后保存地图同样用map_saver_cli。要验证定位复用能力重新启动SLAM Toolbox时使用“定位模式”加载之前保存的地图让机器人在相同环境下移动观察定位的准确性。测试下来地图复用时的定位精度能保持在5厘米以内这对实际应用非常有用。4.5 地图质量量化评估脚本纯肉眼看建图效果是远远不够的对比实验需要可量化的指标。我写了一个Python脚本主要做三件事将建出的栅格地图和仿真世界的真实栅格地图做像素级对比。计算正确率地图中的障碍物和真实障碍物重合的比例。计算地图的不确定性区域比例比如阴影区域、未覆盖区域。评估原理是这样的Gazebo里的仿真世界是已知的可以直接用ros2 run nav2_map_server map_saver_cli在没有任何SLAM算法运行的情况下把“真值地图”导出来。之后SLAM算法输出的地图和真值地图做图像匹配因为两张图的坐标系原点不一定重合需要先用图像配准算法对齐再逐像素比较。对比时需要注意一个细节map_saver_cli保存的地图尺寸可能很大因为真值地图的范围是整个仿真世界SLAM算法建的地图只是机器人走过的部分。评估脚本里要做裁剪把真值地图裁到和SLAM地图相同的范围再用膨胀像素匹配来容忍1-2像素的边缘对齐误差。5. 踩坑实录与排查思路5.1 TF树断裂三个算法全部依赖TF树一旦TF断链所有算法直接罢工。最典型的表现是运行SLAM节点后终端刷出Could not transform from laser_link to map之类的错误。排查思路不复杂先跑ros2 run tf2_ros tf2_echo map odom看输出的四元数是否在不断变化。如果提示cannot find就是TF树里缺少某个转换。用ros2 run tf2_tools view_frames生成TF树PDF一眼就能看出断在哪里。我实验中最常犯的错误是URDF里定义了base_link到laser_link的关系但robot_state_publisher节点没启动导致laser_link的TF始终发布不出来。这个问题在launch文件里多写一行node声明就能解决最坑的是启动顺序混乱时缺一个节点但系统不报错只是静默地不发布TF。5.2 地图漂移与重影地图出现重影的原因基本可以锁定为回环检测没生效或激光匹配错误。GMapping最容易出现这类问题尤其是绕圈走回起点附近时如果粒子没有正确收敛新扫描会被匹配到错误的位置地图上就会挤出重影区域。解决路径把particles从30逐步往上涨从60到100观察重影有没有改善。把linearUpdate调小到0.1米让算法更频繁地做扫描匹配。检查雷达扫描频率和移动速度是否匹配。如果移动速度过快导致相邻两帧雷达扫描的重叠区域太小匹配算法没有足够的共同特征必然失败。在仿真环境里还有一个可能因素仿真物理速率太慢导致时间戳跳变。这个时候看/clock话题的频率如果不是10Hz左右的稳定值说明Gazebo的实时因子没有达到1.0需要降低场景复杂度或升级硬件。5.3 启动仿真器瞬间崩溃或黑屏Gazebo启动黑屏或卡死绝大多数情况是图形界面的话题。仿真服务本身可能已经起来了只是渲染窗口出问题。排查命令gz topic -l如果话题列表正常说明仿真核心没问题可以尝试绕过GUI启动ros2 launch gazebo_ros gzserver.launch.py world:/path/to/world.world这样不启动gzclient纯头less模式跑仿真对于一些远程服务器场景或者没有显示器的嵌入式平台反而是更稳定高效的选择。SLAM建图完全不需要看Gazebo的3D画面只需要RViz2里的地图展示就够了。5.4 让实验结果可复现的小技巧做对比实验最重要的一点是“轨迹必须一致”。如果GMapping跑的时候走了一条路径Cartographer跑的是另一条路径那对比就毫无意义。我用了两种方式保证一致性写了一个简单的Python脚本直接向/cmd_vel话题周期性发布固定的速度指令。通过设定一系列线速度和角速度组成一个固定轨迹比如先直行、再右转、再直行……这样每条轨迹都是预设的各算法跑的就是完全相同的路径。用Gazebo的pub_clock和暂停恢复机制保证每个算法都在相同的仿真时刻开始和结束。用固定脚本控制运动的方式还能顺便评估SLAM的定位误差。因为真值轨迹可以从Gazebo的/ground_truth话题获取把SLAM输出的轨迹和真值轨迹做对比就能算出绝对轨迹误差ATE。这是SLAM领域更通用的评估指标。6. 写在最后的一点心得从结果看三个算法在仿真中的表现各有优劣。GMapping胜在简单直接几行launch文件就能跑起来适合快速验证和教学演示但长走廊中的累计漂移确实明显。Cartographer是精度之王回环修正能力名不虚传代价是配置复杂度和CPU消耗都高出一大截。SLAM Toolbox是工程落地上的最优解建图质量接近Cartographer资源占用更温和还支持地图复用和在线编辑。我个人在实际实验中最受益的一点是参数调优必须围绕自己手里的传感器和运动平台来定不要直接抄默认配置。同样的雷达扫描频率、同样的运动速度在仿真里表现最佳的那组参数换到实体机器人上可能要重新调。因为仿真的噪声模型永远是理想化的真实环境中的动态干扰、光线变化、雷达镜面反射这些因素仿真里根本没有。还有个小建议如果你准备在这个项目基础上扩展可以试着把点云数据接入视觉SLAM算法比如ORB-SLAM3然后把激光SLAM和视觉SLAM的结果做融合看看在同样的仿真场景下多传感器融合能带来多少精度提升。这个方向我目前还在试等有了成体系的结论再分享出来。本文还有配套的精品资源点击获取