DSOL源码基本函数列表
简介DSOL的函数名和算法流程
- 概述
- 命名
- 数据结构
- 主干算法逻辑
DSOL(Direct Sparse Odometry Lite)是宾夕法尼亚大学重构DSO(直接稀疏里程计)的一个版本,众所周知DSO的代码自身耦合比较复杂,而DSOL主要是重构了DSO的代码。增加了gtest测试、glog和fmt格式化输出、absl多线程并行,交互使用ROS一定程度影响了效率。
DSOL可适用双目和单目的SLAM系统。
概述
DSOL结构非常清晰,几乎和DSO算法流程图一样一一对应,看到名字就知道对应的意义。主要都是放到 DirectOdometry::Estimate 下,有以下几个大块对应那三个线程
- Track(image_l, image_r, dT)
- Map(bool add_kf, const cv::Mat& depth)
- BundleAdjust 被Map调用
- BundleAdjuster::Marginalize 被RemoveKeyframe调用
在前端跟踪时使用 FrameAligner,完成相对KeyFrame的直接图像对齐,计算AlignCost;后端优化时使用 BundleAdjuster,计算光度BA问题,主要使用Hessian计算舒尔补边缘化并求解优化。
命名
其中基本命名不同包括:
- aligner 对应于直接图像对齐的实例
- adjuster 对应于后端PBA的实例
- refine 主要指的是双目直接匹配的视差精化
- ooc, oob 遮挡或运动目标引起的bad、out,需要丢弃的patch
- patch 原为pattern
- Forward 正向wrap投影、Backward 反向投影
- FrameHessian1 用于aligner、FrameHessian2 用于adjuster
数据结构
主要数据结构和DSO一样,可能有改名字的,更清晰了。除了其他SLAM中都有的,还包含下面这些主要的基本数据结构
- AffineModel 光度仿射模型
- ImagePyramid 图像金字塔
- PixelSelector 用于找到图像中具有大梯度的像素
- Patch 像素周围的块,也就是pattern
- PatchHessian 分块Hessian的图像梯度块的基类,用于aligner和adjuster
- PointHessian 这个不是常用的,只用于refiner
- Frame 不包含FramePoint,仅用于tracking
- Keyframe 包含FramePointGrid 等,是维护的主要内容
- FramePoint 关键帧上的iDepth点,存储Jacobian
- FramePointGrid 每个格子 大小 32*32, 包含FramePoint
- FrameState 包含SE3和affine
- FrameHessian 一个基类,包含大小信息,不包含Hessian矩阵。用于实现 1.aligner中使用的三角化程度比较低的单帧Hessian 2. adjuster中使用的帧间关联Hessian 3. FrameHessianX 包含动态大小Hessian数据
- KeyframeWindow 包含多个KF的滑窗,放在window.h中
- FrameAligner 直接图像对齐
- DepthPointGrid 每个格子,包含逆深度和像素点
- BundleAdjuster 计算光度BA问题
- FramePointHessian 存储求解出的点数据,
- SchurFrameHessian 存储舒尔补之后的数据,
- StereoMatcher 用于双目的稀疏立体匹配器
主干算法逻辑
按照调用顺序,主要流程按三个大块,所用到的用于SLAM功能的函数如下:
NodeData::Run
DirectOdometry::Estimate
DirectOdometry::Track{ // 跟踪DirectOdometry::TrackFrame{FrameAligner::AlignFrameAligner::AlignLevel 金字塔一层的图像对齐FrameAligner::SolveSolveCholeskyScaledFrameAligner::BuildLevel 为当前层构建AlignCost,返回FrameHessian1AlignCost::Build 为每个patch构造FrameHessianAlignCost::WarpPatch 输入patch0、point0和FrameHessian1,返回DepthPointAlignCost::UpdateHess 为单独一个patch 更新HessianAlignCost::CalcJacGeo 计算du_dx类型为JacGeoFrameHessian1::AddPatchHess
}
DirectOdometry::ShouldAddKeyframe
}
DirectOdometry::Map{ // 建图DirectOdometry::AddKeyframe(cv::Mat& depth) DirectOdometry::AddKeyframe(Frame& frame)PixelSelector::SetOccMaskPixelSelector::SelectKeyframe::InitPointsStereoMatcher::MatchStereoMatcher::MatchCoarseStereoMatcher::MatchRefineStereoMatcher::BestMatchKeyframe::InitFromDispCamera::Disp2Idepth 视差到深度图Keyframe::InitFromAlign(cv::Mat& idepth) 初始化Keyframe::InitPatches 按金字塔层级初始化patchKeyframe::InitPatchesLevelPatch::ExtractAround3
}
DirectOdometry::BundleAdjust{ // PBABundleAdjuster::AdjustBundleAdjuster::AdjustLevelBundleAdjuster::BuildLevel 为所有关键帧单个level构建HessianAdjustCost::Build 返回FrameHessian2AdjustCost::WarpPatchPatch::ExtractFastcv::Point3d GradValAtDAdjustCost::UpdateHessAdjustCost::CalcJacGeo 计算j_geo类型为JacGeoMatrixMNd<2, 3> DprojDpointFrameHessian2::AddPatchHess FramePointHessian::AddPatchHess
}
DirectOdometry::Map{DirectOdometry::RemoveKeyframe{ 删除关键帧BundleAdjuster::Marginalize // 边缘化BundleAdjuster::BuildLevelKf 1. 为一个关键帧的单个level构建HessianAdjustCost::Build 返回FrameHessian2,下面是并行调用,(前面TrackFrame已经出现过)AlignCost::WarpPatch 输入patch0、point0和FrameHessian1,返回DepthPointAlignCost::UpdateHess 为单独一个patch 更新HessianAlignCost::CalcJacGeo 计算du_dx类型为JacGeoFrameHessian1::AddPatchHessFramePointHessian::AddFrameHessFramePointHessian::MargPointsRange 2. 边缘化帧kf_ind中的所有点FillLowerTriangularSafeCwiseInverseMargPointsToFrames 将点边缘化到帧上,并行化计算新的HessianFillUpperTriangularSchurFrameHessian::MargFrame 4. 边缘化帧kf_ind以形成新的先验StableRotateBlockTopLeftMargTopLeftBlock
}}
类基本位于它们的.cpp文件中,直观的可以找到。