从零理解 ORB-SLAM3(二):系统全景、执行上下文与核心数据结构
本卷建立源码地图。先知道对象是谁、数据向哪里走、谁在哪个执行上下文中修改数据再进入几千行 Tracking 和 Optimizer 才不会迷路。1.ORB-SLAM3 的四项关键扩展视觉惯性 MAP 系统把视觉重投影与 IMU 约束紧耦合惯性初始化也采用概率一致的优化高召回地点识别候选首先做几何验证再检查局部共视一致性减少等待连续三帧词袋一致性造成的漏检Atlas多地图跟踪长时间失败时可创建新地图以后发现公共区域再融合抽象相机模型Tracking 和优化器通过投影/反投影/Jacobian 接口支持针孔和鱼眼。论文还用短期、中期、长期数据关联解释精度来源。源码中的连续帧匹配、局部地图投影匹配、重定位/闭环/融合分别对应这三个层次。*图ORB-SLAM3 总体架构。Atlas 是多地图状态中心三条算法通道围绕它协作。*2.仓库与六种Sensor模式主库重点目录目录作用include/类声明、公开接口、成员变量src/主流程和算法实现include/CameraModels/GeometricCamera、Pinhole、KannalaBrandt8Examples/数据集和相机入口、时间戳读取、输入同步Thirdparty/DBoW2词袋地点识别Thirdparty/g2o图优化基础框架Thirdparty/Sophus李群表示和运算System::eSensor定义六种输入组合MONOCULAR, STEREO, RGBD, IMU_MONOCULAR, IMU_STEREO, IMU_RGBDSensor 决定帧构造方式、是否接收 IMU、尺度是否固定、是否执行惯性初始化等。相机模型则决定像点投影方式鱼眼不是第七种 Sensor。3. 输入接口与配置System对外提供TrackMonocular(image, timestamp, imuMeasurements, filename)TrackStereo(left, right, timestamp, imuMeasurements, filename)TrackRGBD(image, depth, timestamp, imuMeasurements, filename)。调用者负责按时间顺序送入图像。视觉惯性示例还需要从 IMU 流中取出落在相邻图像时间区间内的测量并传给相应Track*()。双目图像必须同步RGB-D 深度必须与彩色图注册。配置读取涉及两条兼容路径Settings解析新格式部分旧配置仍通过cv::FileStorage直接读取。配置不只是内参还包括帧率、颜色顺序、ORB 参数、双目基线/深度阈值、IMU 噪声/频率、相机—IMU 外参、Viewer 参数和可选loopClosing。配置错误的影响链焦距/主点错误 → 投影和重投影雅可比错误双目基线或深度尺度错误 → 地图整体尺度错误Tbc方向错误 → 视觉与惯性预测互相冲突IMU 噪声单位错误 → 信息矩阵权重错误时间戳不同步 → 预积分覆盖错误时间段。4. System 构造和模块连接构造函数完整签名包含词典、配置、Sensor、Viewer 开关、初始帧编号和序列名。核心顺序是保存 Sensor读取配置加载 ORB 词典创建KeyFrameDatabase创建Atlas必要时加载已保存 Atlas向 Atlas 标记是否包含惯性传感器创建FrameDrawer、MapDrawer在调用线程中创建Tracking创建LocalMapping并启动其Run()线程创建LoopClosing并启动其Run()线程互相注入 Tracker、LocalMapper、LoopCloser 指针可选地创建 Viewer 线程。重要事实源码注释明确说明 Tracking “live in the main thread of execution”。所以“Tracking 线程”是算法语境中的执行通道不是System内部新建的std::thread。*图Tracking、Local Mapping、Loop Closing、Viewer 和 Global BA 的执行关系。*应用/Example 调用线程 └─ System::Track*() └─ Tracking::GrabImage*() └─ Tracking::Track() 后台线程 A: LocalMapping::Run() 后台线程 B: LoopClosing::Run() 可选线程 C: Viewer::Run() 条件线程 D: LoopClosing::RunGlobalBundleAdjustment()5. Track*() 到 Tracking::Track()以TrackMonocular()为例接口首先检查 Sensor 是否兼容再响应以下控制请求激活/关闭纯定位模式重置当前活跃地图或全部系统。随后若有 IMU 测量调用GrabImuData()放入 Tracking 队列再调用GrabImageMonocular()。后者处理图像缩放/灰度、构造Frame最终进入Track()。Track()是状态机中枢。主要状态包括NO_IMAGES_YET尚无图像NOT_INITIALIZED等待建立初始地图OK正常跟踪RECENTLY_LOST短时丢失惯性模式可能继续预测并尝试恢复LOST恢复窗口耗尽需要重定位、重置或创建新地图。状态并非只由“匹配点数量”决定还受地图规模、初始化阶段、IMU 是否完成初始化、距上次重定位帧数和时间戳连续性影响。*图输入经过 Frame 和 Tracking 形成关键帧/地图点最终输出轨迹和稀疏地图。*6. 为什么要并行Tracking 必须尽快给出每帧位姿预算接近相机帧间隔。Local Mapping 的三角化和 Local BA 更耗时Loop Closing 的地点识别和图优化发生频率更低但可能更昂贵。拆分执行上下文可以让相机输入继续前进。并行也带来一致性问题Tracking 读局部地图时Local Mapping 可能添加或删除点Loop Closing 校正整张地图时Local Mapping 必须停止Global BA 运行期间若出现新闭环旧优化结果可能失效系统退出时各线程要先收到 finish 请求再等待其确认。ORB-SLAM3 使用互斥锁、停止/完成标志和队列保护实现协作。不要把mutex当作算法细节它决定一条调用链是否可以安全修改地图。7. Frame、KeyFrame 与观测Frame表示一次实时输入包含时间戳、图像特征、描述子和金字塔尺度信息相机模型、内参、畸变和双目/RGB-D 深度当前位姿、速度和 IMU bias与特征对应的MapPoint*BoW 向量前一帧与 IMU 预积分对象。Frame 生命周期较短但用于恢复完整轨迹的相对位姿、参考关键帧和丢失标记会由 Tracking 另存。KeyFrame关键帧由选中的 Frame 构造是地图的长期节点。它保存特征和观测还维护与其他关键帧的共视权重生成树的父子关系回环边/融合边前后惯性关键帧线程安全的位姿和连接更新。不是“图像清晰就成为关键帧”。NeedNewKeyFrame()同时考虑帧间隔、局部建图是否繁忙、跟踪内点、近点数量和 Sensor 模式。8. MapPoint 与地图图结构MapPoint保存世界坐标、代表性描述子、法向/可见距离、观测集合以及被看到/被匹配统计。一个地图点必须经历由双目深度或多视图三角化创建在邻域关键帧中投影搜索计算代表性描述子和法向根据找到率、观测数和年龄筛选若与已有点重复则融合或替换。共视图的边权通常与共同观测的地图点数量相关。Tracking 通过共视邻居构造局部地图Local Mapping 用它选择三角化和 BA 邻域。生成树提供始终连通的稀疏骨架闭环边补充长期约束Essential Graph 用较稀疏的图完成全局校正。9. Map、Atlas 与地点数据库Map持有一组 KeyFrame 和 MapPoint并记录初始关键帧、参考点、变化索引和 IMU 初始化状态。Atlas持有多张可能断开的 MapCreateNewMap()创建并激活新地图ChangeMap(map)切换活跃地图GetCurrentMap()供 Tracking/Mapping 获取活跃地图保存相机模型并支持序列化。KeyFrameDatabase跨 Atlas 使用统一 ORB 词袋数据库。查询结果可能用于重定位、同地图闭环或跨地图融合最终类别要看候选关键帧所属 Map 及几何验证结果。10. 输出、持久化和关闭Track*()返回当前相机位姿System 还复制 Tracking 状态、当前跟踪地图点和关键点供应用查询。轨迹保存函数根据 TUM、EuRoC 或 KITTI 格式输出位姿。因为普通 Frame 位姿常以参考 KeyFrame 的相对变换保存导出时要沿关键帧关系恢复到统一坐标。V1.0 支持 Atlas 保存/加载。Boost 序列化恢复对象后还需要重建部分运行时指针和数据库关系序列化不是简单地把内存地址写入文件。安全关闭顺序是System::Shutdown()向后台模块请求结束等待 Local Mapping、Loop Closing 和 Viewer 确认完成若 Global BA 仍在运行等待或终止对应流程再保存轨迹/地图或销毁对象。删除模块会怎样删除 Local Mapping地图不再增长和局部优化最终无法稳定跟踪新区域删除 Loop Closing短/中期跟踪仍能运行但长程漂移无法校正地图也不能融合删除 Atlas跟踪彻底失败后只能重置或结束不能保留旧地图等待以后复用删除 KeyFrameDatabase重定位、闭环和地图融合都会失去高效候选检索。卷二建立了对象和执行上下文。卷三将沿纯视觉输入逐分支走完初始化、正常 Tracking、Local Mapping 和同地图闭环。