1. SLAM概述与ROS2生态
各位同学好,我是你们这门课的主讲。咱们直接开门见山——SLAM,全称 Simultaneous Localization and Mapping,中文叫“同时定位与地图构建”。说白了,就是让一个机器人从陌生环境出发,一边走路一边给自己定位,同时把周围的地图画出来。你想想看,这像不像一个人蒙着眼走进一间黑屋子,一边摸墙一边在脑子里画地图?嗯,差不多就是这个意思。
我最早接触SLAM是在2016年做AGV项目的时候。当时小车在仓库里跑着跑着就偏了,轮子打滑,里程计完全不可信。后来我意识到,没有SLAM,机器人就像个路痴。从那以后,我就一头扎进了这个领域。今天这第一讲,我们先搭好框架,把SLAM问题和ROS2生态串起来。
1.1 SLAM问题定义
SLAM 的数学描述其实不复杂:已知控制量 u₁ₖ 和观测 z₁ₖ,求机器人位姿 xₖ 和地图 m 的联合后验概率。但实际工程里,噪声、数据关联、计算量都是拦路虎。我个人习惯把SLAM拆成“前端”和“后端”——前端处理传感器数据,做帧间匹配;后端做图优化或滤波,消除累积误差。
1.2 应用场景
SLAM 早就不是实验室玩具了。我列几个自己参与过的落地场景:
- 仓储物流:AGV 在密集货架间穿梭,靠激光SLAM实时定位,精度要求 ±5cm。
- 扫地机器人:家用产品里视觉+激光融合,成本敏感,但建图必须稳定。
- 自动驾驶:L4级园区车,多线激光雷达+IMU+轮速,城市峡谷里不能丢位置。
- AR/VR:手机端视觉SLAM,比如 HoloLens,实时跟踪六自由度位姿。
你想想看,没有SLAM,这些设备根本不知道自己在哪,更别提导航了。
1.3 ROS2 核心概念
ROS2 是机器人开发的事实标准。我为什么从ROS1迁移到ROS2?因为ROS2解决了实时性、多机通信和安全性问题。下面四个概念你必须刻在脑子里:
| 概念 | 类比 | SLAM中的角色 |
|---|---|---|
| 节点 (Node) | 一个独立的工作单元 | 激光驱动节点、里程计节点、SLAM核心节点 |
| 话题 (Topic) | 广播电台,一对多 | /scan 发布激光数据,/map 发布栅格地图 |
| 服务 (Service) | 打电话,一问一答 | 请求保存地图、重置位姿 |
| 动作 (Action) | 快递单,可反馈进度 | 导航到目标点,SLAM中很少直接用,但建图任务可封装 |
ros2 topic list 和 ros2 node info 是你的好朋友。
写一个最简单的发布节点,你就明白了:
# Python 示例 — 发布激光模拟数据
import rclpy
from rclpy.node import Node
from sensor_msgs.msg import LaserScan
class FakeLaser(Node):
def __init__(self):
super().__init__('fake_laser')
self.pub = self.create_publisher(LaserScan, '/scan', 10)
self.timer = self.create_timer(0.1, self.publish_scan)
def publish_scan(self):
msg = LaserScan()
msg.header.frame_id = 'laser_frame'
msg.angle_min = -3.14
msg.angle_max = 3.14
msg.ranges = [1.0] * 360 # 假数据
self.pub.publish(msg)
def main():
rclpy.init()
node = FakeLaser()
rclpy.spin(node)
1.4 ROS2 vs ROS1 对比
很多老项目还在用ROS1,但新项目我建议直接上ROS2。为什么?看这张表:
| 特性 | ROS1 (Noetic) | ROS2 (Humble / Iron) |
|---|---|---|
| 通信中间件 | 自定义 TCPROS/UDPROS | DDS (Data Distribution Service) |
| 实时性 | 不支持 | 支持实时内核,适合工业控制 |
| 多机通信 | 需配置 ROS_MASTER_URI | 自动发现,天生分布式 |
| 安全性 | 无认证加密 | DDS 安全插件 (SROS2) |
| Python 版本 | Python 2 (Noetic 支持 Python 3) | Python 3 原生 |
| 生命周期管理 | 无标准化 | Managed Node,状态机控制 |
ros2 run 启动节点,记得先 source 环境。我见过太多人忘记 source /opt/ros/humble/setup.bash,然后一脸懵。
我个人习惯在 ROS2 里用 组件节点 (Component) 来组织 SLAM 模块,这样可以把多个节点放进同一个进程,减少拷贝开销。比如 Cartographer 在 ROS2 里就推荐用 component 方式加载。
好了,这一章我们理清了 SLAM 是什么,ROS2 的核心概念,以及为什么从 ROS1 迁移。