考点 1:SLAM 基本概念与目标
1. 核心定义
SLAM 全称是 Simultaneous Localization and Mapping ,翻译为 同时定位与建图。
- 定位 :机器人知道自己在环境中的 位置和姿态(位姿),比如 "我在教室第 3 排桌子左边,面朝黑板"。
- 建图 :机器人根据传感器数据,画出周围环境的 地图,比如教室的桌子、墙壁的位置。
- 同时:定位和建图不是分开做的 ------ 机器人一边用传感器 "看" 环境画地图,一边根据画好的部分地图判断自己的位置。
2. 最终输出
- 一张 环境地图(比如栅格地图、点云地图)。
- 机器人在地图上的 位姿轨迹(比如从起点到终点,每一刻的位置和朝向)。
3. 与 "纯定位" 的区别
| 对比项 | SLAM | 纯定位(Localization) |
|---|---|---|
| 地图前提 | 地图未知,需要实时生成 | 地图已知(比如提前画好的教室地图) |
| 核心任务 | 定位 + 建图 | 只需要定位(根据已知地图找自己位置) |
| 应用场景 | 机器人第一次进入陌生环境(比如搜救机器人进废墟) | 机器人在熟悉环境中移动(比如扫地机器人在你家) |
生活化例子:
- SLAM 像你第一次去商场,一边记店铺位置(建图),一边看路标找自己在哪(定位)。
- 纯定位像你在自己家,闭着眼睛都能走到卧室(地图已知,只需要确定自己位置)。
考点 2:SLAM 经典架构(前端 / 后端)
SLAM 系统可以分成 前端 和 后端 两部分,分工明确,像工厂的 "生产线" 和 "质检部"。
1. 前端(传感器数据处理层)
核心作用 :处理原始传感器数据,提取有用信息,生成 短期相对位姿约束。简单说,前端负责 "看眼前的环境,算自己走了多远"。主要工作内容:
- 里程计融合:把轮子的里程计(比如轮子转了多少圈,算走了几米)和传感器数据结合,减少单独使用轮子的误差。
- 特征提取 / 匹配 :从激光数据中找环境的 特征点(比如墙角、桌子角),并匹配相邻时刻的特征点 ------ 比如 "上一秒看到的墙角,这一秒还能看到,说明我没走太远"。
- Scan Matching(扫描匹配):把相邻两次的激光扫描数据对齐,计算机器人的相对位姿(后面考点 4 会详细讲)。
- 数据关联:判断 "当前看到的特征点,是不是之前看到过的同一个"------ 比如避免把两个长得像的墙角当成同一个。
2. 后端(优化层)
核心作用 :处理前端生成的约束,解决 累计误差 ,保证地图和轨迹的 全局一致性。简单说,后端负责 "纠偏"------ 前端算的短期轨迹可能有误差,走得越远误差越大,后端把这些误差 "抹平"。主要工作内容:
- 图优化 / 因子图:把机器人的位姿当成 "节点",把前端的约束当成 "边",构建一个图模型,通过数学优化让所有节点的位置最合理(后面考点 6 详细讲)。
- 回环检测:识别机器人 "是不是回到了之前来过的地方"------ 比如绕了一圈回到起点,后端就会把起点和终点的位姿对齐,消除全程的累计误差。
- 全局一致性:优化后,地图不会出现 "墙壁断裂""轨迹交叉" 的情况,整体是连贯的。
生活化例子:
- 前端像你走路时,盯着脚下的路,算自己走了几步、转了多少弯。
- 后端像你走了一圈后,发现 "我回到了起点,但按步数算应该走了 100 米",于是修正步数的误差,让轨迹和实际路线一致。
考点 3:2D LiDAR SLAM 输入输出与数据流(ROS 2)
这部分是 工程重点,对应 ROS 2 实验中的话题和 TF 变换,考试大概率考 "TF 链" 和 "关键话题"。
1. 关键输入输出(ROS 2 话题 / 帧)
ROS 2 中,数据是通过 话题(Topic) 传输的,SLAM 相关的核心话题:
| 话题名 | 含义 | 数据类型 | 作用 |
|---|---|---|---|
/scan |
激光扫描数据 | sensor_msgs/LaserScan |
SLAM 的核心输入,包含激光的角度、距离信息(比如 "正前方 3 米有障碍物") |
/odom |
里程计数据 | nav_msgs/Odometry |
提供机器人的初始位姿估计(比如轮子里程计算的位置) |
/tf |
坐标变换数据 | tf2_msgs/TFMessage |
传输不同坐标系之间的位置关系(比如激光雷达相对于机器人底盘的位置) |
/tf_static |
静态坐标变换 | tf2_msgs/TFMessage |
传输固定不变的坐标关系(比如激光雷达装在机器人上,位置不会变) |
/map |
生成的地图 | nav_msgs/OccupancyGrid |
SLAM 的核心输出,即栅格地图(后面考点 7 详细讲) |
2. 关键 TF 链(坐标变换关系)
机器人和环境的位置,需要用 坐标系 来描述,SLAM 中必须记住的 TF 链:
plaintext
map -> odom -> base_link -> laser
每个坐标系的含义:
| 坐标系 | 含义 | 通俗解释 |
|---|---|---|
map |
世界坐标系 / 地图坐标系 | 地图的 "绝对坐标",原点是地图的左下角(固定不动) |
odom |
里程计坐标系 | 里程计的 "相对坐标",原点是机器人的起点(里程计会漂移) |
base_link |
机器人底盘坐标系 | 机器人的 "身体坐标",原点是底盘中心(跟着机器人动) |
laser |
激光雷达坐标系 | 激光雷达的 "眼睛坐标",原点是雷达的中心(固定在底盘上) |
3. 核心数据流逻辑
- 激光雷达发布
/scan话题,里程计发布/odom话题。 - SLAM 节点(比如
slam_toolbox)接收/scan和/odom,结合 TF 链(知道雷达在机器人上的位置),计算位姿和地图。 - SLAM 节点发布
/map地图,同时发布map -> odom的 TF 变换 ------ 这个变换是定位校正,用来修正里程计的漂移(比如里程计说走了 10 米,实际地图上只走了 9.5 米,就用这个变换调整)。
考点 4:Scan Matching(扫描匹配)
1. 核心目的
把机器人 相邻两次的激光扫描数据(scan) 对齐,计算两次扫描之间机器人的 相对位姿(走了多远,转了多少角度)。
2. 为什么需要它?------ 与里程计互补
机器人的 轮子里程计 有个致命缺点:漂移。
- 比如轮子打滑、地面不平,里程计算的 "走了 1 米",实际可能只走了 0.9 米;走得越远,误差累计越大(短期平滑,长期不准)。
- Scan Matching 是用 环境特征 来计算位姿 ------ 比如相邻两次扫描都看到同一个墙角,通过对齐墙角的位置,就能准确算出走了多远,相当于给里程计 "纠错"。
3. 常见算法思想
- ICP(迭代最近点算法) :最经典的扫描匹配算法。核心思路:
- 从两次扫描数据中找 "最近的点对"(比如第一次扫描的点 A,第二次扫描中离 A 最近的点 B)。
- 计算一个位姿变换,让所有点对的距离总和最小。
- 迭代重复上面两步,直到变换稳定。
- Correlative Scan Matching(相关性扫描匹配) :暴力搜索法。核心思路:
- 假设机器人在一个小范围内(比如 ±0.5 米,±10°)移动。
- 把第一次扫描的点,按不同的位姿变换 "贴" 到第二次扫描上,计算重叠度。
- 选重叠度最高的变换作为结果。
- CSM(Canonical Scan Matcher):工程上常用的优化算法,结合了 ICP 和相关性匹配的优点,速度快、精度高。
考点 5:回环(Loop Closure)与漂移校正
1. 回环的定义
机器人 绕了一圈后,回到之前访问过的位置,这个过程叫 "回环"。比如从教室门口出发,绕教室走一圈又回到门口。
2. 回环触发条件
SLAM 系统通过 特征匹配 识别回环 ------ 比如 "当前看到的墙角 + 桌子的组合,和 10 分钟前门口的特征组合一模一样",系统就判定 "触发回环"。
3. 核心作用:消除累计漂移
这是 SLAM 后端的核心功能!
- 没有回环时,机器人走得越远,前端的误差累计越大,最后地图会 "扭曲"------ 比如教室的墙壁画成了 "波浪线",轨迹也变成了 "螺旋线"。
- 触发回环后,后端会强制让 "当前位姿" 和 "之前的位姿" 对齐 ------ 比如 "现在的门口位姿,必须和 10 分钟前的门口位姿一样",这样就能把全程的累计误差一次性 "拉平",让地图和轨迹恢复全局一致。
生活化例子:你走路时没看路,凭感觉走,走了 1000 步后发现回到了起点,但按步数算应该走了 500 米 ------ 回环就相当于 "发现自己回到起点",然后修正步数的误差,让路线变成一个闭合的圆。
考点 6:图优化(Pose Graph / Factor Graph)直观理解
图优化是 SLAM 后端的 数学核心,考试考 "节点和边的定义""优化目标",不用背公式,理解概念就行。
1. 图的组成:节点 + 边
- 节点(Node) :代表机器人的 位姿(每个时刻的位置和朝向),一个节点对应一个时刻的机器人状态。
- 边(Edge) :代表两个节点之间的 约束关系 ,约束来自 3 个地方:
- 里程计约束:相邻两个时刻,轮子里程计算的相对位姿。
- Scan Matching 约束:相邻两个时刻,扫描匹配算的相对位姿。
- 回环约束:回环触发时,当前时刻和历史时刻的位姿约束(最强的约束)。
2. 优化目标
让 所有边的 "残差" 总和最小。
- 残差:可以理解为 "约束的预期值" 和 "实际值" 的差距。比如里程计约束说 "节点 A 到节点 B 应该走了 1 米",但实际图中节点 A 和 B 的距离是 1.2 米,残差就是 0.2 米。
- 优化过程:调整所有节点的位姿,让所有残差加起来最小 ------ 这样所有约束都能满足,地图和轨迹就全局一致了。
生活化例子:把每个节点当成一个同学,每条边当成同学之间的 "约定"(比如 "我和小明隔 1 米坐")。图优化就是调整所有同学的座位,让所有人的约定都尽可能满足。
考点 7:栅格地图(Occupancy Grid)与参数
2D LiDAR SLAM 最常用的地图是 栅格地图,考试考 "栅格地图的定义" 和 "关键参数"。
1. 栅格地图的本质
把环境分成很多 小方格(栅格),每个方格用一个值表示 "是否被占据":
- 0:空闲(比如空地,可以走)。
- 100:被占据(比如墙壁、桌子,不能走)。
- -1:未知(比如机器人没去过的地方)。
2. 关键参数
- 分辨率:每个栅格的边长,比如 0.05m(5 厘米)。分辨率越高,地图越精细,但计算量越大;分辨率越低,地图越粗糙,但速度快。
- 更新模型 :机器人每收到一次激光数据,怎么更新栅格的 "占据值"。常用 贝叶斯更新------ 比如第一次看到某个栅格有障碍物,就增加它的占据概率;后面没看到,就降低概率。
- 膨胀 / 清理 :
- 膨胀:把障碍物的栅格 "扩大一圈",比如墙壁的栅格周围加一圈 "禁止通行" 的栅格 ------ 防止机器人撞到墙壁(因为机器人有体积)。
- 清理:机器人移动后,把 "之前认为是障碍物,现在发现是空闲" 的栅格更新为空闲(比如移开的箱子)。
- 地图范围与滚动 / 固定地图 :
- 固定地图:地图大小固定,比如 10m×10m,机器人走到边界就无法更新地图。
- 滚动地图:地图大小不固定,跟着机器人移动,只保留机器人周围的区域 ------ 适合大范围环境(比如商场、公园)。
考点 8:SLAM 与 Nav2 集成
Nav2 是 ROS 2 中的 导航框架,SLAM 是导航的 "前期准备",考试考 "建图和导航的流程区别"。
1. 建图阶段(SLAM 模式)
- 启动 slam_toolbox 或 Cartographer 节点。
- 节点接收
/scan和/odom数据,生成/map地图,并发布map -> odom的 TF 变换(校正定位)。 - 建图完成后,用命令保存地图:
ros2 run nav2_map_server map_saver_cli -f my_map(保存为my_map.yaml和my_map.pgm文件)。
2. 导航阶段(定位 + 路径规划模式)
建图完成后,关闭 SLAM 节点,切换到导航模式:
- 启动 map_server 节点:加载刚才保存的地图(发布
/map话题)。 - 启动 AMCL 节点 :AMCL 是 "自适应蒙特卡洛定位",作用是纯定位 ------ 根据已知地图和激光数据,计算机器人的位姿(发布
map -> odom的 TF 变换)。 - 启动 Nav2 的其他节点(路径规划、运动控制):机器人就可以根据地图自主导航了。
核心流程总结
SLAM 建图 → 保存地图 → 关闭 SLAM → 加载地图 + AMCL 定位 → Nav2 导航
考点 9:时间系统(use_sim_time //clock)与 TF 外推错误
这是 ROS 2 实验中 最容易踩的坑,考试考 "时间同步的重要性" 和 "故障原因"。
1. 核心概念:ROS 2 的时间系统
ROS 2 有两种时间:
- 系统时间:计算机的本地时间(真实时间)。
- 仿真时间 :仿真器(比如 Gazebo)发布的
/clock话题的时间 ------ 用于模拟机器人运动,让实验可重复。
2. use_sim_time 参数的作用
这是一个 全局参数,所有节点都会读取:
use_sim_time: true:节点使用 仿真时间 (从/clock话题获取时间)。use_sim_time: false:节点使用 系统时间(默认值)。
3. 关键规则:所有节点必须时间同步
- 实验中,如果用 Gazebo 仿真,所有节点必须设置
use_sim_time: true------ 包括 SLAM 节点、里程计节点、雷达节点。 - 如果时间不同步(比如 SLAM 用系统时间,雷达用仿真时间),会导致 TF 外推错误(TF Extrapolation Error)------ 系统会报错 "找不到某个时刻的 TF 变换",SLAM 直接失效。
4. Bag 回放的时间问题
- 用
ros2 bag play回放传感器数据时,必须加参数-s或--use-sim-time,让所有节点使用 bag 中的时间。 - 否则会出现 "话题有数据,但 SLAM 不处理" 的情况 ------ 因为时间戳对不上。
考点 10:QoS 对 SLAM / 回放的影响
QoS 全称是 Quality of Service(服务质量),ROS 2 中用来定义话题数据的 "传输规则",考试考 "不同话题的 QoS 配置" 和 "不匹配的后果"。
1. QoS 的核心作用
不同的传感器数据,对 "可靠性" 和 "实时性" 的要求不同:
- 可靠性:数据必须送到,不能丢包(比如地图数据)。
- 实时性:数据要快,偶尔丢包没关系(比如激光扫描数据)。
2. SLAM 相关话题的 QoS 配置
| 话题名 | 常用 QoS 配置 | 原因 |
|---|---|---|
/scan |
BEST_EFFORT(尽力而为) |
激光数据频率高(比如 10Hz),偶尔丢一包不影响,优先保证实时性 |
/map |
RELIABLE(可靠) + TRANSIENT_LOCAL(临时本地) |
地图数据重要,必须送到;TRANSIENT_LOCAL 保证新节点订阅后能拿到最新的地图 |
/odom |
RELIABLE |
里程计数据是位姿估计的基础,不能丢包 |
3. QoS 不匹配的后果
话题名能看到,但收不到数据 ------ 这是实验中最常见的问题!比如 /scan 用 BEST_EFFORT 发布,但 SLAM 节点用 RELIABLE 订阅,两者 QoS 不兼容,SLAM 节点就收不到激光数据,建图失败。
考点 11:常见故障排错(SLAM 专项)
考试会给一个故障现象,让你分析原因,这里总结高频故障和排查思路:
| 故障现象 | 常见原因 | 排查方法 |
|---|---|---|
| 地图不更新 | 1. 激光话题 /scan 没数据2. TF 链断裂(比如缺少 base_link -> laser)3. 机器人没运动(里程计没数据) |
1. ros2 topic echo /scan 看有没有数据2. ros2 tf tree 看 TF 链是否完整3. ros2 topic echo /odom 看里程计数据 |
| 地图发散 / 扭曲 | 1. 里程计漂移严重(比如轮子打滑)2. Scan Matching 失败(环境特征太少,比如空旷的走廊)3. 没有回环触发 | 1. 换更好的里程计(比如视觉里程计)2. 在环境中加人工特征(比如贴二维码)3. 检查回环检测参数是否合理 |
| 回环失败 | 1. 环境特征重复(比如长走廊的相同墙壁)2. 激光分辨率太低,特征提取不到3. 回环检测阈值设置不合理 | 1. 增加环境独特特征2. 提高激光雷达分辨率3. 调整 SLAM 节点的回环阈值参数 |
| TF 断裂 | 1. 静态 TF 没发布(比如 base_link -> laser)2. 时间不同步导致 TF 外推错误3. frame_id 写错(比如激光数据的 frame_id 是 lidar,但 TF 中是 laser) |
1. ros2 run tf2_ros tf2_echo base_link laser 看是否有变换2. 检查所有节点的 use_sim_time 参数3. 检查传感器数据的 frame_id |
| 激光方向 / 外参错误 | 激光雷达的安装角度错了(比如装反了) | 用 ros2 run rviz2 rviz2 看激光点云的方向,调整静态 TF 的角度参数 |
| 运动方式不合理 | 机器人运动太快 / 旋转太急,激光数据跟不上 | 降低机器人的运动速度和角速度 |
考点 12:slam_toolbox / Cartographer 常用模式与差异
这是两款 ROS 2 中最常用的 2D LiDAR SLAM 工具,考试考 "两者的适用场景"。
1. slam_toolbox
- 特点 :2D LiDAR 友好,实用性强,配置简单,适合初学者。
- 核心模式 :
mapping_mode: online_async(异步建图):一边运动一边建图,实时性高,适合实验和小场景。mapping_mode: online_sync(同步建图):需要里程计和激光数据严格同步,适合高精度场景。
- 优势 :支持 保存地图、继续建图(比如今天建了一半,明天可以接着建),故障排查文档多。
- 适用场景:课程实验、小型室内环境(教室、实验室)。
2. Cartographer
- 特点 :2D/3D 都支持,精度高,但配置复杂(需要写 Lua 配置文件)。
- 核心机制 :采用 子图(Submap) 策略 ------ 把环境分成多个子图,每个子图独立建图,回环检测在子图之间进行。
- 优势 :适合 大范围、复杂环境(比如商场、工厂),3D 建图效果好。
- 缺点:配置门槛高,初学者容易踩坑,不支持 "继续建图"(关闭后只能重新建图)。
两者对比总结
| 特性 | slam_toolbox | Cartographer |
|---|---|---|
| 2D 友好度 | 高(推荐初学者) | 中 |
| 3D 支持 | 弱 | 强 |
| 配置难度 | 简单(YAML 文件) | 复杂(Lua 文件) |
| 继续建图 | 支持 | 不支持 |
| 适用场景 | 小型室内、课程实验 | 大范围环境、2D/3D 混合建图 |