1. SLAM概述与ROS2生态

各位同学好,我是你们这门课的主讲。咱们直接开门见山——SLAM,全称 Simultaneous Localization and Mapping,中文叫“同时定位与地图构建”。说白了,就是让一个机器人从陌生环境出发,一边走路一边给自己定位,同时把周围的地图画出来。你想想看,这像不像一个人蒙着眼走进一间黑屋子,一边摸墙一边在脑子里画地图?嗯,差不多就是这个意思。

我最早接触SLAM是在2016年做AGV项目的时候。当时小车在仓库里跑着跑着就偏了,轮子打滑,里程计完全不可信。后来我意识到,没有SLAM,机器人就像个路痴。从那以后,我就一头扎进了这个领域。今天这第一讲,我们先搭好框架,把SLAM问题和ROS2生态串起来。

SLAM 核心问题 传感器数据 位姿估计 地图构建 激光 / 视觉 / 惯性 里程计 / 优化 栅格 / 特征地图 ROS2 通信框架 (节点/话题/服务/动作) 分布式 · 实时 · 模块化

1.1 SLAM问题定义

SLAM 的数学描述其实不复杂:已知控制量 u₁ₖ 和观测 z₁ₖ,求机器人位姿 xₖ 和地图 m 的联合后验概率。但实际工程里,噪声、数据关联、计算量都是拦路虎。我个人习惯把SLAM拆成“前端”和“后端”——前端处理传感器数据,做帧间匹配;后端做图优化或滤波,消除累积误差。

💡 核心难点: 数据关联 —— 你永远不知道两次观测是不是同一个路标。我早期做激光SLAM时,因为环境对称,回环检测经常误匹配,差点把地图拼成镜像。后来加了ICP精细配准才稳住。

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里把话题名写错了一个字母,结果节点之间死活收不到数据。调试了半小时才发现是 typo。记住: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/UDPROSDDS (Data Distribution Service)
实时性不支持支持实时内核,适合工业控制
多机通信需配置 ROS_MASTER_URI自动发现,天生分布式
安全性无认证加密DDS 安全插件 (SROS2)
Python 版本Python 2 (Noetic 支持 Python 3)Python 3 原生
生命周期管理无标准化Managed Node,状态机控制
⚠️ 注意: 如果你在 ROS2 里用 ros2 run 启动节点,记得先 source 环境。我见过太多人忘记 source /opt/ros/humble/setup.bash,然后一脸懵。

我个人习惯在 ROS2 里用 组件节点 (Component) 来组织 SLAM 模块,这样可以把多个节点放进同一个进程,减少拷贝开销。比如 Cartographer 在 ROS2 里就推荐用 component 方式加载。

好了,这一章我们理清了 SLAM 是什么,ROS2 的核心概念,以及为什么从 ROS1 迁移。