当前位置: 首页 > news >正文

ROS快速入门教程06

20.SLAM基本介绍

SLAM(Simultaneous Localization and Mapping,即“同步定位与建图”)是移动机器人和增强现实等领域的核心技术。其主要目标是在未知环境中,机器人(或传感器平台)一边移动一边:

  1. 定位(Localization):估计自身在环境中的位置和姿态;
  2. 建图(Mapping):构建周围环境的地图模型。

两者相辅相成:准确的定位依赖于对环境地图的认识,而地图的生成又需要知道机器人的位置,因此需要同时进行。


20.1 SLAM 的基本流程

  1. 数据采集
    • 传感器:激光雷达(LiDAR)、深度相机、普通摄像头、IMU(惯性测量单元)、超声波等。
  2. 特征提取与匹配
    • 从传感器数据中提取“特征”(比如激光扫描的角点、图像中的关键点),并在连续帧或前后观测中进行匹配。
  3. 状态估计
    • 使用滤波(如EKF、UKF)、粒子滤波(FastSLAM)、图优化(GraphSLAM)等方法,对机器人的位姿和地图特征一起进行联合估计。
  4. 地图更新
    • 将新观测整合进地图,常见地图表现形式有栅格地图(Occupancy Grid)、点云地图、拓扑地图等。
  5. 回环检测(Loop Closure)
    • 当机器人回到之前走过的地方,识别出“回环”并进行全局优化,修正累积漂移。

20.2 主要算法流派

流派代表方法特点
滤波式 SLAMEKF-SLAM、UKF-SLAM实时性好,算法框架简单;状态量随着特征增多线性增长,规模化受限。
粒子滤波 SLAMFastSLAM 家族用粒子表示机器人轨迹,地图可分布式维护;适合高维地图,但粒子数需调优。
图优化 SLAMGraphSLAM、g2o、Ceres将轨迹与特征构建成图,收敛至全局最优;后端优化耗时较大,需做好稀疏化。
视觉 SLAMPTAM、ORB-SLAM、LSD-SLAM只用相机即可建图,成本低;对光照与纹理依赖强,对大动态场景鲁棒性较差。
激光 SLAMGMapping、Hector SLAM、Cartographer激光数据精度高,对照明不敏感;成本和电量需求较高。

20.3 在 ROS 中的典型实现

  • gmapping:基于粒子滤波的 2D 栅格地图构建,入门常用。
  • hector_slam:无需里程计,依赖高频激光;对快速运动场景适应性好。
  • cartographer(Google):图优化结合扫描匹配,支持 2D/3D,精度与效率兼备。
  • ORB_SLAM2/3:常见视觉 SLAM 包,支持单目/双目/RGB-D,提供回环检测与全局优化。

使用时通常需要配置对应节点(如 slam_gmappingcartographer_nodeorb_slam2),并将激光或相机话题、里程计话题正确 remap,调节参数(如分辨率、窗口大小、回环检测频率等)以获得稳定的建图效果。


20.4 应用场景

  • 自主导航:机器人扫地机、配送机器人在室内环境中自主行走。
  • 自动驾驶:结合 GPS 外,还可用 LiDAR SLAM 实时感知周围。
  • 增强/虚拟现实:在室内外构建稠密点云,实现虚拟物体与现实世界的精确叠加。
  • 测绘与考古:无人机搭载激光雷达进行地形建模。

21.ROS中实现SLAM建图

实现思路:机器人通过激光雷达驱动节点发布一个雷达数据话题/scan,而SLAM节点订阅该话题就能获取测距数值。SLAM节点发布地图/map话题,生成地图消息。再使用Rviz界面显示地图的形状。

21.1 hector_mapping

sudo apt install ros-noetic-hector-mapping
roslaunch wpr_simulation wpb_stage_slam.launch  
rosrun hector_mapping hector_mapping #newone
rviz #newone
rosrun rqt_robot_steering  rqt_robot_steering #可以通过该软件包控制移动

21.2 通过launch文件启动Hector_Mapping的建图功能

cd catkin_ws/src/
catkin_create_pkg slam_pkg roscpp rospy std_mgs
mkdir launch
cd launch
vim hector.launch
<launch><!-- 载入 机器人 和 SLAM 的仿真场景 --><include file="$(find wpr_simulation)/launch/wpb_stage_slam.launch"/><!-- Hector SLAM --><node pkg="hector_mapping" type="hector_mapping" name="hector_mapping"><param name="tf_map_scanmatch_transform_frame_name" value="base_footprint" /></node><!-- Rviz 显示 --><node pkg="rviz" type="rviz" name="rviz" args="-d $(find wpr_simulation)/rviz/slam.rviz"/><!-- 运动控制 --><node pkg="rqt_robot_steering" type="rqt_robot_steering" name="rqt_robot_steering"/></launch>
catkin_make
roslaunch slam_pkg hector.launch

