源码:
主要的类
ORB_SLAM3::System
下面是对 ORB_SLAM3 中 System 类的简要介绍与要点概览:
- 角色定位
- 系统入口与调度器:负责初始化与持有核心模块(Tracking、LocalMapping、LoopClosing、Viewer、Atlas、词典、数据库),并管理其线程生命周期。
- 调用者通过它喂入图像/IMU 数据、获取当前位姿与状态、控制模式与输出轨迹。
- 传感器与文件类型
- eSensor:MONOCULAR、STEREO、RGBD、IMU_MONOCULAR、IMU_STEREO、IMU_RGBD。
- FileType:TEXT_FILE、BINARY_FILE(内部用于 Atlas 存/读)。
- 构造与初始化
- System(voc 路径, 配置路径, 传感器类型, 是否开 Viewer, 加载/保存 Atlas 路径, ArUco 字典与初始化标记参数)。
- 构造时创建并连接 Tracking/LocalMapping/LoopClosing/Viewer 等对象,启动除 Tracking 外的后台线程。
- 核心处理接口(返回当前相机位姿 Sophus::SE3f)
- TrackStereo(left, right, t, imu 测量, filename)
- TrackRGBD(rgb, depth, t, imu 测量, filename)
- TrackMonocular(img, t, imu 测量, filename)
- LocalizeMonocular(img, t, imu 测量, filename) → 返回 (位姿, 是否成功);仅定位不建图的场景常用。
- 模式控制
- ActivateLocalizationMode()/DeactivateLocalizationMode():切换“仅定位”与“SLAM 建图”。
- MapChanged():查询是否发生大的地图改动(闭环/全局 BA)。
- 系统控制
- Reset()/ResetActiveMap():重置全局或仅活跃地图。
- Shutdown()/isShutDown():请求并等待所有后台线程结束,保存轨迹前必须调用。
- 轨迹与调试输出
- SaveTrajectoryCSV/TUM/EuRoC/KITTI,以及 KeyFrameTrajectory 变体;部分重载可指定 Map。
- SaveDebugData(iniIdx):初始化阶段数据导出。
- 状态查询
- GetTrackingState():跟踪状态码。
- GetTrackedMapPoints()/GetTrackedKeyPointsUn():当前帧关联地图点与未畸变关键点。
- GetTimeFromIMUInit()/isLost()/isFinished()
- ChangeDataset()、GetImageScale()、isLoadingMap()
- 线程模型
- Tracking 运行在调用者线程。
- LocalMapping、LoopClosing、Viewer 在独立线程中运行(mptLocalMapping/mptLoopClosing/mptViewer)。
- 内部用互斥量管理重置与模式切换标志。
- 重要成员
- 传感器类型 mSensor
- 词典 mpVocabulary、回环/重定位数据库 mpKeyFrameDatabase
- 地图集合 mpAtlas(ORB-SLAM3 的多地图/Atlas 架构)
- 核心模块指针:mpTracker/mpLocalMapper/mpLoopCloser/mpViewer
- 可视化:mpFrameDrawer/mpMapDrawer
- 运行状态与缓存:mTrackingState、mTrackedMapPoints、mTrackedKeyPointsUn
- Atlas 存读与校验:SaveAtlas/LoadAtlas/CalculateCheckSum
- 配置 Settings* settings_
- 典型用法流程
- 构造 System(加载词典与配置,决定是否打开 Viewer)。
- 循环调用 TrackXXX 喂入图像/IMU,获取位姿与状态。
- 需要时切换定位模式或重置。
- 结束前调用 Shutdown(),随后保存轨迹到指定格式。
整体上,System 封装了 ORB-SLAM3 的全流程入口与资源管理,提供统一的多传感器跟踪 API、可选仅定位模式、轨迹导出与线程化的后端处理。
接下来为 3 个主要的线程类:
ORB_SLAM3::Tracking
下面是 ORB_SLAM3 中 Tracking 类的精要说明:
- 职责定位
- 前端跟踪核心:负责特征提取/匹配、位姿估计、关键帧判定、IMU 预积分与状态预测、重定位。
- 与后端线程交互:将关键帧与地图点交给 LocalMapping/LoopClosing;与 Viewer/Drawers 同步可视化状态。
- 构造与依赖
- 由 System 创建,持有/使用:Vocabulary、KeyFrameDatabase、Atlas、LocalMapping、LoopClosing、Viewer、FrameDrawer、MapDrawer、Settings 等。
- 支持 ArUco 初始化参数(字典、标签 ID 与尺寸),用于单目初始化辅助。
- 主要对外接口
- GrabImageStereo/GrabImageRGBD/GrabImageMonocular:输入图像(与时间戳),返回相机位姿(Sophus::SE3f)。
- GrabImuData:推入单条 IMU 测量(与图像异步)。
- SetLocalMapper/SetLoopClosing/SetViewer;InformOnlyTracking(仅定位模式开关)。
- ChangeCalibration(更换相机内参);UpdateFrameIMU/GetLastKeyFrame。
- Reset/ResetActiveMap;NewDataset/GetNumberDataset/GetMatchesInliers;SaveSubTrajectory;GetImageScale。
- 跟踪状态机 eTrackingState
- SYSTEM_NOT_READY/NO_IMAGES_YET/NOT_INITIALIZED
- OK/RECENTLY_LOST/LOST
- OK_KLT/INIT_RELOCALIZE(扩展状态,便于调试与恢复)
- 核心内部流程(关键私有方法)
- Track:主循环(传感器无关),组织整帧处理。
- 初始化:StereoInitialization、MonocularInitialization/CreateInitialMapMonocular。
- 预测与跟踪:TrackWithMotionModel、PredictStateIMU、TrackReferenceKeyFrame、TrackLocalMap、SearchLocalPoints、UpdateLastFrame。
- 重定位:Relocalization。
- 局部地图维护:UpdateLocalMap/UpdateLocalPoints/UpdateLocalKeyFrames。
- 关键帧策略:NeedNewKeyFrame/CreateNewKeyFrame。
- IMU:PreintegrateIMU、ResetFrameIMU。
- 重要成员与数据
- 当前/上一帧:mCurrentFrame/mLastFrame;灰度图 mImGray;位姿速度模型 mVelocity(mbVelocity)。
- ORB 提取器:mpORBextractorLeft/Right、mpIniORBextractor;BoW:mpORBVocabulary、mpKeyFrameDB。
- 本地地图缓存:mvpLocalKeyFrames/mvpLocalMapPoints;参考关键帧 mpReferenceKF。
- IMU:预积分 mpImuPreintegratedFromLastKF、测量队列 mlQueueImuData、标定 mpImuCalib、Bias mLastBias、频率/周期。
- 相机与标定:mK/mK_/mDistCoef、基线 mbf、mImageScale、深度缩放 mDepthMapFactor、阈值 mThDepth;双目相机 mpCamera/mpCamera2。
- 模式与标志:mbOnlyTracking、mbVO、mbMapUpdated、mbRGB、mbCreatedMap/mbLoadedMap、bStepByStep。
- 统计与轨迹:mlRelativeFramePoses/mlpReferences/mlFrameTimes/mlbLost/mlState、mnMatchesInliers、时间统计字段。
- ArUco:maruco_dict、minit_tag_id、minit_tag_size(单目初始化辅助)。
- 典型时序
- 外部循环调用 GrabImageX → 内部 Track:预测(运动模型/IMU)→ 局部地图跟踪 → 判定并插入关键帧 → 与 LocalMapping/LoopClosing 协作;必要时触发重定位。
ORB_SLAM3::LocalMapping
LocalMapping 是 ORB-SLAM3 的“局部建图线程”。它在 Tracker 插入关键帧后,负责维护局部地图质量与连通性,核心任务包括:
- 吸收新关键帧,更新共视图并与邻居匹配,三角化生成新地图点;
- 清理质量差/冗余的地图点与关键帧(Culling),保持地图精炼;
- 执行局部 BA(Bundle Adjustment)优化局部窗口内的位姿和点;
- 在 IMU 模式下,完成初始的惯性参数估计(重力方向、尺度、零偏)及后续尺度细化。
它与 Tracker(前端)和 LoopClosing(回环)协作,通过互相的同步与控制接口协调工作节奏和资源。
外部接口与线程控制
-
构造函数
- LocalMapping(System* pSys, Atlas* pAtlas, const float bMonocular, bool bInertial)
- bMonocular/bInertial 用来配置是否为(IMU)单目和是否启用 IMU;虽然 bMonocular 类型是 float,但逻辑上当作 bool 用。
-
主循环
- Run(): 线程入口,循环处理关键帧队列、建图与优化。典型流程:
- CheckNewKeyFrames → 有则取出
- ProcessNewKeyFrame → 更新拓扑、准备匹配
- CreateNewMapPoints → 与邻居互相匹配/三角化
- MapPointCulling → 清理质量差点
- SearchInNeighbors → 扩展相邻约束和点
- KeyFrameCulling → 剔除冗余关键帧
- 局部 BA(可被 InterruptBA 打断)
- Run(): 线程入口,循环处理关键帧队列、建图与优化。典型流程:
-
关键帧接入
- InsertKeyFrame(KeyFrame* pKF): Tracker 调用,将新 KF 入队
- EmptyQueue(): 清空队列(常用于重置)
-
线程同步/生命周期
- RequestStop()/Stop()/Release(): 停止/恢复本线程(回环或模式切换时使用)
- AcceptKeyFrames()/SetAcceptKeyFrames(bool): 是否接收新关键帧的门闸
- InterruptBA(): 打断正在进行的 BA(例如需要快速响应模式切换/回环)
- RequestReset()/RequestResetActiveMap(Map*): 请求全局/当前地图重置
- RequestFinish()/isFinished(): 线程结束控制
- CheckFinish()/SetFinish(): 内部配合 isFinished 的结束判定
-
状态/查询
- KeyframesInQueue(): 当前待处理关键帧数
- IsInitializing(): 是否处于(IMU)初始化阶段
- GetCurrKFTime()/GetCurrKF(): 当前处理的关键帧时间与指针
与其他模块的关系
- Tracker → LocalMapping
- Tracker 在决定插入关键帧时调用 InsertKeyFrame,并依赖 LocalMapping 生成新点、优化局部,维持前端跟踪质量。
- LocalMapping ↔ LoopClosing
- 回环线程可能请求 LocalMapping 暂停,避免与全局/局部图优化冲突;LocalMapping 会在合适时机打断局部 BA 并让位。
- LocalMapping ↔ Atlas/Map
- 所有关键帧与地图点操作都基于当前 Map(通过
mpAtlas),重置或切图时会配合 Atlas 的状态。
- 所有关键帧与地图点操作都基于当前 Map(通过
主要成员与含义(按功能分组)
-
线程/同步控制
- mbStopped/mbStopRequested/mbNotStop, mMutexStop: 停止/恢复控制
- mbAcceptKeyFrames, mMutexAccept: 是否接受新关键帧的门闸
- mbFinishRequested/mbFinished, mMutexFinish: 结束请求与状态
- mbResetRequested/mbResetRequestedActiveMap, mMutexReset, mpMapToReset: 重置控制
- mbAbortBA: 是否打断当前 BA
-
输入/工作队列
- mlNewKeyFrames: 等待处理的关键帧队列
- mpCurrentKeyFrame: 正在处理的当前关键帧
- mlpRecentAddedMapPoints: 最近添加的地图点,便于后续质量筛除
-
模式与配置
- mbMonocular: 是否(IMU)单目模式(影响初始化/尺度)
- mbInertial: 是否启用 IMU(影响初始化与后端项)
- mbFarPoints, mThFarPoints: 是否忽略“过远点”及阈值(米),减少噪声与渲染负担
- mbWriteStats, f_lm: 记录/输出统计信息
-
IMU 相关(惯性初始化与尺度细化)
- bInitializing: 是否处于 IMU 初始化流程中
- InitializeIMU(float priorG=1e2, float priorA=1e6, bool bFirst=false):
- 估计重力方向 mRwg、尺度 mScale、零偏(mbg/mba),以及惯性协方差 mcovInertial/infoInertial
- priorG/priorA 是对重力/加速度项的先验权重(越大越“强先验”)
- bFirst 表示首次初始化阶段的特殊处理
- ScaleRefinement(): 初始化完成后的尺度微调(利用更多观测改进尺度)
- 相关状态/计时:
- mRwg(R_world_to_gravity)、mbg(陀螺零偏)、mba(加计零偏)
- mScale(尺度)、mInitTime/mCostTime(初始化时间/耗时)
- mInitSect/mIdxInit/mnKFs/mFirstTs/mnMatchesInliers 等过程与质量统计
- mbNotBA1/mbNotBA2/mbBadImu:控制/记录 BA 与 IMU 初始化状态
-
统计与调试
- mNumLM(局部建图次数)、mNumKFCulling(KF 剔除计数)、countRefinement(尺度细化次数)
- mTinit(初始化超参/时间窗),以及其他调试用文件输出
典型工作流(关键帧进入后的生命周期)
- Tracker 判定插入关键帧 → 调用 InsertKeyFrame 入队
- LocalMapping::Run 取出队首 KF → ProcessNewKeyFrame 更新连接关系
- 与邻居匹配(SearchInNeighbors),三角化生成新 MapPoints(CreateNewMapPoints)
- MapPointCulling 清理质量差点(少观测/大重投影误差/近重复等)
- KeyFrameCulling 清理冗余关键帧(与邻居高度重合、贡献度低)
- 局部 BA 优化(可被 InterruptBA 打断以响应回环或模式切换)
- 若启用 IMU:未初始化时执行 InitializeIMU,初始化后可进行 ScaleRefinement
常见边界/注意点
- 模式切换:Localization-Only(仅定位)模式会通过门闸阻止接收新关键帧;LocalMapping 会配合停/启。
- 回环并发:闭环发生时,LocalMapping 可能需要暂停或中断 BA;恢复后再继续处理队列。
- 重置:RequestReset/RequestResetActiveMap 触发清队列、清状态,防止历史状态污染新的建图。
- 远点过滤:开启 mbFarPoints 时,超过 mThFarPoints 的点不参与绘制/优化,减少噪声与负担。
ORB_SLAM3::LoopClosing
第三方库
Sophus
简要说:Sophus 是一个基于 Eigen 的 C++ 几何库,专门实现“李群/李代数”在机器人与计算机视觉中的常用群,如 SO(2/3)、SE(2/3)、Sim(3)、RxSO3 等,提供稳定高效的位姿与旋转运算(指数/对数映射、雅可比、群合成/求逆等)。
- 解决什么问题
- 以数学上正确的方式表示并运算位姿/旋转等非线性流形对象,避免把它们当做普通矩阵/欧氏向量而引入误差或不一致。
- 在优化/滤波里方便地用李代数做最小参数更新(log/exp)、计算雅可比。
- 关键特性
- 类型:Sophus::SO3{f,d}(旋转)、SE3{f,d}(位姿)、Sim3(相似变换)等;后缀 f/d 表示 float/double。
- 运算:群合成 T1T2、求逆 T.inverse()、作用到点 Tpoint、exp()/log() 实现李群/李代数互转、hat/vee、Adjoint、左右雅可比。
- 与 Eigen 无缝:内部用 Eigen 存储,接口返回/接收 Eigen 向量与矩阵。
- 轻量通用:常作为视觉 SLAM、VIO、BA 中的基础几何层。
- 在 ORB-SLAM3 中的用法
- 位姿类型广泛使用 Sophus::SE3f(例如
System::TrackMonocular返回相机位姿)。 - 配置读入时把 OpenCV 矩阵转换为 Sophus 变换(见
Converter::toSophus之类用法)。
- 位姿类型广泛使用 Sophus::SE3f(例如
- 和 Eigen 的区别
- Eigen 做线性代数(矩阵/向量);Sophus 提供李群等流形对象与其运算规则,二者配合使用。
- 小例子(概念示意)
- 用 SE3 表示位姿 T,将三维点 p 变换到世界坐标:p_w = T * p_c
- 从微小增量 ξ ∈ R^6(旋转 3+ 平移 3)得到位姿更新:T_new = Sophus::SE3::exp(ξ) * T_old
简单理解:Sophus 让“位姿/旋转”这种非线性对象的数学操作变得安全、规范、易于与优化结合,是 SLAM/VIO 里的常用基础库。
DBoW2
- 基本定义
- DBoW2(Dorian Gálvez-López):视觉词袋(Bag-of-Words)库,支持二进制与浮点描述子;提供“视觉词典 + 倒排索引数据库 + 相似度打分”三件套。
- 目标:把一堆局部特征(如 ORB)量化成稀疏 BoW 向量,用以快速图像检索(回环/重定位候选)。
- 两个核心对象
- Vocabulary(视觉词典)
- 层次化 k-means(参数:分支系数 k、层数 L),树叶节点视为“视觉词”;词典大小 ≈ k^L。
- 为每张图像生成 BoW 向量:统计每个视觉词的频次 term frequency,并乘以 IDF 权重(TF-IDF)。
- 训练可离线完成,运行时只加载(txt 慢,bin 快)。
- Database(倒排索引)
- 存储关键帧的 BoW,按词到图像的映射组织,支持快速相似度查询。
- 返回候选帧 + 相似度分数,供后续几何验证。
- Vocabulary(视觉词典)
- 距离/打分(Scoring)
- 常用 L1/Tf-idf 打分(DBoW2 内置 L1/L2/Chi-Square/KL/Bhattacharyya/DotProduct 等),ORB-SLAM 系列默认 L1 + TF-IDF,稀疏高效。
- 查询复杂度近似与候选数量和词典稀疏度相关,通常远快于直接全量特征匹配。
- 在 ORB-SLAM3 中的角色分工
- ORBVocabulary:加载/持有 DBoW2 词典(
ORBvoc.txt或二进制)。 - KeyFrameDatabase:封装 DBoW2 数据库
- 回环检测:LoopClosing 查询候选关键帧
- 重定位:Tracking 查询候选参考帧
- 工作流:提 ORB → 用 Vocabulary 量化成 BoW → Database 检索候选 → 几何一致性验证(PnP/Sim3/位姿优化)→ 成立则触发闭环或重定位。
- ORBVocabulary:加载/持有 DBoW2 词典(
- 为什么和 ORB-SLAM3 匹配
- 原生支持 ORB(二进制/Hamming),速度快、内存友好。
- 大规模关键帧库中检索高效;离线词典可重用,工程部署便利。
- 参数与权衡
- k(分支因子)与 L(层数)决定词典粒度:越大越细致,检索更区分,但加载更慢、内存更大(启动延迟↑)。
- 词典领域匹配很重要:训练数据与运行场景差异过大,会导致召回下降(回环/重定位更难命中)。
- 二进制词典文件强烈建议使用(显著加快启动,常见对比:几百 ms vs. 数十秒)。
- 常见坑与实践建议
- 词典版本不匹配(特征类型/描述子长度不同)会导致编码/打分异常,务必与 ORB 参数保持一致。
- BoW 的候选只是外观先验,几何验证必不可少;丢失几何验证会产生伪回环。
- 数据库膨胀时可考虑关键帧管理策略(丢弃冗余帧、只加入选定关键帧),减小查询开销。
- 若场景极度同质(纹理重复、室内走廊),适当增大词典或调高几何验证阈值,减少误检。
- 与 DBoW3 的关系
- DBoW3 是 C++11 重写版本,接口更现代;ORB-SLAM3 使用 DBoW2/fork 版本更常见,功能等价但实现细节不同。
一句话记忆:DBoW2 是 ORB-SLAM3 的“外观检索引擎”,把 ORB 特征压成 TF-IDF 的稀疏向量,在大库中快速找相似关键帧,供闭环/重定位的几何验证使用。
g2o
-
定义
- g2o(general graph optimization):通用图优化库,用于求解“非线性最小二乘”的稀疏问题,广泛用于 SLAM/BA/位姿图优化。
-
能力与算法
- 支持高斯 - 牛顿、Levenberg–Marquardt、Dogleg 等迭代法。
- 稀疏线性求解器:Cholesky/QR(基于 CSparse、CHOLMOD、Eigen 等后端)。
- 鲁棒核(Huber、Cauchy、Tukey…)抑制外点影响。
- 边缘化/先验、变量固定、参数块共享等工程能力。
-
基本抽象
- Vertex(顶点/变量):如相机位姿(SE3)、三维点、IMU 偏置、尺度(Sim3)等。
- Edge(因子/误差项):约束两个或多个顶点的观测残差,提供计算残差与雅可比的实现。
- Optimizer:装配图(顶点 + 边)、设置求解器和优化参数,运行优化迭代。
-
工作流(概念)
- 定义参数化(例如 SE3/Sim3/Point3)。
- 为每条观测添加一条 Edge(残差、信息矩阵、鲁棒核)。
- 选择求解器(稀疏线性代数后端)和优化算法(LM/GN)。
- 调用 optimize(N) 迭代,读取更新后的顶点值。
-
在 ORB-SLAM3 中的作用
- 局部/全局 BA:优化相机位姿与路标点(投影因子,内外参可选)。
- 回环位姿图优化:Sim3/SE3 因子构成的图,做全局一致化(含尺度校正)。
- 重定位/初始化时的小规模优化(PnP 优化、结构细化)。
- 强配合 Sophus:顶点通常用 SE3/Sim3 参数化,Edge 里用解析雅可比。
-
与 Ceres/GTSAM 的对比(简述)
- Ceres:自动微分/数值工具链更完备,生态广;g2o 更轻量、贴近 SLAM 经典图模型。
- GTSAM:因子图表达更系统,符号/贝叶斯视角强;g2o API 更直接,工程上易嵌入。
- 选择取决于团队习惯、自动微分需求、后端依赖与性能取舍。
-
常见坑与建议
- 量纲与协方差:信息矩阵需要与残差量纲匹配;像素/米混用会导致不收敛。
- 雅可比正确性:解析雅可比更稳更快;左右扰动一致性必须全链路统一。
- 规约/锚定:图存在自由度(gauge freedom)时需固定参考帧或加先验,否则奇异。
- 鲁棒核:外点多时务必开启;阈值要与观测噪声一致。
- 线性求解器选择:大规模 BA 常用 CHOLMOD;嵌入式或依赖少时可用 Eigen/CSparse。
-
一句话
- g2o 是把“SLAM 的目标函数 = 顶点参数 + 观测因子”高效求解掉的骨干库,提供成熟的非线性最小二乘框架与稀疏后端,是 ORB-SLAM3 做 BA、位姿图与回环优化的基础组件之一。
Pangolin
- Pangolin 是一个轻量级、跨平台的 C++ 可视化与 GUI 库,面向实时计算机视觉/SLAM,基于 OpenGL,依赖少、启动快,适合科研与演示。
- 核心能力
- 窗口与 OpenGL 上下文管理,多视口布局,交互式 3D 视图(旋转/缩放/平移)。
- 3D 绘制:坐标轴、相机金字塔(frustum)、点云、轨迹、线框等。
- 即时 GUI:通过 Var/Panel 定义滑条、复选框、按钮,实时调参数。
- 图像/视频显示:纹理化渲染图像,支持多路流;PangoVideo 统一接口(可选 FFmpeg、相机驱动)。
- 简单绘图(Plotter)与日志可视化,离屏渲染、截图/录屏等。
- 在 ORB-SLAM3 中的用途
- Viewer 窗口:显示当前相机位姿、关键帧、地图点、图优化连线;侧边面板控制可视化选项。
- 与 MapDrawer/FrameDrawer 配合,在实时跟踪中刷新 3D 地图和图像视图。
- 何时选择它
- 需要“快速搭建、实时交互、依赖少”的 3D/图像可视化(SLAM/VIO/重建 demo、算法调参)。
- 不追求复杂桌面 UI(这类建议用 Qt/ImGui 等)。
- 常见注意点
- 需要可用的 OpenGL 上下文;远程/无显示环境用 EGL/OSMesa 方案。
- 事件循环要在创建窗口的线程中渲染,按帧调用 FinishFrame 刷新。
- 可选依赖如 FFmpeg、libjpeg/png 用于视频/图片 I/O;不同平台的包名略有差异。
Q&A
为什么仅 Pinhole 相机需要去畸变
我来解释下从源码逻辑看,为什么只有 Pinhole 相机会触发“去畸变”标志 bNeedToUndistort_:
- 代码触发点
- 在
Settings::readCamera1()里,仅当相机类型是 “PinHole” 且存在畸变参数(k1,k2,p1,p2,可选 k3),并且传感器是单目(System::MONOCULAR或System::IMU_MONOCULAR)时,才会将bNeedToUndistort_设为 true。 - 对于立体(STEREO/IMU_STEREO),不会用这个标志;它走的是
bNeedToRectify_路径,后续通过precomputeRectificationMaps()做“校正 + 对极几何对齐”(这一步包含去畸变),所以不需要单独的 undistort 标志。
- 在
- 各相机模型的处理策略差异
- PinHole(未校正的针孔模型)
- 如果配置里给了畸变系数,单目情况下会直接对图像做去畸变,确保后续跟踪在“理想针孔”成像上进行(ORB 提取、几何约束、投影/反投影都按无畸变针孔假设)。
- 立体情况下不单独去畸变,而是统一做“立体校正”,这一步会同时完成去畸变与行对齐,便于视差计算。
- Rectified(已校正)
- 配置即表示图像已是理想针孔(无畸变),自然不用再去畸变,所以不设置
bNeedToUndistort_。
- 配置即表示图像已是理想针孔(无畸变),自然不用再去畸变,所以不设置
- Kannala-Brandt(鱼眼模型)
- ORB-SLAM3 内部对该模型使用的是非线性相机模型的“投影/反投影”过程,直接在原始(畸变)图上工作,不需要先把图像几何上拉直。
- 换句话说,这类相机的畸变是由几何模型显式建模并在运算中消化掉的,而不是通过预处理的图像去畸变来适配针孔假设。
- PinHole(未校正的针孔模型)
- 补充细节
- 如果是 Pinhole 但没有提供畸变参数,就不会触发去畸变(
bNeedToUndistort_仍为 false)。 - RGB-D 情况也不会触发
bNeedToUndistort_;通常 RGB-D 数据集给的是已标定/配准的图像与深度,系统只读取DepthMapFactor等参数。 - 立体 PinHole 的
bNeedToRectify_会在precomputeRectificationMaps()里用stereoRectify + initUndistortRectifyMap同时完成去畸变与校正。
- 如果是 Pinhole 但没有提供畸变参数,就不会触发去畸变(
小结:只有 Pinhole 在“单目且存在畸变系数”时需要对图像做预去畸变;Rectified 已无畸变;Kannala-Brandt8 则通过相机模型本身处理畸变,无需对图像做几何变换。对于立体,统一用“校正(Rectify)”流程替代单独的去畸变。
ORB 在该 SLAM 中的作用
- 可以这么理解:在 ORB-SLAM3 的视觉前端里,ORB 是默认的“局部特征检测与描述”方法(Oriented FAST 取点 + Rotated BRIEF 描述子)。
- 它的作用
- 在图像上找到稳定的关键点(FAST,多尺度);
- 用二进制描述子(rBRIEF)表示这些关键点的外观,用于快速匹配(汉明距离);
- 供后续位姿估计(PnP/对极几何)、建图、以及用 DBoW2 做回环/重定位检索。
- 场景适配
- 单目/双目/RGB-D 都用 ORB 做视觉特征;RGB-D 只是在 RGB 上提 ORB,再用深度对齐出 3D。
- 鱼眼(Kannala-Brandt)只改变相机投影模型,特征仍是 ORB。
- IMU 融合是独立通道,和 ORB 互补。
- 不是全部
- ORB 负责“视觉特征”层;后端优化、地图表示、回环验证等还有各自的几何与优化模块。
- 有替代品(SIFT/SURF/SuperPoint/SuperGlue 等),但官方实现默认用 ORB,因其快、稳、开源、与 DBoW2 匹配度高。
最终建图完的关键帧是否越多越好
不一定。关键帧不是“越多越好”,而是“够用且不冗余最好”。
-
多关键帧的正面作用
- 覆盖更全:视角/位置更密,弱纹理或遮挡时更容易找到匹配与重定位。
- 稠密观测:每个地图点被更多关键帧观测,几何约束更稳,BA 更容易收敛到好解。
- 细节保留:对于曲折路径或复杂空间,密一点能减少盲区。
-
过多关键帧的代价与副作用
- 计算负担上升:
- 跟踪阶段:搜索局部地图点、投影匹配的开销随局部关键帧/地图点数增长。
- 后端优化:局部/全局 BA、回环/位姿图优化的规模变大,收敛变慢(稀疏求解器时间明显增加)。
- 回环检索:DBoW2 数据库膨胀,检索和几何验证成本上升。
- 冗余信息多:大量相似视角的关键帧带来高度相关的观测,信息增益有限,反而拖慢优化。
- 内存占用与工程复杂度:更大的地图文件,更慢的加载/保存;合并/裁剪更复杂。
- 识别混淆风险:外观高度相似的冗余关键帧可能增加误回环候选(需更强几何验证兜底)。
- 计算负担上升:
-
ORB-SLAM3 的做法(自动“够用不冗余”)
- 有关键帧插入策略:只有满足视差/时间/跟踪质量/局部建图空闲等条件才插入。
- 有关键帧裁剪(KeyFrame Culling):若一个关键帧的大部分地图点已被若干邻接关键帧以相当或更好的尺度观测到,则视为冗余并剔除。这样保持空间/视角上的代表性,而非堆叠近似重复视角。
- 局部化处理:跟踪只使用协视图局部子图,避免全图爆炸。
-
实用建议(什么时候该多一点,什么时候该少一点)
- 该多一点:单目初始化阶段、弱纹理/快速运动/光照剧变、回环稀少的长走廊等困难场景(提升稳健性与重定位概率)。
- 该少一点:视角几乎不变/重复扫同一路径;传感器帧率很高但平台移动很慢;离线地图要便于部署(内存/启动时延敏感)。
- 经验取舍:保证地图点平均被 3–5 个以上关键帧观测、关键帧间有足够视差/位姿变化(平移或转动),避免相邻关键帧几乎同视角。
-
可以调的杠杆(在 ORB-SLAM3 中)
- 插入相关:NeedNewKeyFrame 的阈值(与 mMaxFrames、匹配内点数、局部建图状态有关)、插入“丢失时也可插”(InsertKFsWhenLost)。
- 裁剪相关:关键帧冗余判据(大量地图点被邻居以不差的尺度观测)。
- 特征密度:nFeatures、金字塔参数(影响匹配稳定性和插帧需求)。
一句话:关键帧要“代表性强、覆盖均匀、相互不冗余”。数量够用即可;过多的收益迅速递减,还会显著拖慢跟踪与优化。