SLAM(同步定位与建图)

文章目录

    • [1. SLAM 核心思想概述](#1. SLAM 核心思想概述)
    • [2. SLAM 系统架构图示](#2. SLAM 系统架构图示)
    • [3. 关键技术与知识领域](#3. 关键技术与知识领域)
    • [4. C 代码概念性示例](#4. C 代码概念性示例)
      • [片段 1:前端里程计计算 (概念性)](#片段 1:前端里程计计算 (概念性))
      • [片段 2:后端图优化概念 (伪代码风格)](#片段 2:后端图优化概念 (伪代码风格))
    • 总结

1. SLAM 核心思想概述

SLAM 的全称是 Simultaneous Localization and Mapping,即同步定位与建图 。它要解决的是一个"鸡生蛋还是蛋生鸡"的问题:一个自主移动的机器人(或设备)在未知环境中,需要:

1、定位 :确定自身的位置和姿态。
2、建图 :构建周围环境的地图。

但这两者相互依赖:精确的地图需要知道机器人的准确位置才能构建;而精确的定位又需要一张准确的地图作为参考。SLAM 的核心就是通过一系列传感器数据(如激光雷达、摄像头、IMU 等)和先进的算法,来同时解决这两个问题。

2. SLAM 系统架构图示

下面是一个典型的 SLAM 系统(以视觉或激光 SLAM 为例)的流程图,展示了其核心模块和数据流。
SLAM系统 提取特征/计算里程计 优化后的位姿 检测回环 回环约束 更新地图 优化后的位姿 后端-优化 前端-跟踪 建图 回环检测 传感器数据:
图像/激光扫描/IMU 输出: 全局一致的地图 输出: 机器人运动轨迹

图示解读

  • 传感器数据:系统的输入。可以是相机捕获的图像序列、激光雷达的点云扫描、IMU 测量的加速度和角速度等。

  • 前端 (Front-End) - 跟踪

    • 职责:数据关联、初始位姿估计(里程计)。
    • 技术 :从连续两帧数据中提取特征(如 SIFT, ORB, 角点)并进行匹配,或直接匹配点云,来估算机器人相对运动的位移和旋转(增量运动)。这个过程也称为里程计,但它会累积误差。
  • 回环检测 (Loop Closure Detection)

    • 职责:识别机器人是否回到了之前访问过的地点。
    • 技术:通过比较当前观测与历史观测的相似性(如图像特征匹配、点云匹配)来实现。这是消除累积误差的关键。
  • 后端 (Back-End) - 优化

    • 职责 :接收前端提供的里程计约束和回环检测提供的回环约束,对所有时刻的机器人位姿和地图路标点进行全局优化,得到一个全局一致的最优估计。
    • 技术 :主要基于图优化 (Graph Optimization)或滤波(如 Extended Kalman Filter - EKF)技术。现代 SLAM 系统(如 ORB-SLAM, Cartographer)多以图优化(使用 g2o, GTSAM 等库)为核心。
  • 建图 (Mapping)

    • 职责:根据优化后的机器人位姿,将传感器观测到的数据融合到全局地图中。
    • 输出 :地图的表示形式多样,如稀疏特征点地图稠密点云地图占据栅格地图 (Occupancy Grid Map)或八叉树地图(OctoMap)。

3. 关键技术与知识领域

SLAM 是一个高度跨学科的领域,融合了以下技术:

1、状态估计理论

  • 核心:如何从带有噪声的观测数据中,最优地估计系统的状态(机器人的位姿 [x, y, z, roll, pitch, yaw])。
  • 知识:概率论、贝叶斯滤波、卡尔曼滤波(KF)、扩展卡尔曼滤波(EKF)、无迹卡尔曼滤波(UKF)、粒子滤波(PF)。

2、优化理论

  • 核心:将 SLAM 问题建模为一个巨大的非线性最小二乘问题,并通过迭代优化(如高斯-牛顿法、LM 算法)来求解。
  • 知识:线性代数、矩阵分析、最优化方法。图优化是现代 SLAM 的后端标准。

3、计算机视觉

  • 核心:主要用于视觉 SLAM (VSLAM)。涉及从图像中提取信息。
  • 知识:特征提取与匹配(SIFT, SURF, ORB)、相机模型(针孔、鱼眼)、畸变校正、对极几何、PnP (Perspective-n-Point)、ICP (Iterative Closest Point)、光流、深度学习(用于深度估计、特征提取、端到端 SLAM)。

4、几何学与刚体变换

  • 核心:描述机器人在三维空间中的运动和环境点的位置。
  • 知识:三维空间中的旋转和平移(李群 SO(3), SE(3))、四元数、旋转矩阵、欧拉角。

5、传感器融合

  • 核心:结合不同传感器(如相机+IMU)的优势,克服单一传感器的局限性(如视觉遮挡、IMU 漂移)。
  • 知识:多传感器校准、时间同步、滤波与优化框架。

6、C++/Python 编程与软件工程

  • SLAM 系统对性能和效率要求极高,核心模块通常用 C++ 实现。需要熟练掌握数据结构、算法、多线程、性能优化等。

4. C 代码概念性示例

由于完整的 SLAM 系统非常庞大,这里我们用两个简化的 C 代码片段来阐释前端和后端的思想。

片段 1:前端里程计计算 (概念性)

假设我们有一个简单的 2D 激光雷达,通过计算连续两帧扫描之间的位移和旋转。

c 复制代码
#include <math.h>

// 简化的点结构
typedef struct {
    float x;
    float y;
} Point2D;

// 简化的激光扫描结构
typedef struct {
    Point2D points[360]; // 360个点,一度一个
    int count;
} LidarScan;

// 使用ICP的简单思想计算两帧扫描之间的位姿变化(位移和旋转)
// 这是一个极度简化的概念实现,真实的ICP复杂得多
void calculate_odometry(const LidarScan* previous_scan, const LidarScan* current_scan, float* delta_x, float* delta_y, float* delta_theta) {
    // 1. 数据关联(这里假设最简单的情况,点已按顺序对应)
    // 真实系统需要复杂的匹配算法,如最近邻搜索

    // 2. 计算旋转(简化:使用平均点差)
    Point2D prev_center = {0}, curr_center = {0};
    for (int i = 0; i < previous_scan->count; ++i) {
        prev_center.x += previous_scan->points[i].x;
        prev_center.y += previous_scan->points[i].y;
        curr_center.x += current_scan->points[i].x;
        curr_center.y += current_scan->points[i].y;
    }
    prev_center.x /= previous_scan->count;
    prev_center.y /= previous_scan->count;
    curr_center.x /= current_scan->count;
    curr_center.y /= current_scan->count;

    // 计算以中心为参考的向量,并求平均角度差(非常 naive 的方法)
    float angle_sum = 0.0f;
    int num_valid = 0;
    for (int i = 0; i < previous_scan->count; ++i) {
        Point2D prev_vec = {previous_scan->points[i].x - prev_center.x, previous_scan->points[i].y - prev_center.y};
        Point2D curr_vec = {current_scan->points[i].x - curr_center.x, current_scan->points[i].y - curr_center.y};
        
        float prev_angle = atan2f(prev_vec.y, prev_vec.x);
        float curr_angle = atan2f(curr_vec.y, curr_vec.x);
        angle_sum += curr_angle - prev_angle;
        num_valid++;
    }
    *delta_theta = angle_sum / num_valid; // 估计的平均旋转

    // 3. 计算平移(简化)
    // 假设旋转后,平移就是中心点的位移减去旋转的影响
    float cos_theta = cosf(*delta_theta);
    float sin_theta = sinf(*delta_theta);
    // 将上一个中心点根据旋转进行变换
    Point2D rotated_prev_center = {
        prev_center.x * cos_theta - prev_center.y * sin_theta,
        prev_center.x * sin_theta + prev_center.y * cos_theta
    };
    *delta_x = curr_center.x - rotated_prev_center.x;
    *delta_y = curr_center.y - rotated_prev_center.y;

    printf("Odometry Estimated: dx=%f, dy=%f, dtheta=%f\n", *delta_x, *delta_y, *delta_theta);
}

片段 2:后端图优化概念 (伪代码风格)

这个片段展示图优化问题的构建思想。实际中会使用 g2o 或 Ceres Solver 等库。

c 复制代码
// 假设:位姿节点和约束边的结构
typedef struct {
    int id;
    float x, y, theta; // 待优化的位姿
} PoseNode;

typedef struct {
    int id_from, id_to;
    float dx, dy, dtheta; // 测量得到的约束,比如来自里程计或回环
    float information_matrix[3][3]; // 约束的信息矩阵(权重/不确定性)
} ConstraintEdge;

// 一个简化的图优化器结构
typedef struct {
    PoseNode* poses;
    int num_poses;
    ConstraintEdge* constraints;
    int num_constraints;
} PoseGraph;

// 核心优化函数(概念性,实际使用迭代优化库)
void optimize_graph(PoseGraph* graph) {
    // 这是一个巨大的非线性最小二乘问题:
    // min Σ [ e(ij)^T * Ω_ij * e(ij) ]
    // 其中 e(ij) 是预测位姿和测量约束之间的误差函数
    // Ω_ij 是信息矩阵

    // 误差函数示例:计算两个位姿之间的约束误差
    for (int edge_idx = 0; edge_idx < graph->num_constraints; ++edge_idx) {
        ConstraintEdge* edge = &graph->constraints[edge_idx];
        PoseNode* pose_i = &graph->poses[edge->id_from];
        PoseNode* pose_j = &graph->poses[edge->id_to];

        // 1. 根据当前估计的 pose_i 和 pose_j,计算它们之间的相对变换 T_ij_estimated
        // 2. 将 T_ij_estimated 与测量的约束 T_ij_measured (edge->dx, dy, dtheta) 进行比较,得到误差向量 e_ij
        // 3. 目标是最小化所有边的 e_ij^T * Ω_ij * e_ij 的总和

        // printf("计算边 %d->%d 的误差...\n", edge->id_from, edge->id_to);
    }

    // 真实实现会:
    // - 使用李代数表示位姿和变换,便于求导
    // - 构建雅可比矩阵和海森矩阵
    // - 使用高斯-牛顿或LM等迭代算法求解增量方程,更新所有 pose_node 的估计值
    // printf("正在进行LM迭代优化...\n");
    // ... 大量线性代数运算 ...

    printf("图优化完成!位姿已调整以减少全局不一致性。\n");
}

总结

SLAM 是一个复杂而迷人的工程与学术领域。它不仅仅是几个算法,而是一个完整的系统,涉及:

  • 理论深度:深厚的数学和概率论基础。
  • 技术广度:涵盖计算机视觉、机器人学、传感器技术、优化理论。
  • 工程挑战:对系统稳定性、实时性、效率的要求极高。

现代的成熟 SLAM 系统(如 ORB-SLAM3LIO-SAMGoogle Cartographer)都是数万行 C++ 代码的结晶,并 heavily rely on 第三方优化库。本文的图示和代码旨在为你提供一个高层次的、概念性的理解,而要深入实践,需要在这些基础知识之上,选择特定方向(如 VSLAM、激光SLAM、多传感器融合)进行深入研究。

相关推荐
点云SLAM15 小时前
四元数 (Quaternion)与李群SE(3)知识点(1)
线性代数·slam·四元数·旋转矩阵·位姿表示·李群se(3)·四元数插值
海鸥_5 天前
常见的相机模型针孔/鱼眼(Pinhole,Mei,K
计算机视觉·相机·slam
点云SLAM21 天前
SLAM文献之-Globally Consistent and Tightly Coupled 3D LiDAR Inertial Mapping
3d·机器人·slam·vgicp算法·gpu 加速·lidar-imu 建图方法·全局匹配代价最小化
时凯凯凯凯1 个月前
使用 Vive Tracker 替代 T265 实现位姿获取(基于 Ubuntu + SteamVR)
linux·ubuntu·目标跟踪·slam
点云SLAM2 个月前
矩阵中QR算法分解简介和基于Eigen库使用示例
人工智能·线性代数·算法·矩阵·slam·qr矩阵分解算法·数值线性代数
古承风2 个月前
相机的内外参分别指什么
自动驾驶·slam
龙猫略略略2 个月前
slam中的eskf观测矩阵推导
slam·激光slam·fastlio
Perishell2 个月前
无人机避障——感知篇(Ego_Planner_v2中的滚动窗口实现动态实时感知建图grid_map ROS节点理解与参数调整影响)
计算机视觉·无人机·slam·地图生成·建图感知·双目视觉
bigFish啦啦啦2 个月前
D435i + ROS2
slam