21.3 Hector_Mapping建图的参数设置

学习hector_mapping的更多参数,可以打开wiki网站进行搜索都有哪些参数。
这里重新编写hector.launch文件学习参数

<launch><!-- 第一个 Hector_Mapping 建图节点 --><group ns="slam_1"><node pkg="hector_mapping" type="hector_mapping" name="hector_mapping_1"><param name="map_update_distance_thresh" value="0.4"/><param name="map_update_angle_thresh" value="0.9" /><param name="map_pub_period" value="0.2" /><param name="map_frame" value="slam_1/map" /><param name="base_frame" value="slam_1/base_footprint" /><param name="odom_frame" value="slam_1/odom" /></node></group><!-- 第二个 Hector_Mapping 建图节点 --><group ns="slam_2"><node pkg="hector_mapping" type="hector_mapping" name="hector_mapping_2"><param name="map_update_distance_thresh" value="0.1"/><param name="map_update_angle_thresh" value="0.1" /><param name="map_pub_period" value="0.2" /><param name="map_frame" value="slam_2/map" /><param name="base_frame" value="slam_2/base_footprint" /><param name="odom_frame" value="slam_2/odom" /></node></group><!-- **************************** 分割线 **************************** --><!-- 载入 SLAM 的仿真场景 --><include file="$(find gazebo_ros)/launch/empty_world.launch"><arg name="world_name" value="$(find wpr_simulation)/worlds/slam_simple.world"/><arg name="paused" value="false"/><arg name="use_sim_time" value="true"/><arg name="gui" value="true"/><arg name="recording" value="false"/><arg name="debug" value="false"/></include><!-- 载入 1号机器人 --><include file="$(find wpr_simulation)/launch/wpb_slam_template.launch"><arg name="robot_namespace" value="slam_1" /> <arg name="local_x" value="0" /> <arg name="local_y" value="-0.3" /> <arg name="local_yaw" value="0" /> </include><!-- 载入 2号机器人 --><include file="$(find wpr_simulation)/launch/wpb_slam_template.launch"><arg name="robot_namespace" value="slam_2" /> <arg name="local_x" value="0" /> <arg name="local_y" value="0.3" /> <arg name="local_yaw" value="0" /> </include><!-- 运动控制 --><node pkg="rqt_robot_steering" type="rqt_robot_steering" name="rqt_robot_steering"/><!-- 速度话题分流 --><node pkg = "topic_tools" type = "relay" name = "relay_1" args="/cmd_vel /slam_1/cmd_vel" /><node pkg = "topic_tools" type = "relay" name = "relay_2" args="/cmd_vel /slam_2/cmd_vel" /></launch>

22. 初识ROS的TF系统

机器人移动建图原理:机器人一边移动一边建图。为了方便描述机器人和这个地图坐标系远点的空间关系,我们分别定义两个坐标系,首先是地图坐标系,原点在机器人建图的初始位置,坐标轴方向遵循ROS的右手法则,命名为map。机器人坐标系在机器人底盘中心,坐标轴方向遵循ROS的右手法则,命名为base_footprintbase_footprint为父坐标系,map为子坐标系。那么描述机器人的空间位置,则可以说父坐标系相对于子坐标系的空间偏移量xyz
在这里插入图片描述
在这里插入图片描述

tf2_msgs消息格式结构

在这里插入图片描述

22.1 里程计的介绍

里程计(Odometry)指的是机器人利用自身运动传感器(如轮速编码器、IMU、视觉相机等)对自身位姿(位置和朝向)增量变化进行估计的过程。它常作为 SLAM 中运动预测(Motion Model)的输入,帮助滤波或图优化方法预测下一时刻的位置,然后与观测(传感器测量)一同进行融合校正。


