SLAM 脑内架构图(状态估计 → VO → 后端)
🧠 SLAM 脑内架构图(状态估计 → VO → 后端)
一、最顶层:SLAM 是什么?
┌─────────────────────────────────────────────┐ │ SLAM = 状态估计问题 │ │ "我从带噪声的观测中,估计机器人的状态" │ └─────────────────────────────────────────────┘二、状态估计的数学骨架
带噪声的观测 z │ ▼ "真实状态 x 是什么?" │ ┌──────────┴──────────┐ │ 贝叶斯公式 │ │ P(x|z) ∝ P(z|x)·P(x)│ └──────────┬──────────┘ │ 忽略先验 P(x) → 最大似然 │ 假设高斯噪声 → 取负对数 │ 最小二乘法 │ 非线性 → 迭代优化 │ GN / LM 求微调量 Δx │ x ← x ⊕ Δx │ 收敛 → 最优估计三、前端:视觉里程计(VO)
┌──────────────────────────────────────────────────────┐ │ 前端:VO │ │ "用相邻帧的视觉观测,估计短时间内的相机运动" │ ├──────────────────────────────────────────────────────┤ │ │ │ 状态 x:相机位姿 T ∈ SE(3) │ │ 观测 z:图像(像素坐标 / 灰度) │ │ 观测方程 h(x):投影模型 │ │ 残差 e: │ │ • 特征法 → 重投影误差 │ │ • 直接法 → 光度误差 │ │ 优化:GN / LM │ │ 更新:T ← T · exp(Δξ) │ │ │ ├──────────────┬───────────────────────────────────────┤ │ 特征点法 │ 直接法 │ │ • 提取特征 + 匹配 │ • 不用特征 │ │ • 稀疏点云 │ • 用灰度 │ │ • 对光照不敏感 │ • 弱纹理友好│ │ • 依赖纹理 │ • 怕光照变化│ └──────────────┴───────────────────────────────────────┘四、后端:全局优化
┌──────────────────────────────────────────────────────┐ │ 后端:SLAM │ │ "把前端估计和回环信息融合成全局一致的轨迹和地图" │ ├──────────────────────────────────────────────────────┤ │ │ │ 目标函数: │ │ min ‖e_前端‖² + ‖e_回环‖² + ‖e_先验‖² │ │ │ │ 优化方法: │ │ • 图优化(g2o / Ceres / GTSAM) │ │ • Bundle Adjustment(BA) │ │ • 滑动窗口 / 全局优化 │ │ │ │ 节点:位姿 + 地图点 │ │ 边: │ │ • 前端里程计边 │ │ • 回环边(闭环约束) │ │ • 先验边(IMU / GPS) │ │ │ └──────────────────────────────────────────────────────┘五、完整数据流(从传感器到轨迹)
┌────────┐ ┌────────┐ ┌────────────┐ ┌────────────┐ │ 图像帧 │────▶│ 前端VO │────▶│ 后端优化 │────▶│ 轨迹 + 地图│ │(RGB-D) │ │(位姿估计)│ │(BA+回环) │ │(全局一致) │ └────────┘ └────────┘ └────────────┘ └────────────┘ │ ▲ │ │ └────回环检测──────┘六、一句话串起所有层
SLAM 本质上是一个分层状态估计系统:底层是最小二乘优化,中间层是视觉里程计(特征法 / 直接法),上层是带回环和先验的全局图优化。
七、面试速记版(脑内折叠图)
SLAM ├── 数学基础:贝叶斯 → 最大似然 → 最小二乘 → GN/LM ├── 前端 VO │ ├── 特征法:重投影误差 │ └── 直接法:光度误差 └── 后端 ├── BA / 图优化 ├── 回环检测 └── 先验融合(IMU / GPS)前端 VO 的完整时间线(一步一步来)
🟢 Step 0:初始化(唯一一次“纯单帧”)
第 0 帧到来 ↓ 人为设定: T₀ = I(单位矩阵) ↓ 深度图 / 三角化得到一些 3D 点✅这里用了“单帧位姿估计”
但这个“估计”是人为指定的
没有任何特征法 / 直接法参与
👉 原因:没有上一帧,没法算相对运动
🔵 Step 1:第 1 帧 → 第 2 帧(第一次真正 VO)
第 1 帧(已知 T₁) 第 2 帧(新图) ↓ 特征法 / 直接法登场 ↓ 建立观测方程 ↓ 计算残差 e ↓ GN / LM 求 ΔT₁₂ ↓ T₂ = T₁ · ΔT₁₂❌这里不“算单帧位姿”
✅只用特征法 / 直接法算相对运动 ΔT
👉 关键点:
特征法 / 直接法只负责“算 ΔT”,不负责“算 T₂”
🔵 Step 2:第 2 帧 → 第 3 帧(重复)
第 2 帧(已知 T₂) 第 3 帧(新图) ↓ 特征法 / 直接法 ↓ 算 ΔT₂₃ ↓ T₃ = T₂ · ΔT₂₃✅ 模式完全一样
🔵 Step N:一直往后走
Tₖ = Tₖ₋₁ · ΔTₖ₋₁,ₖ👉前端 VO 的本质:
99% 的时间
特征法 / 直接法在干活
“单帧位姿”只是记账用的结果
三、什么时候“单帧位姿估计”真的被“算”出来?
✅ 情况 1:初始化(假算)
T₀ = I人为规定,不是算出来的。
✅ 情况 2:递推得到(最常见)
Tₖ = Tₖ₋₁ · ΔT这是通过相对运动推出来的,不是单帧独立估计。
✅ 情况 3:PnP(真·单帧位姿估计)
发生在这些场景:
1️⃣ 重定位(Tracking Lost)
当前帧 + 已有地图 ↓ PnP ↓ 直接算出 T_current✅ 这里真的在用单帧图像算位姿
✅ 通常配合特征点法(EPnP / DLT)
2️⃣ 后端 BA 中的一次迭代
固定地图点 ↓ 优化某一帧的 T ↓ 本质也是单帧 PnP四、一句话区分(非常重要)
前端 VO:
特征法 / 直接法 → 算ΔT
位姿更新公式 → 算Tₖ
重定位 / PnP:
特征法 → 直接算Tₖ
用熟悉的“状态估计语言”再讲一遍
观测 z ↓ h(x):观测方程 ↓ 残差 e ↓ 优化求 Δx ↓ x_new = x_old ⊕ Δx在前端 VO 里:
符号
含义
x_old
Tₖ₋₁
x_new
Tₖ
Δx
ΔT
h(x)
投影 / 光度模型
优化方法
特征法 / 直接法
👉特征法 / 直接法 = 优化模块
👉单帧位姿 = 优化结果的累积
正确理解:
特征法和直接法从来不算‘这一帧在哪’,它们只算‘这一帧相对于上一帧怎么动’。
单帧位姿是“动完之后,累加出来的”。
[第 0 帧] 已知 T₀ + 3D 点
[第 1 帧] 新图像
│
▼
特征法 / 直接法 登场
│
├─ 特征法:找匹配点 → 重投影误差
└─ 直接法:灰度不变 → 光度误差
│
▼
GN / LM 迭代
│
▼
算出相对运动 ΔT₀₁
│
▼
T₁ = T₀ · ΔT₀₁
│
▼
记录 T₁,丢弃 / 缓存中间量