本文档属于 Robotics Tutorial 项目,作者:Pengfei Guo,达妙科技。采用 CC BY 4.0 协议,转载请注明出处。
C++基础与进阶方向综合教学大纲¶
版本: v1.0 | 日期: 2026-05-14
定位:
02_C++基础与进阶/是整个 Robotics Tutorial 的公共地基层。它不把 C++ 当成孤立语法课,而是围绕真实机器人软件中的类型系统、资源管理、并发实时、软件工程、库生态、ROS2 工程化和规控公共基础组织。所有方向(SLAM、机械臂、足式、无人机、具身智能)在进入方向专项之前,都应先完成本层的对应学习路径。 数据基础: 58 篇教学文档源码级编写,覆盖 GitHub 上 100+ 个现代 C++ 和机器人项目的源码分析;课程主线按 2026-05 前后版本锁定 Eigen 3.4 / PCL 1.14 / OpenCV 4.10 / Ceres 2.2 / manif 0.0.5 / ROS 2 Kilted,具体 API 以各项目当前官方文档为准。 总投入: 6 个子方向、58 篇文档、~50 周核心内容。可按子方向独立选修,也可按快速路径 ~18 周完成最小闭合。
快速路径(Quick-Start Tracks)¶
不是每个人都需要完整 50 周课程。以下针对不同方向的最小路径,让你获得进入方向专项的能力。
路径 S:SLAM 方向快速入口(~18 周)¶
10_C++语言核心/10_类型系统(1w) → 20_编译模型(1w) → 30_现代类设计(1w) → 40_RAII(1w) → 50_移动语义(1w)
→ 100_Lambda与STL(1w) → 110_Eigen基础(1.5w) → 120_函数模板(1w)
→ 20_并发/10_线程管理(1w) → 20_并发/40_实时约束(1w)
→ 40_通用库/10_文件IO(1w) → 40_通用库/20_Eigen深入(1w) → 40_通用库/30_李群manif(1w)
→ 40_通用库/40_Ceres(2w) → 40_通用库/50_PCL(1w)
→ 30_软件工程/50_测试调试(1w)
→ 50_ROS2/20_构建与建模(1w)
总计 ~18 周
路径 M:机械臂方向快速入口(~16 周)¶
10_C++语言核心/10_类型系统(1w) → 20_编译模型(1w) → 30_现代类设计(1w) → 40_RAII(1w) → 50_移动语义(1w)
→ 60_继承多态(1w) → 100_Lambda与STL(1w) → 110_Eigen基础(1.5w)
→ 130_SFINAE与萃取(1w) → 140_CRTP(1w)
→ 20_并发/10_线程管理(1w) → 20_并发/40_实时约束(1w)
→ 60_规控/10_数值优化库(1w) → 60_规控/20_实时Linux(1w)
→ 50_ROS2/20_构建与建模(1w) → 50_ROS2/40_硬件集成(0.5w)
总计 ~16 周
路径 L:足式/无人机规控方向快速入口(~17 周)¶
10_C++语言核心/10_类型系统(1w) → 20_编译模型(1w) → 30_现代类设计(1w) → 40_RAII(1w) → 50_移动语义(1w)
→ 100_Lambda与STL(1w) → 110_Eigen基础(1.5w) → 140_CRTP(1w)
→ 20_并发/10_线程管理(1w) → 20_并发/40_实时约束(1w)
→ 60_规控/10_数值优化库(1w) → 60_规控/20_实时Linux(1w)
→ 60_规控/30_无锁数据结构(1w) → 60_规控/50_Eigen高级(1w)
→ 50_ROS2/20_构建与建模(1w) → 50_ROS2/40_硬件集成(0.5w)
总计 ~17 周
路径 R:RL / 具身智能方向快速入口(~14 周)¶
10_C++语言核心/10_类型系统(1w) → 20_编译模型(1w) → 40_RAII(1w) → 50_移动语义(1w)
→ 100_Lambda与STL(1w) → 110_Eigen基础(1.5w)
→ 20_并发/10_线程管理(1w) → 20_并发/70_CUDA基础(1w) → 20_并发/80_CUDA应用(1w)
→ 60_规控/60_GPU加速(1w)
→ 50_ROS2/10_设计哲学(0.5w) → 50_ROS2/20_构建与建模(1w)
→ 50_ROS2/40_硬件集成(0.5w) → 50_ROS2/30_仿真生态(1w)
总计 ~14 周
计算与硬件需求¶
| 子方向 | GPU | 真机/传感器 | 备注 |
|---|---|---|---|
| Part 1: C++ 语言核心 (16章) | -- | -- | 任意 Linux/Mac/WSL2 均可 |
| Part 2: 并发与系统编程 (Ch1-6) | -- | -- | 推荐多核 CPU (>=4C) |
| Part 2: CUDA 章节 (Ch7-8) | RTX 3060+ | -- | Jetson Orin 可替代 |
| Part 3: 软件工程 (6章) | -- | -- | 需安装 GDB/Sanitizer 工具链 |
| Part 4: 通用库剖析 (6章) | -- | -- | PCL/OpenCV 需 16GB+ RAM |
| Part 5: ROS2 工程化 (5章) | -- | 推荐相机+IMU | Docker 推荐;仿真可替代真机 |
| Part 6: 规控公共基础 (8章) | RTX 3060+ (GPU章) | -- | PREEMPT_RT 内核推荐 |
工业 vs 研究标记¶
| 标记 | 含义 | 代表章节 |
|---|---|---|
| 🏭 | 工业落地核心 | 10_C++/40_RAII, 20_并发/10_线程, 30_软件工程/50_测试, 50_ROS2/20_构建, 60_规控/20_实时Linux |
| 🔬 | 研究前沿 | 10_C++/160_Concepts, 20_并发/80_CUDA应用, 40_通用库/30_李群manif, 60_规控/60_GPU加速 |
| 🏭🔬 | 工业+研究兼有 | 10_C++/110_Eigen, 40_通用库/40_Ceres, 40_通用库/50_PCL, 50_ROS2/30_仿真, 60_规控/10_数值优化 |
总览路线图¶
┌────────────────────────────────────────────────────────────────────────────┐
│ 01_数学 完成 (线性代数 · 微积分 · 概率论 · 最优化基础) │
└────────────────────────────────────────────────────────────────────────────┘
│
▼
┌────────────────────────────────────────────────────────────────────────────┐
│ 02_C++基础与进阶 ← 你在这里 │
│ │
│ Part 1 C++ 语言核心 (10_, 16章, ~16 周) │
│ 类型系统 → 编译模型 → 类设计 → RAII → 移动 → 多态 → 类型转换 │
│ → 异常 → 运算符 → Lambda → Eigen基础 → 模板系列(4章) → 宏 → Concepts │
│ │
│ Part 2 并发与系统编程 (20_, 8章, ~8 周) │
│ 线程互斥 → 原子内存模型 → 并行框架 → 实时约束 │
│ → pmr分配 → 缓存布局 → CUDA基础 → CUDA应用 │
│ │
│ Part 3 软件工程 (30_, 6章, ~4 周) │
│ 设计模式(入口) → 多线程架构(入口) → ROS2集成(入口) │
│ → CMake(入口) → 测试调试 → 日志序列化 │
│ │
│ Part 4 通用库剖析 (40_, 6章, ~9 周) │
│ 文件IO → Eigen深入 → 李群manif → Ceres → PCL → OpenCV │
│ │
│ Part 5 ROS2 工程化 (50_, 5章, ~5 周) │
│ 设计哲学 → 构建与建模 → SLAM导航仿真 → 硬件与RL → CLI调试 │
│ │
│ Part 6 规控公共工程基础 (60_, 8+导读, ~8 周) │
│ 数值优化库 → 实时Linux → 无锁并发 → ROS2架构 │
│ → Eigen高级 → GPU加速 → 构建系统 → 测试调试 │
└────────────────────────────────────────────────────────────────────────────┘
│
├──────────┬──────────┬──────────┬──────────┐
▼ ▼ ▼ ▼ ▼
03_SLAM 04_移动规控 05_运动控制 06_具身智能 (各方向专项)
SLAM后端 移动机器人 机械臂 VLA/RL
因子图 路径规划 力控 Sim2Real
多传感器 轨迹跟踪 足式 灵巧操作
子方向之间的依赖关系¶
Part 1: C++ 语言核心 (10_)
┌──────────┬────────────┐
▼ ▼ ▼
Part 2: 并发 (20_) │ Part 3: 软件工程 (30_)
│ │ │
▼ ▼ ▼
Part 4: 通用库剖析 (40_)
│ │
▼ ▼
Part 5: ROS2 (50_) Part 6: 规控公共 (60_)
│ │
▼ ▼
┌─────┴─────┐ ┌──────┴──────┐
▼ ▼ ▼ ▼
03_SLAM 04_移动 05_机械臂 05_足式
前置知识依赖矩阵¶
| 本大纲子方向 | 依赖 01_数学 内容 | 关键知识点 |
|---|---|---|
| Part 1: C++ 语言核心 | 无强依赖 | 编程入门级 C++ 基础即可 |
| Part 2: 并发与系统编程 | 线性代数基础 | Eigen 矩阵运算 (CUDA 章节) |
| Part 3: 软件工程 | 无强依赖 | -- |
| Part 4: 通用库剖析 | 线性代数、微积分、概率论 | 旋转矩阵/四元数、最小二乘/优化、高斯分布 |
| Part 5: ROS2 工程化 | 无强依赖 | -- |
| Part 6: 规控公共基础 | 线性代数、最优化、微分方程 | QP/NLP建模、Jacobian、动力学方程 |
| 后续章节 | 前置章节 | 原因 |
|---|---|---|
| RAII 与智能指针 (10_/40) | 现代类设计 (10_/30) | 必须理解构造、析构和特殊成员函数 |
| 移动语义 (10_/50) | RAII (10_/40) | 移动本质是资源所有权转移 |
| Lambda (10_/100) | 移动语义 (10_/50) | 捕获对象涉及拷贝、移动和生命周期 |
| Eigen 基础 (10_/110) | 类型系统 (10_/10), 类型转换 (10_/70) | 类型推导、对齐和类型转换 |
| 模板与 traits (10_/120-140) | Lambda (10_/100) | CRTP、Policy 和库适配依赖模板心智模型 |
| 并发 (20_/10) | RAII (10_/40), 异常 (10_/80) | 线程代码必须有资源生命周期和异常边界 |
| pmr (20_/50) | 实时约束 (20_/40) | 分配优化服务于实时路径和延迟上界 |
| CUDA 应用 (20_/80) | 缓存布局 (20_/60), CUDA 基础 (20_/70) | GPU 加速前必须理解数据布局和传输成本 |
| 通用库 Eigen 深入 (40_/20) | Eigen 基础 (10_/110) | 表达式模板、对齐、SIMD 是 Eigen 进阶 |
| 李群 manif (40_/30) | Eigen 深入 (40_/20) | 旋转/变换依赖 Eigen 高级用法 |
| Ceres (40_/40) | 李群 manif (40_/30), Eigen 深入 (40_/20) | 非线性优化依赖 Manifold 和 Eigen 接口 |
| PCL (40_/50) | Eigen 深入 (40_/20) | 点云处理依赖 Eigen 对齐和模板特化 |
| OpenCV (40_/60) | Eigen 深入 (40_/20) | Mat-Eigen 互操作需要理解内存布局 |
| 测试调试 (30_/50) | 异常 (10_/80), 线程 (20_/10), 实时 (20_/40) | 测试要覆盖异常、并发和实时边界 |
| 日志序列化 (30_/60) | 测试调试 (30_/50) | 运行时基础设施必须可测试、可复现 |
| ROS2 构建 (50_/20) | 编译模型 (10_/20), RAII (10_/40) | ROS2 构建依赖 CMake 和 C++ 编译模型 |
| ROS2 硬件集成 (50_/40) | 线程 (20_/10), 实时 (20_/40) | 硬件接入涉及并发和实时边界 |
| 规控数值优化 (60_/10) | Ceres (40_/40), Eigen 深入 (40_/20) | 从 Ceres 迁移到 QP/NLP 生态 |
| 规控实时 Linux (60_/20) | 实时约束 (20_/40), 线程 (20_/10) | PREEMPT_RT 是并发+实时的系统级扩展 |
| 规控无锁 (60_/30) | 原子 (20_/20), 实时 (20_/40) | 无锁结构建立在内存模型和实时约束之上 |
生态速览(2026-05)¶
| 类别 | 核心栈 | 最新动态 |
|---|---|---|
| C++ 标准 | C++17 (主线) / C++20 (进阶) / C++23 (前沿) | Modules 逐步落地;std::expected 生产可用;Contracts 进入 C++26 草案 |
| Eigen | Eigen 3.4.x | 长期稳定;CMake targets 成熟;Ref<T> 泛型接口广泛采用 |
| Ceres | Ceres 2.2.x | Manifold API 替代 LocalParameterization;EvaluationCallback 简化 VIO |
| PCL | PCL 1.14.x | C++17 重构持续;VoxelGrid 性能提升;ROS2 PCL 桥接稳定 |
| OpenCV | OpenCV 4.10.x | DNN 模块持续增强;CUDA 后端更成熟;GStreamer 管线集成 |
| manif | manif 0.0.5 | SE(3)/SO(3)/SE2 完整支持;Jacobian 自动计算;与 Ceres Manifold 对接 |
| ROS2 | Kilted Kaiju (2025) | 基于 Ubuntu 24.04;lifecycle node 成熟;ros2_control 异步硬件组件 |
| CUDA | CUDA 12.x + Thrust 2.x | CUDA Graphs 生产就绪;Thrust 重命名为 CCCL;cuBLAS LT 新 API |
| CMake | CMake 3.29+ | cmake_path() 增强;CXX_MODULE_DIRS 实验性 C++20 modules 支持 |
| 构建生态 | colcon + ament + rosdep | ament_cmake_auto 简化包配置;rosdep 社区键持续增长 |
| QP 求解器 | OSQP / ProxQP / qpOASES / HPIPM | ProxQP 3.x 性能提升显著;OSQP 0.6 稳定;HPIPM 用于 MPC |
| NLP 求解器 | Ipopt / CasADi / acados | CasADi 3.6 改进代码生成;acados 0.4 实时 MPC 成熟 |
| 仿真 | MuJoCo 3.x / Gazebo Ionic / Isaac Sim | MuJoCo MJX GPU 后端生产就绪;Genesis 物理引擎 43M FPS |
Part 1: C++ 语言核心(10_C++语言核心/, 16 章 ~16 周)¶
完成本部分后你能做什么: 理解现代 C++ 工程代码的主要设计约束,能阅读和修改中型 SLAM/ROS2 C++ 代码库,掌握类型系统、资源管理、模板元编程和 Eigen 数学预备。
导读¶
模块导读与学习建议
| 属性 | 值 |
|---|---|
| 文件 | 10_C++语言核心/README.md |
| 规模 | 18 行 |
| 定位 | 整体课程结构说明,学习路径建议 |
Ch01 类型系统与值类别推导¶
从
auto/decltype到值类别,建立 C++ 类型推导的完整心智模型
| 属性 | 值 |
|---|---|
| 文件 | 10_C++语言核心/10_类型系统与值类别推导.md |
| 周数 | 1.0 周 |
| 前置依赖 | C++ 基础语法 (函数、指针、类初步) |
| 规模 | 1722 行 |
| 工业/研究 | 🏭 |
核心知识点:
1. auto 类型推导规则:值语义推导、引用折叠、const 剥离
2. decltype 推导规则:表达式类别决定推导结果
3. 值类别 (value category):lvalue / prvalue / xvalue 的精确定义
4. const 与 constexpr 的本质区别和编译期计算
5. 函数参数传递策略:值传递 / 引用传递 / 万能引用 的选型原则
6. SLAM 代码中的类型推导实例:Eigen 表达式类型、回调签名推导
7. 引用折叠 (reference collapsing) 与转发引用的关系
8. C++17 CTAD (Class Template Argument Deduction) 基础
9. using 类型别名 vs typedef 的现代用法
10. 类型推导陷阱:auto 捕获 Eigen 表达式的悬垂风险
练习:
1. A 型: 编写一组函数,用 static_assert 验证不同 auto/decltype 场景的推导结果
2. B 型: 阅读 ORB-SLAM3 中 3 处 auto 使用,分析推导出的精确类型
3. 思考题: 为什么 Eigen 文档建议不要对矩阵运算结果使用 auto?
Ch02 编译模型基础¶
预处理-编译-链接三阶段模型,理解 ODR、符号可见性和头文件管理
| 属性 | 值 |
|---|---|
| 文件 | 10_C++语言核心/20_编译模型基础.md |
| 周数 | 1.0 周 |
| 前置依赖 | Ch01 |
| 规模 | 1644 行 |
| 工业/研究 | 🏭 |
核心知识点:
1. 翻译单元 (translation unit) 的精确定义
2. 预处理阶段:#include 展开、条件编译、宏展开
3. 编译阶段:名字查找、重载决议、模板实例化
4. 链接阶段:符号解析、静态库/共享库、链接顺序
5. ODR (One Definition Rule) 违反的常见场景和诊断
6. inline 变量/函数的链接语义 (C++17)
7. 头文件卫士 vs #pragma once vs C++20 模块
8. 静态初始化顺序 (SIOF) 问题与解决方案
9. 符号可见性控制:-fvisibility=hidden、__attribute__((visibility))
10. SLAM 项目常见编译问题:Eigen 头文件顺序、模板显式实例化
练习:
1. A 型: 构造一个 ODR 违反场景,用 ASan 和 nm 诊断并修复
2. B 型: 分析一个 SLAM 项目的编译时间瓶颈,用 -ftime-report 定位最慢的翻译单元
3. 思考题: 为什么模板库通常必须放在头文件中?C++20 模块如何解决这个问题?
Ch03 现代类设计与特殊成员函数¶
Rule of Zero/Five,构造与初始化,SLAM 中的类型设计模式
| 属性 | 值 |
|---|---|
| 文件 | 10_C++语言核心/30_现代类设计与特殊成员函数.md |
| 周数 | 1.0 周 |
| 前置依赖 | Ch02 |
| 规模 | 1586 行 |
| 工业/研究 | 🏭 |
核心知识点:
1. 特殊成员函数六件套:默认/拷贝/移动构造 + 拷贝/移动赋值 + 析构
2. Rule of Zero:优先让编译器生成特殊成员函数
3. Rule of Five:管理资源时必须全部声明
4. = default / = delete 的语义和使用场景
5. 成员初始化列表 vs 类内初始值 (NSDMI) 的选型
6. 委托构造函数 (delegating constructor) 与初始化重用
7. 聚合初始化 (aggregate initialization) 与 C++17 结构化绑定
8. SLAM 中的类型设计:MapPoint/Frame/KeyFrame 的所有权模型
9. 不可拷贝但可移动的设计模式 (如线程、文件句柄)
10. explicit 构造函数与转换运算符的防御性设计
练习:
1. A 型: 设计一个 SensorBuffer 类,声明 Rule of Five 并用 static_assert 验证可移动不可拷贝
2. B 型: 分析 ORB-SLAM3 的 Frame 类,判断其特殊成员函数是否满足 Rule of Five
3. 思考题: 如果一个类只有 = default 的析构函数但包含 unique_ptr 成员,它是否可拷贝?
Ch04 RAII 与智能指针¶
资源获取即初始化,
unique_ptr/shared_ptr/weak_ptr的所有权语义
| 属性 | 值 |
|---|---|
| 文件 | 10_C++语言核心/40_RAII与智能指针.md |
| 周数 | 1.0 周 |
| 前置依赖 | Ch03 |
| 规模 | 1621 行 |
| 工业/研究 | 🏭 |
核心知识点:
1. RAII 核心契约:构造获取资源,析构释放资源
2. unique_ptr:独占所有权、自定义删除器、make_unique
3. shared_ptr:共享所有权、引用计数、控制块布局
4. weak_ptr:打破循环引用、观察者模式
5. 智能指针与工厂模式:返回 unique_ptr 的工厂函数
6. 智能指针的性能开销:shared_ptr 原子引用计数的代价
7. SLAM 中的所有权模型:MapPoint 的 shared_ptr vs weak_ptr 循环
8. enable_shared_from_this 的使用场景和陷阱
9. 资源边界:文件句柄、GPU 缓冲区、socket 的 RAII 封装
10. 智能指针与多线程:shared_ptr 的线程安全保证边界
练习:
1. A 型: 封装 OpenGL 纹理的 RAII 管理类,用 unique_ptr + 自定义删除器
2. B 型: 分析 LIO-SAM 中 shared_ptr<PointCloud> 的生命周期流转路径
3. 思考题: 为什么 make_shared 比 shared_ptr<T>(new T) 更高效?
Ch05 移动语义与完美转发¶
右值引用、移动构造、RVO、
std::forward与转发引用
| 属性 | 值 |
|---|---|
| 文件 | 10_C++语言核心/50_移动语义与完美转发.md |
| 周数 | 1.0 周 |
| 前置依赖 | Ch04 |
| 规模 | 1573 行 |
| 工业/研究 | 🏭 |
核心知识点:
1. 右值引用 (T&&) 的本质:绑定到即将销毁的对象
2. 移动构造/移动赋值:资源窃取而非深拷贝
3. std::move 的真正语义:无条件转换为右值引用
4. moved-from 状态:合法但未指定的状态
5. RVO / NRVO (返回值优化):编译器何时省略拷贝/移动
6. 完美转发 (std::forward):保持值类别透传
7. 引用折叠规则与万能引用 (T&& in template)
8. 移动语义在容器中的应用:emplace_back vs push_back
9. SLAM 中的移动场景:关键帧插入、地图点转移
10. 移动语义陷阱:对 const 对象 std::move 的静默退化
练习:
1. A 型: 实现一个 PointCloudBuffer,验证移动构造比拷贝快 10x
2. B 型: 在真实 SLAM 代码中找到 3 处可以用移动替代拷贝的地方
3. 思考题: 为什么 std::move 不保证移动发生?什么时候 const T&& 会退化为拷贝?
Ch06 继承与多态深入¶
虚函数表、抽象类、接口设计、多态代价分析
| 属性 | 值 |
|---|---|
| 文件 | 10_C++语言核心/60_继承与多态深入.md |
| 周数 | 1.0 周 |
| 前置依赖 | Ch05 |
| 规模 | 1642 行 |
| 工业/研究 | 🏭 |
核心知识点:
1. 虚函数表 (vtable) 的内存布局与调用机制
2. override / final 的防御性用法
3. 虚析构函数:何时必须声明
4. 抽象类与纯虚函数:接口约束
5. 多重继承与虚继承:菱形继承问题
6. RTTI (dynamic_cast, typeid) 的代价和替代方案
7. 接口设计:NVI (Non-Virtual Interface) 模式
8. 多态 vs 模板:运行期多态 vs 编译期多态的选型
9. SLAM 中的多态:特征提取器接口、回环检测接口
10. 对象切片 (slicing) 问题与防御手段
练习:
1. A 型: 设计一个 FeatureExtractor 抽象接口,实现 ORB 和 SuperPoint 两个派生类
2. B 型: 用 GDB 查看一个多态对象的 vtable 布局
3. 思考题: 1kHz 控制循环中虚函数调用的延迟影响有多大?何时应改用 CRTP?
Ch07 类型转换¶
四类 cast、RTTI、Eigen 类型转换、二进制边界
| 属性 | 值 |
|---|---|
| 文件 | 10_C++语言核心/70_类型转换.md |
| 周数 | 1.0 周 |
| 前置依赖 | Ch06 |
| 规模 | 1972 行 |
| 工业/研究 | 🏭 |
核心知识点:
1. static_cast:安全的值转换和向下转型
2. dynamic_cast:运行期安全的多态向下转型
3. const_cast:去除 const 限定的危险操作
4. reinterpret_cast:底层二进制重新解释
5. C 风格转型 (Type)expr 为什么应该避免
6. Eigen 中的 .cast<T>():标量类型转换
7. 指针转换与对齐要求:reinterpret_cast 的 UB 边界
8. 跨 ABI 边界的类型安全:void* 传递的规范
9. 字节序转换与网络通信中的类型转换
10. 隐式转换与 explicit 的交互
练习:
1. A 型: 编写一个类型安全的 variant 访问器,对比 static_cast 和 dynamic_cast 的性能
2. B 型: 找到一个 SLAM 项目中使用 C 风格转型的地方,改为显式 C++ cast 并分析安全性
3. 思考题: reinterpret_cast<char*>(&obj) 合法吗?为什么 C++ 标准对 char* 有特殊待遇?
Ch08 错误处理与异常安全¶
异常安全等级、
noexcept、错误码 vs 异常、std::expected
| 属性 | 值 |
|---|---|
| 文件 | 10_C++语言核心/80_错误处理与异常安全.md |
| 周数 | 1.0 周 |
| 前置依赖 | Ch05 |
| 规模 | 2237 行 |
| 工业/研究 | 🏭 |
核心知识点:
1. 异常安全三级保证:基本保证 / 强保证 / 不抛出保证
2. noexcept 规约:对移动构造和析构的影响
3. 异常与 RAII 的协同:栈展开保证资源释放
4. 错误码 (std::error_code / std::errc) 的无异常路径
5. C++23 std::expected<T, E>:单子式错误处理
6. 异常在跨模块边界的安全传播问题
7. 实时路径禁止异常:-fno-exceptions 的工程影响
8. ROS2 节点边界的错误处理策略:异常 → 日志 + 降级
9. SLAM 中的错误处理模式:跟踪失败、优化发散、传感器超时
10. 异常安全的 swap 习惯用法
练习:
1. A 型: 实现一个强异常安全的 MapDatabase::insertKeyFrame()
2. B 型: 在 VINS-Mono 中找到 3 处异常不安全的代码,提出修复方案
3. 思考题: 为什么 std::vector 的 push_back 在移动构造不是 noexcept 时退化为拷贝?
Ch09 运算符重载¶
运算符语义、仿函数、三路比较、Eigen 运算符惯用法
| 属性 | 值 |
|---|---|
| 文件 | 10_C++语言核心/90_运算符重载.md |
| 周数 | 1.0 周 |
| 前置依赖 | Ch07 |
| 规模 | 2592 行 |
| 工业/研究 | 🏭🔬 |
核心知识点:
1. 运算符重载的基本规则:成员 vs 非成员
2. 算术运算符:+ / - / * 的对称性设计
3. 流输出运算符 <<:友元函数的典型应用
4. 仿函数 (function object):operator() 的回调模式
5. 比较运算符与 C++20 三路比较 (<=>)
6. 下标运算符 [] 和 C++23 多维下标
7. 类型转换运算符:operator T() 的隐式/显式控制
8. Eigen 运算符惯用法:表达式模板如何拦截 +/*
9. 智能指针的解引用运算符 (* / ->)
10. 自增/自减运算符的前置/后置区分
练习:
1. A 型: 为 Pose2D 类实现 * (组合) / inverse() / << (输出) 运算符
2. B 型: 分析 Eigen MatrixBase::operator+ 的模板展开路径
3. 思考题: 为什么 C++20 的 <=> 三路比较可以自动生成 </>/<=/>=?
Ch10 Lambda 与 STL 算法¶
Lambda 表达式、回调、
std::function、STL 算法与容器选型
| 属性 | 值 |
|---|---|
| 文件 | 10_C++语言核心/100_Lambda与STL算法.md |
| 周数 | 1.0 周 |
| 前置依赖 | Ch05 |
| 规模 | 1547 行 |
| 工业/研究 | 🏭 |
核心知识点:
1. Lambda 语法:捕获列表、参数列表、返回类型、mutable
2. 捕获语义:值捕获 vs 引用捕获 vs 初始化捕获 (C++14)
3. std::function 的类型擦除:灵活但有开销
4. 函数模板参数 vs std::function:性能差异
5. STL 算法族:transform/accumulate/sort/find_if/remove_if
6. 容器选型:vector/deque/map/unordered_map 的性能特征
7. 范围 for 与 C++20 std::ranges 的管道语法
8. SLAM 中的回调模式:跟踪器回调、优化完成回调
9. Lambda 与线程:std::thread 构造中的捕获陷阱
10. 泛型 Lambda (C++14/20) 与 auto 参数
练习:
1. A 型: 用 STL 算法实现一个点云下采样器 (VoxelGrid 逻辑)
2. B 型: 对比 std::function<void()> 和模板参数传递回调的性能差异 (benchmark)
3. 思考题: Lambda 捕获 this 时,如果对象被移动了会发生什么?
Ch11 Eigen 基础与 SLAM 数学预备¶
Eigen 矩阵、旋转、齐次变换、
Map、数值边界
| 属性 | 值 |
|---|---|
| 文件 | 10_C++语言核心/110_Eigen基础与SLAM数学预备.md |
| 周数 | 1.5 周 |
| 前置依赖 | Ch01, Ch07 |
| 规模 | 2801 行 |
| 工业/研究 | 🏭🔬 |
核心知识点:
1. Eigen 矩阵类型系统:固定大小 vs 动态大小、行优先 vs 列优先
2. 矩阵运算:加法、乘法、转置、逆、SVD
3. 旋转表示:旋转矩阵、四元数、欧拉角、轴角
4. 齐次变换矩阵 Isometry3d 的正确用法
5. Eigen::Map:零拷贝内存映射
6. Block 操作:.block()/.row()/.col()/.topRows()
7. 线性方程组求解:LLT / LDLT / QR / SVD 的选型
8. 数值稳定性:条件数、浮点精度、比较容差
9. Eigen 与 SLAM:位姿变换、Jacobian 计算、BA 中的稀疏结构
10. AngleAxisd 与 Quaterniond 的互转与插值
练习:
1. A 型: 用 Eigen 实现一个完整的 SE(3) 变换链,验证链式变换的结合律
2. B 型: 用 Map 将一段连续 double 数组映射为 4x4 齐次变换矩阵,在 Ceres 代价函数中使用
3. 思考题: 为什么 Isometry3d 不是 4x4 矩阵?它内部的存储布局是什么?
Ch12 函数模板与类模板基础¶
模板推导、显式实例化、CTAD、非类型模板参数
| 属性 | 值 |
|---|---|
| 文件 | 10_C++语言核心/120_函数模板与类模板基础.md |
| 周数 | 1.0 周 |
| 前置依赖 | Ch10, Ch11 |
| 规模 | 2504 行 |
| 工业/研究 | 🏭🔬 |
核心知识点:
1. 函数模板:类型推导、显式指定、重载决议
2. 类模板:成员函数模板、嵌套类型、typename 消歧义
3. 显式实例化 (template class Foo<int>;) 控制编译时间
4. CTAD (C++17):构造时自动推导模板参数
5. 非类型模板参数 (NTTP):int N/auto N/std::size_t N
6. Eigen 的模板参数化:Matrix<Scalar, Rows, Cols>
7. 模板默认参数与 Allocator 模式
8. 两阶段名字查找 (two-phase lookup) 与 template 关键字
9. SLAM 中的模板应用:泛型优化器、Ceres Jet 类型
10. 模板编译时间管理:前向声明、显式实例化、extern template
练习:
1. A 型: 实现一个 RingBuffer<T, N>,用 NTTP 指定固定容量
2. B 型: 分析 Ceres AutoDiffCostFunction 的模板参数和推导过程
3. 思考题: 为什么显式实例化能减少编译时间?它和隐式实例化的 ODR 关系是什么?
Ch13 模板特化、SFINAE 与类型萃取¶
全特化/偏特化、SFINAE、
type_traits、if constexpr
| 属性 | 值 |
|---|---|
| 文件 | 10_C++语言核心/130_模板特化SFINAE与类型萃取.md |
| 周数 | 1.0 周 |
| 前置依赖 | Ch12 |
| 规模 | 1871 行 |
| 工业/研究 | 🏭🔬 |
核心知识点:
1. 全特化 (full specialization) 与偏特化 (partial specialization)
2. SFINAE (Substitution Failure Is Not An Error) 原则
3. std::enable_if 的条件启用模式
4. type_traits 标准库:is_same/is_integral/is_floating_point
5. if constexpr (C++17):编译期分支
6. 自定义 traits 模式:is_eigen_type<T> 检测
7. 标签分发 (tag dispatch) 与 traits 的结合
8. Eigen 的 traits 体系:NumTraits<Scalar>/ScalarBinaryOpTraits
9. SFINAE vs Concepts:从 C++11 到 C++20 的演进
10. SLAM 库中的 traits 模式:GTSAM traits<T>、Ceres Jet<T,N>
练习:
1. A 型: 用 SFINAE 编写一个 serialize() 函数,对 Eigen 类型和 POD 类型分别处理
2. B 型: 分析 GTSAM 的 traits<Pose3> 实现
3. 思考题: if constexpr 和 enable_if 在哪些场景下不可互换?
Ch14 变参模板、折叠表达式与 CRTP¶
参数包、折叠表达式、CRTP 静态多态
| 属性 | 值 |
|---|---|
| 文件 | 10_C++语言核心/140_变参模板折叠表达式与CRTP.md |
| 周数 | 1.0 周 |
| 前置依赖 | Ch13 |
| 规模 | 1966 行 |
| 工业/研究 | 🔬 |
核心知识点:
1. 变参模板 (variadic template):参数包展开
2. 折叠表达式 (C++17):(args + ...) 的四种形式
3. CRTP (Curiously Recurring Template Pattern):静态多态
4. CRTP vs 虚函数:编译期 dispatch vs 运行期 dispatch
5. Eigen 的 CRTP 架构:MatrixBase<Derived>
6. Pinocchio 的 CRTP:JointModelBase<Derived> 访问者模式
7. 编译期多态在 1kHz 控制循环中的性能优势
8. Mixin 模式与 CRTP 的组合
9. 变参模板在日志/序列化中的应用
10. 参数包与完美转发的组合:emplace 系列函数的实现
练习:
1. A 型: 用 CRTP 实现一个 SensorBase<Derived>,支持 IMU 和 LiDAR 两种传感器
2. B 型: 精读 Eigen CwiseBinaryOp 的 CRTP 继承链,画出从 MatrixBase 到具体运算的调用图
3. 思考题: CRTP 和虚函数在代码可维护性上的 trade-off 是什么?何时选哪个?
Ch15 预处理器与宏¶
条件编译、变参宏、宏注册模式、宏与类型安全的边界
| 属性 | 值 |
|---|---|
| 文件 | 10_C++语言核心/150_预处理器与宏.md |
| 周数 | 1.0 周 |
| 前置依赖 | Ch12 |
| 规模 | 1500 行 |
| 工业/研究 | 🏭 |
核心知识点:
1. 条件编译:#if/#ifdef/#ifndef 的工程场景
2. 变参宏 (__VA_ARGS__):日志宏的实现
3. __VA_OPT__ (C++20):空参数的优雅处理
4. 宏注册模式:PCL PCL_INSTANTIATE 的展开逻辑
5. 字符串化 (#) 和标记拼接 (##) 运算符
6. 预定义宏:__FILE__/__LINE__/__func__/__cplusplus
7. 宏与 constexpr 的替换关系
8. 平台特定编译:#ifdef _WIN32/__linux__/__APPLE__
9. 头文件宏保护与 #pragma once 的差异
10. 宏的调试:-E 预处理输出、-dM 宏定义列表
练习:
1. A 型: 实现一个带文件名/行号的日志宏 LOG(level, fmt, ...),用 __VA_OPT__ 处理空参数
2. B 型: 展开 PCL 的 PCL_INSTANTIATE(VoxelGrid, PCL_XYZ_POINT_TYPES) 宏,分析生成的实例化代码
3. 思考题: 为什么 C++ 社区在逐步用 constexpr / consteval 替代宏?哪些场景宏仍不可替代?
Ch16 Concepts 与 Policy-based Design¶
C++20 Concepts、
requires约束、Policy-based Design
| 属性 | 值 |
|---|---|
| 文件 | 10_C++语言核心/160_Concepts与Policy.md |
| 周数 | 1.0 周 |
| 前置依赖 | Ch13, Ch14 |
| 规模 | 1507 行 |
| 工业/研究 | 🔬 |
核心知识点:
1. Concepts 基础语法:concept / requires / 约束从句
2. 标准库 Concepts:std::integral/std::floating_point/std::invocable
3. 自定义 Concepts:LieGroup/Optimizable 接口约束
4. requires 表达式的四种子句:简单/类型/复合/嵌套
5. 约束排序 (subsumption):更特化的 Concept 优先匹配
6. Concepts vs SFINAE:可读性和错误信息的提升
7. Policy-based Design:策略模板参数化类行为
8. 策略模式在 SLAM 中的应用:不同优化策略、不同特征类型
9. Concepts + CRTP 的组合模式
10. Concepts 在库接口设计中的最佳实践
练习:
1. A 型: 定义 LieGroup Concept 并约束 SO(3)/SE(3) 类型
2. B 型: 将一个 SFINAE 约束的函数模板重构为 Concepts 版本,对比编译错误信息
3. 思考题: Concepts 能否完全替代 SFINAE?在什么场景下 SFINAE 仍然必要?
Part 2: 并发与系统编程(20_并发与系统编程/, 8 章 ~8 周)¶
完成本部分后你能做什么: 掌握 C++ 多线程编程、内存模型、并行框架和 CUDA GPU 编程,能为机器人系统设计并发架构和实时数据传递管线。
Ch17 线程管理与互斥同步¶
thread/jthread、锁、条件变量、死锁诊断
| 属性 | 值 |
|---|---|
| 文件 | 20_并发与系统编程/10_线程管理与互斥同步.md |
| 周数 | 1.0 周 |
| 前置依赖 | Part 1 Ch04 (RAII), Ch08 (异常) |
| 规模 | 2685 行 |
| 工业/研究 | 🏭 |
核心知识点:
1. std::thread 构造、join/detach 的生命周期约束
2. std::jthread (C++20):自动 join 和 stop_token 协作取消
3. std::mutex / std::recursive_mutex / std::shared_mutex
4. 锁管理器:lock_guard / unique_lock / scoped_lock (C++17)
5. 条件变量 (condition_variable):生产者-消费者模式
6. 死锁诊断:std::lock 多锁同时获取、锁序约定
7. 传感器缓冲区设计:IMU/图像双缓冲与线程安全队列
8. 线程亲和性 (affinity) 与 CPU 隔离
9. 线程优先级与调度策略:SCHED_FIFO / SCHED_RR
10. SLAM 中的线程模型:跟踪线程、局部地图线程、回环线程
练习:
1. A 型: 实现一个线程安全的 SensorQueue<T>,支持超时等待和批量取出
2. B 型: 用 ThreadSanitizer 诊断一个人为构造的死锁场景
3. 思考题: ORB-SLAM3 的三线程架构为什么选择 unique_lock 而不是 lock_guard?
Ch18 原子操作与内存模型¶
atomic、内存序、无锁基础、发布-订阅边界
| 属性 | 值 |
|---|---|
| 文件 | 20_并发与系统编程/20_原子操作与内存模型.md |
| 周数 | 1.0 周 |
| 前置依赖 | Ch17 |
| 规模 | 2323 行 |
| 工业/研究 | 🏭🔬 |
核心知识点:
1. std::atomic<T> 的基本操作:load/store/exchange/CAS
2. 内存序六级:relaxed → consume → acquire → release → acq_rel → seq_cst
3. acquire-release 语义:建立 happens-before 关系
4. 无锁标志位:atomic<bool> 的停止信号模式
5. 无锁计数器:fetch_add 的引用计数实现
6. 序列锁 (seqlock):读多写少的高频数据共享
7. 双缓冲 (double buffer):最新数据覆盖模式
8. x86 vs ARM 内存模型差异:为什么只在 x86 测试不够
9. std::atomic_ref (C++20):对非 atomic 对象的原子访问
10. SLAM 发布-订阅中的内存可见性保证
练习:
1. A 型: 实现一个 seqlock 保护的 Pose3D 共享读写,验证在 ARM 上的正确性
2. B 型: 用 std::atomic<bool> 实现 TRAC-IK 风格的双线程竞速停止信号
3. 思考题: memory_order_relaxed 在什么场景下安全?在什么场景下会导致数据不一致?
Ch19 并行编程框架¶
OpenMP、TBB、并行 STL、点云并行处理
| 属性 | 值 |
|---|---|
| 文件 | 20_并发与系统编程/30_并行编程框架.md |
| 周数 | 1.0 周 |
| 前置依赖 | Ch17, Ch18 |
| 规模 | 2325 行 |
| 工业/研究 | 🏭🔬 |
核心知识点:
1. OpenMP 基础:#pragma omp parallel for 及其调度策略
2. OpenMP 归约:reduction(+:sum) 的线程安全累加
3. TBB (Threading Building Blocks):tbb::parallel_for / tbb::parallel_reduce
4. TBB 任务流:tbb::flow::graph 的 DAG 并行
5. C++17 并行 STL:std::execution::par / par_unseq
6. 并行容器:tbb::concurrent_hash_map / concurrent_vector
7. 点云并行处理:PCL 滤波/配准的并行加速
8. 负载均衡:静态划分 vs 动态划分 vs work-stealing
9. 并行度分析:Amdahl 定律的实际应用
10. 嵌套并行与线程过度订阅的诊断
练习: 1. A 型: 用 OpenMP 和 TBB 分别实现点云 KNN 搜索,对比加速比 2. B 型: 用 C++17 并行 STL 重写一个串行点云下采样器 3. 思考题: 为什么 OpenMP 在 SLAM 后端优化中比 TBB 更常见?
Ch20 实时约束与高性能数据传递¶
SPSC 队列、双缓冲、预分配、延迟长尾分析
| 属性 | 值 |
|---|---|
| 文件 | 20_并发与系统编程/40_实时约束与高性能数据传递.md |
| 周数 | 1.0 周 |
| 前置依赖 | Ch17, Ch18 |
| 规模 | 1719 行 |
| 工业/研究 | 🏭 |
核心知识点:
1. 实时路径定义:deadline、最坏执行时间 (WCET)
2. SPSC (Single Producer Single Consumer) 无锁队列
3. 双缓冲 / 三缓冲:最新数据覆盖 vs 队列累积
4. 预分配策略:对象池、arena、固定大小缓冲区
5. 延迟长尾分析:P99/P999 延迟测量方法
6. 热路径检查清单:隐藏分配、锁竞争、字符串格式化
7. SCHED_FIFO 与优先级反转 (PI mutex)
8. mlockall 防止页错误
9. 实时日志:非实时线程异步写日志
10. 控制回路中的数据传递模式:传感器 → 估计 → 规划 → 控制
练习:
1. A 型: 实现一个 SPSC 队列,测量 P99 延迟
2. B 型: 对比 std::queue + mutex vs SPSC 在 1kHz 频率下的延迟分布
3. 思考题: 为什么三缓冲比双缓冲更适合"读最新丢旧数据"的场景?
Ch21 内存分配策略与 pmr¶
std::pmr、frame arena、对象池、分配监控
| 属性 | 值 |
|---|---|
| 文件 | 20_并发与系统编程/50_内存分配策略与pmr.md |
| 周数 | 1.0 周 |
| 前置依赖 | Ch20 |
| 规模 | 1513 行 |
| 工业/研究 | 🏭 |
核心知识点:
1. 默认分配器的问题:全局锁、碎片、不确定延迟
2. std::pmr 多态分配器框架
3. monotonic_buffer_resource:帧级 arena 分配
4. pool_resource:固定大小对象池
5. 上游资源链 (upstream resource chaining)
6. 对象池模式:预分配+回收的零 malloc 路径
7. 分配监控:自定义 memory_resource 统计分配计数和峰值
8. Eigen 分配器:aligned_allocator 与 pmr 的交互
9. STL 容器 + pmr:pmr::vector / pmr::string
10. 实时路径的 malloc 检测:LD_PRELOAD 拦截
练习:
1. A 型: 用 monotonic_buffer_resource 实现一个帧级点云处理管线
2. B 型: 编写自定义 memory_resource 记录所有分配,定位一个控制循环中的隐藏 malloc
3. 思考题: 为什么 jemalloc/tcmalloc 不能替代 pmr 解决实时分配问题?
Ch22 缓存优化与数据布局¶
Cache line、AoS/SoA、false sharing、热冷数据分离
| 属性 | 值 |
|---|---|
| 文件 | 20_并发与系统编程/60_缓存优化与数据布局.md |
| 周数 | 1.0 周 |
| 前置依赖 | Ch20, Ch21 |
| 规模 | 1501 行 |
| 工业/研究 | 🏭🔬 |
核心知识点:
1. 缓存层级:L1/L2/L3 的延迟和带宽
2. Cache line (64B):空间局部性的最小单位
3. AoS (Array of Structs) vs SoA (Struct of Arrays)
4. 点云存储:PointXYZI AoS vs 分离 x[]/y[]/z[]/i[]
5. False sharing:多线程写相邻变量导致缓存抖动
6. alignas(64) 和 padding 消除 false sharing
7. 热冷数据分离:把高频访问字段放在同一 cache line
8. 预取 (prefetch):__builtin_prefetch 的适用场景
9. perf stat / cachegrind 分析缓存命中率
10. 矩阵乘法的分块 (tiling) 优化
练习:
1. A 型: 对比 AoS 和 SoA 布局下 10M 个 3D 点的遍历性能
2. B 型: 用 perf stat 测量一段 SLAM 前端代码的 L1 cache miss rate
3. 思考题: 为什么 Eigen 默认列优先存储?这对 SLAM 中的行扫描有什么影响?
Ch23 CUDA 基础与 Thrust¶
CUDA 执行模型、Thrust、stream、event、CMake CUDA
| 属性 | 值 |
|---|---|
| 文件 | 20_并发与系统编程/70_CUDA基础与Thrust.md |
| 周数 | 1.0 周 |
| 前置依赖 | Ch20, Ch22 |
| 规模 | 1584 行 |
| 工业/研究 | 🏭🔬 |
核心知识点:
1. CUDA 执行模型:Grid / Block / Thread 层级
2. 内存层级:Global / Shared / Local / Constant / Texture
3. __global__ / __device__ / __host__ 修饰符
4. CUDA stream:异步执行与多流并行
5. CUDA event:流间同步与计时
6. Thrust 算法库:sort/reduce/transform/scan
7. 统一内存 (Unified Memory):cudaMallocManaged 的使用和限制
8. Pinned memory:cudaMallocHost 加速 H2D/D2H 传输
9. CMake + CUDA:enable_language(CUDA)、编译分离
10. 错误检查:CUDA_CHECK 宏与 cudaGetLastError
练习: 1. A 型: 编写一个 CUDA kernel 做并行矩阵-向量乘法 2. B 型: 用 Thrust 实现一个 GPU 上的点云体素下采样 3. 思考题: 为什么小规模问题 (N<10000) 通常在 CPU 上更快?
Ch24 CUDA 在 SLAM 中的应用¶
GPU 后端接入、CPU/GPU fallback、OpenCV CUDA、Jetson 部署
| 属性 | 值 |
|---|---|
| 文件 | 20_并发与系统编程/80_CUDA在SLAM中的应用.md |
| 周数 | 1.0 周 |
| 前置依赖 | Ch23 |
| 规模 | 2467 行 |
| 工业/研究 | 🏭🔬 |
核心知识点:
1. SLAM 中的 GPU 加速场景:特征提取、立体匹配、BA、点云处理
2. OpenCV CUDA 模块:cv::cuda::GpuMat 与 CPU Mat 的互操作
3. GPU 加速特征提取:CUDA ORB、SuperPoint GPU
4. GPU 稠密匹配:SGBM CUDA、MVS GPU
5. GPU BA 后端:cuBLAS + cuSPARSE 加速 Schur 补求解
6. GPU 点云处理:CUDA KNN、GPU ICP
7. CPU/GPU fallback 策略:运行时检测 GPU 可用性
8. Jetson 部署:TensorRT、DeepStream、低功耗约束
9. CUDA Graphs:减少 kernel launch 开销
10. 多 GPU 与异构计算策略
练习: 1. A 型: 用 OpenCV CUDA 实现 GPU 加速的 FAST 特征检测,对比 CPU 版速度 2. B 型: 在 Jetson Orin 上部署一个 TensorRT 加速的深度估计模型 3. 思考题: 为什么 GPU 加速 BA 在实际 SLAM 系统中不总是带来加速?数据传输开销如何分析?
Part 3: 软件工程(30_软件工程/, 6 章 ~4 周)¶
完成本部分后你能做什么: 掌握机器人 C++ 项目的设计模式、测试调试、日志序列化等工程化能力。前 4 章为入口页,指向
03_SLAM/架构与工程化/的完整内容。
Ch25 设计模式与高级惯用法(入口页)¶
设计模式入口,完整内容见
03_SLAM/架构与工程化/
| 属性 | 值 |
|---|---|
| 文件 | 30_软件工程/10_设计模式与高级惯用法.md |
| 周数 | 0.25 周 (入口导读) |
| 前置依赖 | Part 1 Ch06 (多态), Ch14 (CRTP) |
| 规模 | 42 行 |
| 工业/研究 | 🏭 |
核心知识点:
1. 单例模式:SLAM 中的全局配置管理
2. 工厂模式:特征提取器/匹配器的可插拔创建
3. 观察者模式:传感器数据分发
4. 策略模式:优化器/求解器的运行时切换
5. 详细内容与完整代码示例见 03_SLAM/架构与工程化/Ch29_设计模式
Ch26 多线程架构与混合开发(入口页)¶
多线程架构入口,完整内容见
03_SLAM/架构与工程化/
| 属性 | 值 |
|---|---|
| 文件 | 30_软件工程/20_多线程架构与混合开发.md |
| 周数 | 0.25 周 (入口导读) |
| 前置依赖 | Part 2 Ch17 (线程), Ch20 (实时) |
| 规模 | 25 行 |
| 工业/研究 | 🏭 |
核心知识点:
1. SLAM 系统的典型线程架构
2. C++ / Python 混合开发模式
3. pybind11 / nanobind 绑定实践
4. 详细内容见 03_SLAM/架构与工程化/Ch30_多线程架构
Ch27 ROS2 高级集成(入口页)¶
ROS2 高级集成入口,完整内容见
03_SLAM/架构与工程化/
| 属性 | 值 |
|---|---|
| 文件 | 30_软件工程/30_ROS2高级集成.md |
| 周数 | 0.25 周 (入口导读) |
| 前置依赖 | Part 5 ROS2 基础 |
| 规模 | 38 行 |
| 工业/研究 | 🏭 |
核心知识点:
1. ROS2 节点生命周期管理
2. 自定义消息与服务的设计原则
3. ROS2 与 SLAM/Nav2 的集成模式
4. 详细内容见 03_SLAM/架构与工程化/Ch31_ROS2集成
Ch28 CMake 从入门到工程化(入口页)¶
CMake 工程化入口,完整内容见
03_SLAM/架构与工程化/
| 属性 | 值 |
|---|---|
| 文件 | 30_软件工程/40_CMake从入门到工程化.md |
| 周数 | 0.25 周 (入口导读) |
| 前置依赖 | Part 1 Ch02 (编译模型) |
| 规模 | 49 行 |
| 工业/研究 | 🏭 |
核心知识点:
1. 现代 CMake target-centric 设计
2. PUBLIC/PRIVATE/INTERFACE 依赖传播
3. 安装与导出:install(EXPORT ...) / find_package
4. 详细内容见 03_SLAM/架构与工程化/Ch32_CMake
Ch29 代码质量、测试与调试¶
GTest、GBench、GDB、Sanitizer、clang-tidy、perf、CI
| 属性 | 值 |
|---|---|
| 文件 | 30_软件工程/50_代码质量测试与调试.md |
| 周数 | 1.0 周 |
| 前置依赖 | Part 1 Ch08 (异常), Part 2 Ch17 (线程), Ch20 (实时) |
| 规模 | 1705 行 |
| 工业/研究 | 🏭 |
核心知识点: 1. Google Test (GTest):测试夹具、参数化测试、死亡测试 2. Google Benchmark (GBench):微基准测试框架 3. GDB 调试:断点、watchpoint、多线程调试 4. AddressSanitizer (ASan):堆/栈越界、use-after-free 5. ThreadSanitizer (TSan):数据竞争检测 6. UndefinedBehaviorSanitizer (UBSan):未定义行为检测 7. clang-tidy:静态分析与自动修复 8. perf / flame graph:性能热点分析 9. CI/CD 集成:GitHub Actions + GTest + Sanitizer 10. SLAM 项目的测试策略:数值精度测试、轨迹回归测试
练习: 1. A 型: 为一个 ICP 实现编写 GTest 测试套件,包含数值精度和退化场景 2. B 型: 用 ASan+TSan 扫描一个多线程 SLAM 前端,修复发现的问题 3. 思考题: 为什么微基准测试不能替代端到端性能测试?
Ch30 日志、配置与序列化¶
spdlog、YAML、JSON、Protobuf、FlatBuffers、SQLite、PCD
| 属性 | 值 |
|---|---|
| 文件 | 30_软件工程/60_日志配置与序列化.md |
| 周数 | 2.0 周 |
| 前置依赖 | Ch29 |
| 规模 | 3682 行 |
| 工业/研究 | 🏭 |
核心知识点: 1. spdlog:高性能异步日志库,格式化与 sink 管理 2. YAML-cpp:机器人配置文件解析 3. nlohmann/json:JSON 序列化与反序列化 4. MessagePack:紧凑二进制格式 5. Protobuf:结构化数据序列化与跨语言互操作 6. FlatBuffers:零拷贝反序列化 7. SQLite:嵌入式数据库用于实验管理 8. PCD 文件格式:点云二进制/ASCII 读写 9. 实验可复现性:配置快照 + 数据版本 + 随机种子 10. 日志分级策略:开发/测试/部署的日志级别管理
练习: 1. A 型: 用 spdlog + YAML 配置一个可运行时切换级别的日志系统 2. B 型: 对比 Protobuf 和 FlatBuffers 在序列化/反序列化一个地图帧时的性能 3. 思考题: 为什么地图文件需要包含版本号和坐标系信息?
Part 4: 通用库剖析(40_通用库剖析/, 6 章 ~9 周)¶
完成本部分后你能做什么: 深入掌握 SLAM/机器人系统中最常用的 C++ 库——文件 IO、Eigen 进阶、李群 manif、Ceres 非线性优化、PCL 点云和 OpenCV 视觉——从"会用 API"升级到"理解内部机制"。
Ch31 文件 I/O 与字符串处理¶
ifstream/ofstream、std::filesystem、二进制 IO、fmt格式化
| 属性 | 值 |
|---|---|
| 文件 | 40_通用库剖析/10_文件IO与字符串处理.md |
| 周数 | 1.0 周 |
| 前置依赖 | Part 1 Ch04 (RAII), Ch03 (类设计) |
| 规模 | 2016 行 |
| 工业/研究 | 🏭 |
核心知识点:
1. std::ifstream/std::ofstream:RAII 文件读写
2. std::stringstream:流式解析 g2o/TUM/KITTI 格式
3. std::string 常用操作与 C++17 string_view 零拷贝
4. 二进制 I/O:PCD 点云文件二进制读写
5. fmt 库 / C++20 std::format:高性能格式化输出
6. std::filesystem (C++17):目录遍历、路径拼接、文件检查
7. 数据集格式解析:KITTI/TUM/EuRoC 轨迹文件
8. 字节序 (endianness) 处理:跨平台二进制文件
9. 序列化框架速览:Boost.Serialization/Protobuf/nlohmann-json/cereal
10. evo 工具链:轨迹评估与格式验证
练习:
1. A 型: 编写 KITTI 格式轨迹文件的读写器,用 evo 验证输出正确性
2. B 型: 对比文本格式和二进制格式 PCD 文件的读写速度
3. 思考题: string_view 指向的字符串被销毁后会发生什么?如何防范?
Ch32 Eigen 深入——表达式模板、对齐与 SIMD¶
表达式模板、aliasing、
Map/Ref、SIMD 自动向量化
| 属性 | 值 |
|---|---|
| 文件 | 40_通用库剖析/20_Eigen深入.md |
| 周数 | 1.0 周 |
| 前置依赖 | Part 1 Ch11 (Eigen 基础), Part 4 Ch31 (文件IO) |
| 规模 | 1759 行 |
| 工业/研究 | 🏭🔬 |
核心知识点:
1. 表达式模板 (Expression Templates):为什么 C = A + B + D 只遍历一次
2. aliasing 问题:A = A * B 的数据损坏与 eval()/noalias() 修复
3. Eigen::Map:零拷贝映射外部内存,在 Ceres 代价函数中的用法
4. Eigen::Ref<T>:泛型函数参数,避免临时矩阵
5. 对齐要求:EIGEN_MAKE_ALIGNED_OPERATOR_NEW 与 C++17 over-aligned new
6. SIMD 自动向量化:SSE/AVX 编译选项与 Matrix4f vs Matrix4d
7. 表达式模板陷阱:auto 保存表达式的悬垂引用
8. 惰性求值 vs 立即求值:何时需要 .eval()
9. Block 操作的零拷贝语义
10. Eigen 矩阵的内存布局与缓存友好性
练习:
1. A 型: 构造一个 aliasing bug,用 noalias() 修复并验证性能提升
2. B 型: 用 -march=native 对比 SSE/AVX 下矩阵运算的速度差异
3. 思考题: 为什么 auto v = A.row(0) 不安全但 Eigen::Ref<VectorXd> v = A.row(0) 安全?
Ch33 李群与 manif 库¶
SO(3)/SE(3) 编程、exp/log 映射、Jacobian、IMU 预积分基础
| 属性 | 值 |
|---|---|
| 文件 | 40_通用库剖析/30_李群与manif库.md |
| 周数 | 1.0 周 |
| 前置依赖 | Ch32 (Eigen 深入), 01_数学线性代数 |
| 规模 | 3069 行 |
| 工业/研究 | 🏭🔬 |
核心知识点:
1. 李群 SO(3)/SE(3) 的数学本质
2. exp/log 映射:李代数与李群的互转
3. 群作用 (Group Actions):多坐标系链式变换
4. 切空间、李代数、hat/vee 算子
5. Rodrigues 公式与 SE(3) 指数映射推导
6. Plus/Minus 算子与伴随矩阵
7. 左扰动 vs 右扰动约定
8. 流形 Jacobian 定义与基础 Jacobian 模块
9. 流形上的不确定性与协方差传播
10. 离散积分与 IMU 预积分基础
11. manif 库 API:SO3d/SE3d/log()/exp()/compose()
12. manif 与 Ceres Manifold 接口对接
练习: 1. A 型: 用 manif 实现一个完整的 SE(3) 变换链,验证 Jacobian 与数值微分一致性 2. B 型: 推导 SO(3) 左扰动 Jacobian 并与 manif 计算结果对比 3. 思考题: 为什么 SLAM 优化器更新位姿时用 exp(delta) * T 而不是 T + delta?
Ch34 Ceres Solver——非线性优化与自动微分¶
非线性最小二乘、Jet 双数、Manifold、Schur 补
| 属性 | 值 |
|---|---|
| 文件 | 40_通用库剖析/40_Ceres_Solver.md |
| 周数 | 2.0 周 |
| 前置依赖 | Ch32 (Eigen 深入), Ch33 (李群 manif) |
| 规模 | 1602 行 |
| 工业/研究 | 🏭🔬 |
核心知识点:
1. 非线性最小二乘问题的数学结构
2. Ceres 工作流:Problem → CostFunction → Solver
3. Jet 双数自动微分:精确导数无需手写 Jacobian
4. LossFunction 鲁棒核:Huber/Cauchy 降权异常观测
5. Manifold 接口:四元数/SO(3) 过参数化处理
6. Solver 策略选型:Trust Region / Line Search
7. 线性求解器选型:Dense QR / Sparse Cholesky / Schur
8. Schur 补在 Bundle Adjustment 中的关键作用
9. 协方差提取:Covariance::Compute 评估解的不确定性
10. Ceres 与 GTSAM/g2o 的对比:适用场景分析
练习: 1. A 型: 用 Ceres 实现一个完整的 BA 问题,用 Schur 补加速求解 2. B 型: 对比 Jet 自动微分和手写 Jacobian 的精度与性能 3. 思考题: Ceres 的 Manifold 接口和 GTSAM 的 traits 系统解决的是同一个问题吗?
Ch35 PCL 点云库深度剖析¶
点类型系统、滤波器、KD-Tree、ICP/GICP/NDT
| 属性 | 值 |
|---|---|
| 文件 | 40_通用库剖析/50_PCL点云库.md |
| 周数 | 2.0 周 |
| 前置依赖 | Ch32 (Eigen 深入) |
| 规模 | 2085 行 |
| 工业/研究 | 🏭🔬 |
核心知识点:
1. PCL 模块化架构:filters/features/registration/segmentation/io
2. 点类型系统:PointXYZ/PointXYZI/PointXYZRGBNormal/自定义点类型
3. 对齐分配器:pcl::make_shared 与 aligned_allocator
4. 滤波器全家族:VoxelGrid/PassThrough/StatisticalOutlier/RadiusOutlier
5. KD-Tree 近邻搜索:FLANN 后端与 k-NN/radius search
6. ikd-Tree / iVox:现代 LiDAR SLAM 的替代数据结构
7. ICP 配准:Point-to-Point/Point-to-Plane 的迭代流程
8. GICP (Generalized ICP):概率化配准
9. NDT (Normal Distributions Transform):体素化概率配准
10. PCL 与 ROS2:sensor_msgs::PointCloud2 的高效互转
练习:
1. A 型: 实现完整的 LiDAR 点云处理管线:下采样 → 去噪 → 法线估计 → ICP 配准
2. B 型: 对比 ICP/GICP/NDT 在 KITTI 数据集上的配准精度和速度
3. 思考题: PCL 的 pcl::PointCloud<T> 使用 std::vector 存储,为什么仍需要 aligned_allocator?
Ch36 OpenCV 在 SLAM 中的深度应用¶
cv::Mat内存模型、特征检测/跟踪、多视图几何
| 属性 | 值 |
|---|---|
| 文件 | 40_通用库剖析/60_OpenCV深度应用.md |
| 周数 | 2.0 周 |
| 前置依赖 | Ch32 (Eigen 深入) |
| 规模 | 2243 行 |
| 工业/研究 | 🏭🔬 |
核心知识点:
1. cv::Mat 内存模型:连续存储、ROI、引用计数
2. cv::Mat 与 Eigen 零拷贝互转
3. 图像预处理:CLAHE、高斯模糊、金字塔构建
4. FAST 角点检测:ORB-SLAM3 前端实现
5. Shi-Tomasi 角点检测:VINS-Mono 前端实现
6. KLT 稀疏光流跟踪:calcOpticalFlowPyrLK 与 setMask 均匀化
7. 特征匹配:ORB/SIFT 描述子 + BFMatcher/FLANN
8. 本质矩阵/基础矩阵分解:findEssentialMat/findFundamentalMat
9. PnP 求解:solvePnPRansac 的 RANSAC 参数调优
10. 三角化:triangulatePoints 与深度估计
练习:
1. A 型: 复现 VINS-Mono 风格的稀疏光流跟踪前端
2. B 型: 用 findEssentialMat + triangulatePoints 实现一个最小化双目 VO
3. 思考题: 为什么 ORB-SLAM3 用 FAST 而 VINS-Mono 用 Shi-Tomasi?各自的 trade-off 是什么?
Part 5: ROS2 工程化(50_ROS2工程化/, 5 章 ~5 周)¶
完成本部分后你能做什么: 掌握 ROS2 的设计理念、构建系统、仿真生态、硬件接入和调试工具链,能把算法接入完整的机器人系统。
Ch37 设计哲学与架构演进¶
ROS2 设计动机、DDS/RMW、版本生态
| 属性 | 值 |
|---|---|
| 文件 | 50_ROS2工程化/10_设计哲学与架构演进.md |
| 周数 | 0.5 周 |
| 前置依赖 | Part 1 基础 C++ |
| 规模 | 486 行 |
| 工业/研究 | 🏭 |
核心知识点:
1. ROS1 → ROS2 的设计动机:实时性、安全性、多平台
2. DDS 通信中间件:RTPS 协议、QoS 策略
3. RMW (ROS Middleware) 抽象层
4. ROS2 版本生态:Humble → Iron → Jazzy → Kilted
5. 节点 / 话题 / 服务 / 动作的核心概念
6. ROS2 在工业和研究中的采用现状
7. 与 ROS1 的桥接 (ros1_bridge)
8. ROS2 的实时能力边界
练习: 1. A 型: 搭建 ROS2 Kilted 开发环境,运行 turtlesim 基础教程 2. 思考题: ROS2 选择 DDS 而非自研通信层的技术和商业原因是什么?
Ch38 构建系统与机器人建模¶
colcon、ament、pluginlib、rosdep、URDF/Xacro、Docker
| 属性 | 值 |
|---|---|
| 文件 | 50_ROS2工程化/20_构建系统与机器人建模.md |
| 周数 | 1.5 周 |
| 前置依赖 | Ch37, Part 1 Ch02 (编译模型) |
| 规模 | 1672 行 |
| 工业/研究 | 🏭 |
核心知识点:
1. colcon 构建系统:workspace / overlay / underlay
2. ament_cmake / ament_python 包结构
3. pluginlib:运行时插件加载机制
4. rosdep:依赖声明与自动安装
5. URDF 建模:link/joint/transmission 语义
6. Xacro 宏系统:参数化机器人描述
7. robot_state_publisher 与 joint_state_publisher
8. Docker 化 ROS2 开发环境
9. 多包工作区管理最佳实践
10. package.xml 依赖声明与版本控制
练习: 1. A 型: 创建一个包含 C++ 节点和 Python 节点的 ROS2 多包工作区 2. B 型: 用 Xacro 写一个参数化的 2-DOF 机械臂 URDF 3. 思考题: 为什么 ROS2 不直接用 CMake 而要用 colcon + ament 封装?
Ch39 SLAM 导航与仿真生态¶
Nav2、SLAM Toolbox、RTABMap、Gazebo、RViz2
| 属性 | 值 |
|---|---|
| 文件 | 50_ROS2工程化/30_SLAM导航与仿真生态.md |
| 周数 | 1.0 周 |
| 前置依赖 | Ch38 |
| 规模 | 968 行 |
| 工业/研究 | 🏭🔬 |
核心知识点:
1. Nav2 (Navigation2):行为树导航框架
2. SLAM Toolbox:2D 激光 SLAM
3. RTABMap:RGB-D / 激光多传感器 SLAM
4. Gazebo Ionic:物理仿真与传感器仿真
5. MuJoCo + ROS2:通过 mujoco_ros2 桥接
6. RViz2:3D 可视化与交互
7. Foxglove Studio:Web 可视化与远程调试
8. 仿真到真机的数据流:use_sim_time 参数
9. TF2 坐标变换树的维护
10. 导航参数调优:costmap / planner / controller
练习: 1. A 型: 在 Gazebo 中搭建一个带 LiDAR 的移动机器人,用 SLAM Toolbox 建图 2. B 型: 配置 Nav2 实现自主导航并调优避障参数 3. 思考题: 为什么 Gazebo 的物理仿真精度在接触密集的操作任务中不够?MuJoCo 如何改善?
Ch40 硬件集成与 RL 部署¶
micro-ROS、嵌入式 GPU、ros2_control、RL 部署
| 属性 | 值 |
|---|---|
| 文件 | 50_ROS2工程化/40_硬件集成与RL部署.md |
| 周数 | 1.0 周 |
| 前置依赖 | Ch38, Part 2 Ch17 (线程) |
| 规模 | 343 行 |
| 工业/研究 | 🏭🔬 |
核心知识点:
1. ros2_control 框架:HardwareInterface / Controller / ControllerManager
2. 硬件接口设计:传感器/执行器的 read()/write() 抽象
3. micro-ROS:嵌入式 MCU 的 ROS2 支持
4. Jetson 部署:TensorRT + ROS2 推理节点
5. RL 策略部署:PyTorch / ONNX → C++ 推理
6. Isaac Lab / Isaac Gym 与 ROS2 集成
7. 相机驱动:RealSense / ZED 的 ROS2 驱动
8. IMU 接入与时间同步
9. EtherCAT / CAN 工业总线集成
10. 安全与看门狗机制
练习: 1. A 型: 用 ros2_control 配置一个模拟 2-DOF 关节的 position controller 2. B 型: 在 Jetson 上部署一个 ONNX 模型的 ROS2 推理节点 3. 思考题: micro-ROS 与标准 ROS2 在 QoS 和可靠性上的差异如何影响控制系统?
Ch41 CLI 调试与性能工具¶
ROS2 CLI、rosbag2、QoS、TF、trace、调试工具
| 属性 | 值 |
|---|---|
| 文件 | 50_ROS2工程化/50_CLI调试与性能工具.md |
| 周数 | 1.0 周 |
| 前置依赖 | Ch38, Ch39 |
| 规模 | 680 行 |
| 工业/研究 | 🏭 |
核心知识点:
1. ROS2 CLI 工具:ros2 topic/ros2 service/ros2 param
2. rosbag2 / mcap:数据录制与回放
3. QoS 调试:ros2 topic info -v 查看 QoS 匹配
4. TF2 调试:tf2_echo/view_frames 坐标变换链
5. ros2 doctor:系统健康检查
6. LTTng / ros2_tracing:分布式追踪
7. PlotJuggler:实时数据可视化
8. rqt 工具集:节点图、话题监控、参数调整
9. 内存与 CPU 分析:heaptrack/perf 与 ROS2 节点
10. 网络调试:DDS 发现问题诊断
练习:
1. A 型: 用 rosbag2 录制一段 SLAM 数据,用 PlotJuggler 可视化 IMU 和位姿
2. B 型: 用 ros2_tracing 分析一个导航系统的回调延迟分布
3. 思考题: 为什么 ROS2 默认的 DDS 发现机制在大型网络中可能导致问题?如何用 FASTRTPS_DEFAULT_PROFILES_FILE 解决?
Part 6: 规控公共工程基础(60_规控公共工程基础/, 8 章+导读 ~8 周)¶
完成本部分后你能做什么: 掌握从 SLAM 工程迁移到规控(机械臂/足式/无人机)所需的公共 C++ 工程能力:数值优化库、实时 Linux、无锁并发、ROS2 架构、Eigen 高级用法、GPU 加速、构建系统和测试调试。 适用对象: 完成 Part 1-5(或等效经验)后,准备切入规控方向的工程师。
导读:规控公共基础与体系架构¶
五大源文件合并的顶层架构设计与知识地图
| 属性 | 值 |
|---|---|
| 文件 | 60_规控公共工程基础/00_导读.md |
| 规模 | 21 行 (导读入口) |
| 定位 | 顶层架构说明,五大源文件的关系与阅读建议 |
参考设计文档 (规划与调研材料):
- P1_方向分类与公共基础层设计方案.md (457 行) — 四大方向划分与 Part 0 设计
- P2_30章扩展方案.md (322 行) — 课程蓝图
- P3-00_概述与学习路径映射.md (176 行) — 路径映射
- P4_C++库生态全景调研.md (264 行) — 库工具箱清单
- P5_经典论文脉络全景.md (432 行) — 110+ 篇论文脉络
- P6_总结.md (10 行) — 总结
Ch42 数值优化库的 C++ 集成生态¶
从 Ceres 最小二乘迁移到 QP/NLP/代码生成的规控优化生态
| 属性 | 值 |
|---|---|
| 文件 | 60_规控公共工程基础/10_数值优化库集成.md |
| 周数 | 1.0 周 |
| 前置依赖 | Part 4 Ch34 (Ceres), Ch32 (Eigen 深入) |
| 规模 | 1107 行 |
| 工业/研究 | 🏭🔬 |
核心知识点: 1. 从最小二乘到带约束优化:SLAM vs 规控的问题差异 2. QP 标准形式:Hessian、gradient、约束矩阵、稀疏结构 3. NLP 标准形式:KKT 条件、SQP / interior-point 4. OSQP:ADMM 算法、warm start、稀疏接口 5. ProxQP:近端 QP 求解器、Pinocchio 推荐后端 6. qpOASES:在线主动集、MPC 热启动 7. HPIPM:高性能 MPC 求解器、Riccati 递归 8. Ipopt:大规模 NLP、稀疏 Hessian、MUMPS 线性求解 9. CasADi:符号化建模与代码生成 10. acados:实时 MPC 框架、Heron SQP 11. 求解器适配层设计:数据所有权边界 12. warm start 策略与失败诊断
练习: 1. A 型: 用 OSQP / ProxQP 实现一个带关节限位的 IK-QP 2. B 型: 用 CasADi 建模一个 7-DOF 避障轨迹优化问题 3. 思考题: warm start 何时帮助收敛、何时反而有害?
Ch43 实时 Linux 与实时安全 C++ 编程¶
PREEMPT_RT、cyclictest、无堆分配、非实时日志
| 属性 | 值 |
|---|---|
| 文件 | 60_规控公共工程基础/20_实时Linux与安全编程.md |
| 周数 | 1.0 周 |
| 前置依赖 | Part 2 Ch17 (线程), Ch20 (实时约束) |
| 规模 | 1068 行 |
| 工业/研究 | 🏭 |
核心知识点:
1. 实时性定义:deadline 保证 vs 平均快速
2. PREEMPT_RT 内核补丁:解决了什么、没解决什么
3. SCHED_FIFO / SCHED_DEADLINE 调度策略
4. mlockall():锁定内存防止页错误
5. cyclictest:实时性能基准测试
6. 实时路径禁区:动态分配、异常、字符串、I/O
7. 预分配与对象池在实时循环中的应用
8. 非实时日志线程:异步落盘设计
9. watchdog 与安全降级策略
10. PREEMPT_RT + ros2_control 的 1kHz 控制实践
练习:
1. A 型: 在 PREEMPT_RT 内核上运行 cyclictest,对比默认内核的最坏延迟
2. B 型: 编写一个 1kHz 实时循环,用 LD_PRELOAD 检测其中的隐藏 malloc
3. 思考题: 为什么 SCHED_DEADLINE 比 SCHED_FIFO 更适合多实时任务系统?
Ch44 无锁数据结构与并发原语¶
acquire/release、双缓冲/三缓冲、SPSC 队列、seqlock
| 属性 | 值 |
|---|---|
| 文件 | 60_规控公共工程基础/30_无锁数据结构.md |
| 周数 | 1.0 周 |
| 前置依赖 | Part 2 Ch18 (原子), Ch20 (实时约束) |
| 规模 | 1506 行 |
| 工业/研究 | 🏭 |
核心知识点: 1. 并发问题三层分类:数据竞争 / 逻辑竞争 / 活性问题 2. C++ 内存序 acquire/release 语义详解 3. 双缓冲:写者更新、读者读最新 4. 三缓冲:写者不阻塞、读者无撕裂 5. SPSC 无锁队列:环形缓冲区 + 缓存行隔离 6. seqlock:读多写少的高频位姿共享 7. "读最新" vs "读每一条" 的需求区分 8. 控制/估计/规划/日志四线程数据交换设计 9. 压力测试:多核/ARM 平台的正确性验证 10. 无锁结构的可解释等待边界
练习:
1. A 型: 实现一个 seqlock 保护的 RobotState 共享,压力测试 ARM 正确性
2. B 型: 实现 SPSC 队列并对比 std::queue + mutex 的延迟分布
3. 思考题: 为什么无锁队列在 x86 上"碰巧正确"但在 ARM 上会出错?
Ch45 ROS2 架构与组件化设计¶
组件节点、lifecycle、executor、callback group、DDS 选型
| 属性 | 值 |
|---|---|
| 文件 | 60_规控公共工程基础/40_ROS2架构与组件化.md |
| 周数 | 1.0 周 |
| 前置依赖 | Part 5 Ch37-Ch38, Part 2 Ch17 |
| 规模 | 1339 行 |
| 工业/研究 | 🏭 |
核心知识点:
1. ROS2 节点三种范式:普通节点 / 组件节点 / lifecycle 节点
2. 何时必须用组件和生命周期管理
3. Executor 与 callback group 对并发行为的影响
4. SingleThreadedExecutor 中同步服务调用的死锁风险
5. 进程内通信 (intra-process comm) 的零拷贝条件
6. QoS 对控制消息的影响:可靠性 / 历史深度
7. 大消息传输策略:共享内存 / iceoryx
8. ros2_control 的 executor 集成
9. DDS/RMW 实现选型:CycloneDDS / FastDDS / iceoryx
10. 参数服务器在实时循环中的查询策略
练习:
1. A 型: 将一个单节点 SLAM 原型拆成组件化 + lifecycle 架构
2. B 型: 对比 MultiThreadedExecutor + MutuallyExclusiveCallbackGroup 与串行执行的延迟
3. 思考题: 为什么 iceoryx 的零拷贝不能用于所有消息类型?
Ch46 Eigen 库的高级用法专题¶
表达式模板进阶、
auto悬垂、零拷贝接口、稀疏矩阵、malloc 检测
| 属性 | 值 |
|---|---|
| 文件 | 60_规控公共工程基础/50_Eigen高级用法.md |
| 周数 | 1.0 周 |
| 前置依赖 | Part 4 Ch32 (Eigen 深入) |
| 规模 | 1547 行 |
| 工业/研究 | 🏭🔬 |
核心知识点:
1. 表达式模板延迟求值的深层理解
2. auto 保存 Eigen 表达式的生命周期陷阱
3. Map 和 Ref 的所有权语义:何时不拥有数据
4. 稀疏矩阵构造:SparseMatrix 三元组插入与压缩列格式
5. Eigen 对齐与 SIMD 编译边界
6. 固定大小可向量化类型与 std::vector 的对齐问题
7. 模板化 Scalar 支持自动微分 (CppAD/Jet)
8. 实时路径 malloc 检测:Eigen 动态分配的识别
9. Block 操作的零拷贝细节
10. Eigen 在控制回路中的小矩阵高频计算优化
练习:
1. A 型: 编写自定义 Eigen 分配器,在控制循环中检测所有堆分配
2. B 型: 用 Eigen::SparseMatrix 构建一个 MPC 问题的约束矩阵
3. 思考题: Eigen::Matrix<CppAD::AD<double>, 3, 1> 如何让同一份代码同时支持数值和自动微分?
Ch47 GPU 加速与 CUDA 在机器人中的应用¶
GPU 适用性判断、stream/同步、TensorRT、cuRobo
| 属性 | 值 |
|---|---|
| 文件 | 60_规控公共工程基础/60_GPU加速应用.md |
| 周数 | 1.0 周 |
| 前置依赖 | Part 2 Ch23-Ch24 (CUDA), Part 2 Ch22 (缓存布局) |
| 规模 | 1366 行 |
| 工业/研究 | 🏭🔬 |
核心知识点:
1. GPU 适用性判断:吞吐 vs 延迟、批量度阈值
2. PCIe 传输成本:何时 GPU 加速反而更慢
3. CUDA stream 在机器人管线中的多流设计
4. 显式同步 vs 隐式同步的延迟影响
5. CUDA Graphs:减少 launch 开销
6. Thrust 在机器人中的应用:排序、扫描、归约
7. TensorRT:推理部署优化
8. cuRobo:GPU 并行碰撞检查与运动规划
9. GPU 与实时控制的边界:cudaDeviceSynchronize 在控制循环中的风险
10. GPU fallback 策略:GPU 不可用时的降级路径
练习: 1. A 型: 在 CUDA 中实现一个批量矩阵乘法,对比 CPU Eigen 的吞吐 2. B 型: 用 TensorRT 部署一个深度估计模型并测量推理延迟 3. 思考题: 为什么 cuRobo 能在 GPU 上实现毫秒级运动规划,而传统 OMPL 在 CPU 上需要秒级?
Ch48 构建系统与大型 C++ 项目组织¶
现代 CMake、target-centric 设计、colcon + ament、CI
| 属性 | 值 |
|---|---|
| 文件 | 60_规控公共工程基础/70_构建系统与项目组织.md |
| 周数 | 1.0 周 |
| 前置依赖 | Part 1 Ch02 (编译模型), Part 5 Ch38 (ROS2 构建) |
| 规模 | 1418 行 |
| 工业/研究 | 🏭 |
核心知识点:
1. 现代 CMake target-centric 设计:告别全局变量
2. PUBLIC/PRIVATE/INTERFACE 依赖传播语义
3. 安装与导出:install(EXPORT ...)/find_package/Config.cmake
4. 多包 colcon 工作区的包边界设计
5. ament_cmake_auto:自动化包配置简化
6. 头文件边界:何时暴露 Eigen 类型为 PUBLIC 依赖
7. vcpkg / conan 与 rosdep 的分工
8. Docker + CI:自动化构建与测试
9. 大型项目的模块化拆分策略
10. ABI 兼容性与版本控制
练习:
1. A 型: 为一个机器人控制库编写 modern CMake 安装脚本,支持 find_package
2. B 型: 在 GitHub Actions 中配置 colcon build + GTest + Sanitizer 的 CI 管线
3. 思考题: 为什么暴露 Eigen 类型的库必须将 Eigen 设为 PUBLIC 依赖?ABI 兼容性如何受影响?
Ch49 测试与调试基础设施¶
测试金字塔、sanitizer、perf、Tracy、rosbag 回归测试
| 属性 | 值 |
|---|---|
| 文件 | 60_规控公共工程基础/80_测试与调试基础设施.md |
| 周数 | 1.0 周 |
| 前置依赖 | Part 3 Ch29 (测试调试), Part 2 Ch17 (线程) |
| 规模 | 1516 行 |
| 工业/研究 | 🏭 |
核心知识点: 1. 测试金字塔:函数级 → 模块级 → 系统级 2. 控制器单元测试:输入-输出不变量验证 3. ROS2 节点集成测试:launch_testing 框架 4. rosbag/mcap 回归测试:录制-回放验证 5. ASan / TSan / UBSan 在规控代码中的应用 6. perf / flame graph:性能热点分析 7. Tracy Profiler:帧级可视化性能分析 8. Google Benchmark:微基准测试 9. PlotJuggler:控制数据实时可视化 10. 调试结果到自动化检查的转化:防止同类问题复发
练习: 1. A 型: 为一个 PID 控制器编写 GTest 测试套件,覆盖阶跃响应和饱和边界 2. B 型: 用 Tracy 对一个 1kHz 控制循环做帧级性能分析,定位最慢帧 3. 思考题: 为什么上机调试成本最高?测试金字塔如何降低总调试时间?
学习路径建议¶
最小可行路径(~18 周)¶
如果目标是尽快看懂现代 SLAM/机器人 C++ 代码:
Ch01 类型系统 → Ch02 编译模型 → Ch03 类设计 → Ch04 RAII → Ch05 移动语义
→ Ch10 Lambda → Ch11 Eigen基础 → Ch17 线程管理 → Ch20 实时约束
→ Ch31 文件IO → Ch32 Eigen深入 → Ch33 李群manif → Ch34 Ceres
→ Ch29 测试调试 → Ch38 ROS2构建
深入工程路径(在最小路径基础上 +~15 周)¶
如果目标是独立维护中型机器人软件:
Ch06 多态 → Ch07 类型转换 → Ch08 异常安全 → Ch09 运算符
→ Ch12 函数模板 → Ch13 SFINAE → Ch14 CRTP → Ch15 宏 → Ch16 Concepts
→ Ch18 原子内存模型 → Ch19 并行框架 → Ch21 pmr → Ch22 缓存优化
→ Ch35 PCL → Ch36 OpenCV → Ch30 日志序列化
规控专项路径(在最小路径基础上 +~8 周)¶
如果目标是进入机械臂/足式/无人机规控方向:
Ch42 数值优化库 → Ch43 实时Linux → Ch44 无锁并发 → Ch45 ROS2架构
→ Ch46 Eigen高级 → Ch47 GPU加速 → Ch48 构建系统 → Ch49 测试调试
性能专项路径(~12 周)¶
如果目标是优化 SLAM 前端或点云处理性能:
Ch11 Eigen基础 → Ch17 线程 → Ch18 原子 → Ch19 并行框架
→ Ch20 实时约束 → Ch21 pmr → Ch22 缓存优化
→ Ch23 CUDA基础 → Ch24 CUDA应用
→ Ch32 Eigen深入 → Ch35 PCL → Ch47 GPU加速
ROS2 实战路径(~10 周)¶
如果目标是把算法接入机器人系统:
Ch02 编译模型 → Ch04 RAII → Ch08 异常 → Ch17 线程 → Ch20 实时
→ Ch29 测试调试 → Ch30 日志序列化
→ Ch37 ROS2设计哲学 → Ch38 构建与建模 → Ch39 仿真
→ Ch40 硬件集成 → Ch41 CLI调试 → Ch45 ROS2架构
交叉引用地图¶
Part 1 → 其他方向¶
| Part 1 章节 | 下游使用者 | 关键衔接 |
|---|---|---|
| Ch11 Eigen 基础 | Part 4 全部, Part 6 Ch46, 03_SLAM, 05_机械臂 | 所有方向的数学计算基础 |
| Ch14 CRTP | 05_机械臂/M01 Pinocchio | Pinocchio CRTP 访问者模式 |
| Ch06 多态 | 05_机械臂/M02 DART/KDL | 运行期多态对比编译期多态 |
| Ch04 RAII | Part 2 全部, Part 3 全部 | 资源管理贯穿所有工程章节 |
| Ch08 异常 | Part 5 ROS2, 03_SLAM/架构与工程化 | 跨模块错误处理策略 |
Part 2 → 其他方向¶
| Part 2 章节 | 下游使用者 | 关键衔接 |
|---|---|---|
| Ch17 线程管理 | Part 5, Part 6, 05_机械臂/M03 TRAC-IK | 双线程竞速 IK 求解 |
| Ch20 实时约束 | Part 6 Ch43, 05_机械臂/M11 实时C++ | 1kHz 控制循环设计 |
| Ch23-24 CUDA | Part 6 Ch47, 05_机械臂/M09 GPU规划 | cuRobo GPU 碰撞检查 |
| Ch21 pmr | Part 6 Ch43, 05_机械臂/M11 | 实时路径无堆分配 |
Part 4 → 其他方向¶
| Part 4 章节 | 下游使用者 | 关键衔接 |
|---|---|---|
| Ch33 李群 manif | 03_SLAM/BA/VIO, 05_机械臂/Pinocchio | Manifold 优化接口 |
| Ch34 Ceres | 03_SLAM/后端优化, Part 6 Ch42 | 从最小二乘迁移到 QP/NLP |
| Ch35 PCL | 03_SLAM/LiDAR, 04_移动/导航 | 点云处理全栈 |
| Ch36 OpenCV | 03_SLAM/视觉前端 | 特征提取与多视图几何 |
Part 5 → 其他方向¶
| Part 5 章节 | 下游使用者 | 关键衔接 |
|---|---|---|
| Ch38 构建与建模 | 05_机械臂/P01 URDF, 04_移动/Nav2 | URDF/Xacro 机器人建模 |
| Ch39 仿真生态 | 05_机械臂/P02 sim-to-real, 06_具身/RL | Gazebo/MuJoCo 仿真 |
| Ch40 硬件集成 | 05_机械臂/M12 ros2_control | 硬件接口与控制器框架 |
Part 6 → 其他方向¶
| Part 6 章节 | 下游使用者 | 关键衔接 |
|---|---|---|
| Ch42 数值优化 | 05_机械臂/M05-M06, 05_足式/MPC | QP/NLP 求解器选型 |
| Ch43 实时 Linux | 05_机械臂/M11-M12, 05_足式/实时控制 | PREEMPT_RT + 1kHz 控制 |
| Ch44 无锁并发 | 05_足式/状态估计-控制通信 | 控制线程间数据交换 |
| Ch45 ROS2 架构 | 05_机械臂/M14 MoveIt2, 04_移动/Nav2 | 组件化系统设计 |
| Ch47 GPU 加速 | 05_机械臂/M09 cuRobo, 06_具身/RL训练 | GPU 并行碰撞+规划 |
与 03_SLAM/ 的关系¶
02_C++基础与进阶/ 的 Part 3 软件工程中 Ch25-Ch28 是入口页。它们对应的完整内容位于:
学习时可以先读 02_C++基础与进阶/30_软件工程/ 的入口页明确问题地图,再进入 03_SLAM/架构与工程化/ 读完整章节。
与 05_运动控制/ 的关系¶
02_C++基础与进阶/ 的 Part 6 规控公共基础是进入 05_运动控制/ 各子方向的桥梁:
- 机械臂方向 (05_运动控制/20_机械臂/): 依赖 Ch42 (数值优化) → M05 QP/NLP, Ch43 (实时) → M11 实时C++, Ch14 (CRTP) → M01 Pinocchio
- 足式方向 (05_运动控制/30_足式/): 依赖 Ch42 (数值优化) → MPC, Ch43 (实时) → 实时控制, Ch44 (无锁) → 多线程通信
- 无人机方向: 依赖 Ch42 (数值优化) → MPC, Ch43 (实时) → 飞控实时, Ch47 (GPU) → 视觉处理
学习产出¶
完成本目录后,学习者不应只记住语法点,而应能回答这些工程问题:
- 一个类是否应该可拷贝、可移动,还是只允许独占所有权?
- 一个回调捕获对象时,生命周期由谁保证?
- 一个异常应该在库内部抛出、转换成错误码,还是在 ROS2 节点边界记录并降级?
- 一个并发队列是否真的保护了读写双方的数据可见性?
- 一个热路径是否包含隐藏分配、锁竞争或字符串格式化?
- 一个数据结构为什么适合 AoS 或 SoA?
- 一个 GPU 加速后端不可用时,系统应该失败、降级还是切换策略?
- 一个测试是否验证了算法不变量,而不只是验证某组样例输出?
- 一条日志是否包含足够上下文,让实验可以复现?
- 一个地图文件是否能被未来版本读取,并解释它使用的坐标系、时间基准和配置快照?
- 一个数值优化问题应该用 Ceres 的最小二乘还是 OSQP 的 QP?
- 一个实时控制循环中是否有隐藏的动态分配或系统调用?
- 一个无锁数据结构在 ARM 平台上是否仍然正确?
- 一个 ROS2 系统的 executor 和 callback group 配置是否会导致死锁?
- 一个 CMake 项目的依赖传播是否会在下游产生意外的头文件污染?
这些问题连接了所有章节,也是从"会写 C++"走向"能维护机器人系统"的分界线。