1. 里程计的来源

  1. 轮式里程计(Wheel Odometry)
    • 利用轮子上的编码器(Encoder)测量转动圈数,再根据轮子半径与轴距计算出线速度和角速度。
    • 优点:实现简单、计算量小;
    • 缺点:易受轮胎打滑、地面不平整影响,累计误差(漂移)随时间线性增长。
  2. 惯性里程计(Inertial Odometry)
    • 利用 IMU(加速度计+陀螺仪)对加速度和角速度进行积分得到位移与姿态变化。
    • 优点:高频率更新,对快速运动响应好;
    • 缺点:噪声和偏置导致二次积分误差爆炸式增长。
  3. 视觉里程计(Visual Odometry, VO)
    • 通过对连续图像帧(单目、双目或 RGB-D)中提取特征点并匹配,估计相机的运动变换。
    • 优点:拒绝轮滑、对外部环境敏感度高;
    • 缺点:对光照和纹理依赖大,计算量相对较高。
  4. 激光里程计(LiDAR Odometry)
    • 基于激光扫描点云的配准算法(如 ICP、NDT)来估计帧间变换。
    • 优点:精度高、不受光照影响;
    • 缺点:对场景几何特征要求较高,实时性和计算资源要求大。

2. 里程计在 SLAM 中的作用

  • 预测运动
    SLAM 算法通常分为预测(Prediction)和校正(Correction)两步。里程计提供的位姿增量用于预测机器人下一时刻的位姿先验。
  • 构建运动模型
    在滤波式 SLAM(如 EKF-SLAM、FastSLAM)中,里程计噪声模型决定了状态协方差的增长;在图优化 SLAM(如 g2o、Ceres)中,则是构建运动边(odometry edge)的残差项。
  • 回环检测辅助
    虽然回环检测更多依赖观测(特征或扫描匹配),但精准的里程计能缩小搜索范围,提高回环匹配速度与正确率。

3. 局限与改进

  1. 漂移累积
    所有纯里程计方法都会随时间累积漂移,短时间内可以较准,长时间运行误差会越来越大。
  2. 多传感器融合
    • 将轮式/惯性/视觉/激光里程计与环境观测(SLAM 的 Mapping 部分)融合,可显著抑制漂移。
    • 常见做法有扩展卡尔曼滤波融合(EKF Fusion)、滑动窗口优化(Windowed BA)或因子图优化(Factor Graph)。
  3. 里程计校准
    • 定期标定编码器、IMU 的偏置,并在线估计传感器健康状态;
    • 视觉里程计中进行相机内外参标定。
  4. 去耦与冗余
    • 多种里程计相互校验,比如将视觉里程计与轮式里程计融合,检测轮滑或视觉失效;
    • 在关键时刻启用备用传感器,保证系统鲁棒性。

23. 使用Gmapping进行SLAM建图

gMapping 是 ROS 生态中最常用的 2D 激光 SLAM(同步定位与建图)开源实现之一,基于 Rao–Blackwellized 粒子滤波(RBPF)算法,能够在未知环境中实时构建栅格地图。

23.1算法原理

  1. Rao–Blackwellized 粒子滤波
    gMapping 将机器人的轨迹作为粒子滤波器的随机变量,用一组粒子 (x_{1:t}k)k=1M_{k=1}M 来表示可能的历史轨迹。
    对每个粒子,都维护一份局部地图(占据栅格),并通过激光观测更新该地图的概率。
  2. 粒子权重计算
    • 根据运动模型(里程计增量)对每个粒子进行预测;
    • 用当前激光扫描对每个粒子的地图进行似然评估,计算权重;
    • 根据权重进行重采样,保留最有可能的轨迹和地图。
  3. 地图合并
    最终输出由权重最高的粒子所维护的地图,或对多粒子地图进行加权融合以提高鲁棒性。

23.2 主要特点

  • 实时性:在普通笔记本/嵌入式平台上即可运行,适合室内移动机器人。
  • 低成本传感器:仅需 2D 激光雷达和轮式里程计(或里程计+IMU)。
  • 易于集成:作为 ROS 包 slam_gmapping,与 roslaunchtfrviz 等工具无缝对接。
  • 可调参数丰富:分辨率、粒子数、重采样阈值等,可根据场景和算力灵活调节。

23.3 快速上手

  1. 安装

    sudo apt-get install ros-<distro>-slam-gmapping
    
  2. 运行示例
    在已有激光和里程计话题的机器人系统中,可以启动:

    roslaunch slam_gmapping slam_gmapping.launch \scan:=/base_scan \odom:=/odom \map_update_interval:=5.0
    
    • scan:激光雷达的话题名
    • odom:里程计话题
    • map_update_interval:地图更新周期(秒)
  3. 可视化

    rosrun rviz rviz
    

    在 RViz 中添加 “Map” 及 “LaserScan” 显示,实时查看建图效果。


23.4 关键参数调优

参数含义建议范围
particles粒子数量30 – 200
xmin/ymin/xmax/ymax地图边界(m)根据环境大小设定
delta栅格分辨率(m)0.02 – 0.1
sigma激光测量噪声标准差0.01 – 0.1
kernelSize占据概率核大小1 – 3
resampleThreshold重采样阈值(有效粒子比例)0.5 – 0.8
lsigma/ogain激光局部平滑与增益,用于改善小环境的匹配默认或微调
  • 增加 particles 可提高鲁棒性,但占用更多 CPU。
  • 缩小 delta 可提升地图精度,但会放大噪声并增加计算量。
  • resampleThreshold 决定何时触发重采样,过低会导致样本贫化,过高会过早重采样。

23.5 优缺点

  • 优点
    • 算法成熟、社区活跃;
    • 对里程计噪声和部分动态障碍有一定容忍;
    • 可与 ROS 中其他包(如 AMCL、move_base)配合做导航。
  • 缺点
    • 粒子滤波的粒子数随环境复杂度需求增加,CPU 占用较高;
    • 对大尺度或户外场景支持有限,仅适合平面、结构化环境;
    • 没有回环检测模块,对长期建图漂移校正能力弱。

在这里插入图片描述
运行建图仿真环境

roslaunch wpr_simulation wpb_stage_robocup.launch
rostopic list #查看话题
rostopic echo /scan --noarr
rosrun rqt_tf_tree rqt_tf_tree
rosrun gmapping slam_gmapping
rosrun rviz rviz
rosrun wpr_simulation keyboard_vel_ctrl

24.使用Gmapping进行SLAM建图

cd catkin_ws/src/
catkin_create_pkg slam_pkg roscpp rospy std_msgs
mkdir launch
vim launch/gmapping.launch
<launch><!-- 载入 机器人 和 RoboCup@Home 的仿真场景 --><include file="$(find wpr_simulation)/launch/wpb_stage_robocup.launch"/><!-- Gmapping --><node pkg="gmapping" type="slam_gmapping" name="slam_gmapping"/><!-- Rviz --><arg name="rvizconfig" default="$(find wpr_simulation)/rviz/slam.rviz" /><node name="rviz" pkg="rviz" type="rviz" args="-d $(arg rvizconfig)" required="true" /><!-- 手柄控制 --><node respawn="true" pkg="joy" type="joy_node" name="joy_node" ><param name="dev" type="string" value="/dev/input/js0" /><param name="deadzone" value="0.12" /></node><param name="axis_linear" value="1" type="int"/><param name="axis_angular" value="0" type="int"/><param name="scale_linear" value="0.5" type="double"/><param name="scale_angular" value="1" type="double"/><node pkg="wpr_simulation" type="teleop_js_node" name="teleop_js_node"/></launch>

在这里插入图片描述
在这里插入图片描述

相关文章:

  • 什么是源网荷储一体化
  • Unity背景随着文字变化而变化
  • 【Python】‌Python单元测试框架unittest总结
  • Nacos源码—Nacos配置中心实现分析
  • 计算机的基本组成
  • Sigmoid函数范围
  • P2572 [SCOI2010] 序列操作 Solution
  • RAG vs 传统生成模型:核心差异与适用场景
  • NextDenovo2.5.2安装与使用-生信工具53
  • upload-labs靶场通关详解:第三关
  • 力扣刷题(第二十一天)
  • 设置GO程序在离线情况下读取本地缓存的模块
  • 红黑树算法笔记(一)
  • 【C/C++】C++中noexcept的妙用与性能提升
  • 学习笔记:黑马程序员JavaWeb开发教程(2025.4.1)
  • SaaS数据备份器-电商企业数据采集与整合的高效助手
  • Linux——多线程
  • 电厂数据库未来趋势:时序数据库 + AI 驱动的自优化系统
  • 用 Rust 搭建一个优雅的多线程服务器:从零开始的详细指南
  • Linux 一键部署chrony时间服务器
  • 巴基斯坦对印度发起网络攻击,致其约70%电网瘫痪
  • 构建菌株有效降解有机污染物,上海交大科研成果登上《自然》
  • 远离军事前线的另一面暗斗:除了“断水”,印度还试图牵制对巴国际援助
  • A股三大股指低收:银行股再度走强,两市成交11920亿元
  • 2025柯桥时尚周启幕:国际纺都越来越时尚
  • 【社论】以法治力量促进民企长远健康发展