ORB SLAM3系统初始化

ORB SLAM3的初始化主要是为了:

  • 从配置文件中读取需要的参数
  • 创建跟踪线程,局部建图线程,闭环线程三大主线程,以及可视化线程
  • 创建后面需要的对象:ORB词袋、关键帧数据库、多地图

其步骤如下:

  • 步骤:
    1. 检测配置文件能否打开
    2. 加载ORB词袋(ORBVocabulary)
    3. 创建关键帧数据库(KeyFrameDatabase)
    4. 创建多地图(Atlas)
    5. 创建跟踪线程(Tracking)
    6. 创建局部建图线程(LocalMapping)
    7. 创建闭环线程(LoopClosing)
    8. 设置线程间的指针

这里主要讲解跟踪线程的初始化,而对于局部建图线程,闭环线程的初始化只是简单的参数赋值

跟踪线程

A.相机模型

从配置文件中读取相机参数,创建相机模型(Pinhole/KannalaBrandt8)

  • Pinhole/KannalaBrandt8: 继承自GeometricCamera,输入:相机参数(fx,fy,cx,cy, k1, k2, p1, p2, k3/fx,fy,cx,cy,k1,k2,k3,k4
  • 添加相机模型到多地图系统中(mpAtlas->AddCamera(mpCamera))

对于针孔相机模型Pinhole可以参考文章:【二】[详细]针孔相机模型、相机镜头畸变模型、相机标定与OpenCV实现

OpenCV 中的 `FileStorage` 类能够读写`.xml`和`.yaml`文件,以 `FileNode` 为单位存储数据,其有以下操作:
* 写入:`FileStorage::WRITE`
* 追加:`FileStorage::APPEND`
* 读取:`FileStorage::WRITE`

B.ORB特征提取器

从配置文件中读取ORB参数,创建ORB特征提取器(ORBextractor),其主要参数:

  • nFeatures: 特征点的数量
  • Scalefactor:特征金字塔的尺度因子
  • nLevels: 特征金字塔的层数
  • iniThFAST: 初始Fast阈值
  • minThFAST: 最小Fast阈值

ORBextractor的构造函数如下,需要注意的是单目情况下,特征点的数目增加为5倍

mpORBextractorLeft = new ORBextractor(nFeatures,fScaleFactor,nLevels,fIniThFAST,fMinThFAST);
//相对于普通情况,单目初始化时提取的特征点数量更多
mpIniORBextractor = new ORBextractor(5*nFeatures,fScaleFactor,nLevels,fIniThFAST,fMinThFAST);

构造ORBextractor特征提取器主要分为如下几个步骤:

  1. 设置图像金字塔的尺度因子逆尺度因子方差
mvScaleFactor.resize(nlevels);
mvInvScaleFactor.resize(nlevels);

mvLevelSigma2.resize(nlevels);
mvInvLevelSigma2.resize(nlevels);

m v S c a l e f a c t o r i = m v S c a l e f a c t o r i − 1 ⋅ s c a l e f a c t o r m v I n v S c a l e f a c t o r i = 1 m v S c a l e f a c t o r i m v L e v e l S i g m a 2 i = m v S c a l e f a c t o r i 2 m v I n v L e v e l S i g m a 2 i = 1 m v L e v e l S i g m a 2 i \begin{array}{l} mvScalefactor_{i} = mvScalefactor_{i-1} \cdot scalefactor \\ mvInvScalefactor_{i} = \frac{1}{mvScalefactor_{i}} \\ mvLevelSigma2_{i} = mvScalefactor_{i}^{2} \\ mvInvLevelSigma2_{i} = \frac{1}{mvLevelSigma2_{i}} \end{array} mvScalefactori=mvScalefactori1scalefactormvInvScalefactori=mvScalefactori1mvLevelSigma2i=mvScalefactori2mvInvLevelSigma2i=mvLevelSigma2i1
图像金字塔如下:

2. 预分配每层金字塔的特征点数量

  • 分配的方式:先分配前 n − 1 n-1 n1层,再将剩余的特征点 N − s u m ( 0 , n − 1 ) N-sum(0,n-1) Nsum(0,n1)分配给第n层。

每层金字塔期望的特征点数量:

假设需要提取的特征点数量为 N N N,金字塔共有 m m m层,第0层图像的宽为 W W W,高为 H H H ,对应的面积 H ⋅ W = C H\cdot W =C HW=C,图像金字塔缩放因子为 s ( 0 < s < 1 ) s(0<s<1) s(0<s<1),在 ORB-SLAM中 , m = 8 , s = 1 / 1.2 m=8,s=1/ 1.2 m=8s=1/1.2
那么,整个金字塔总面积为:
S = H ⋅ W ⋅ ( s 2 ) 0 + H ⋅ W ⋅ ( s 2 ) 1 + ⋯ + H ⋅ W ⋅ ( s 2 ) ( m − 1 ) = H W 1 − ( s 2 ) m 1 − s 2 = C 1 − ( s 2 ) m 1 − s 2 \begin{aligned} S &=H \cdot W \cdot\left(s^{2}\right)^{0}+H \cdot W \cdot\left(s^{2}\right)^{1}+\cdots+H \cdot W \cdot\left(s^{2}\right)^{(m-1)} \\ &=H W \frac{1-\left(s^{2}\right)^{m}}{1-s^{2}}=C \frac{1-\left(s^{2}\right)^{m}}{1-s^{2}} \end{aligned} S=HW(s2)0+HW(s2)1++HW(s2)(m1)=HW1s21(s2)m=C1s21(s2)m
单位面积应该分配的特征点数目为:
N a v g = N S = N C 1 − ( s 2 ) m 1 − s 2 = N ( 1 − s 2 ) C ( 1 − ( s 2 ) m ) N_{a v g}=\frac{N}{S}=\frac{N}{C \frac{1-\left(s^{2}\right)^{m}}{1-s^{2}}}=\frac{N\left(1-s^{2}\right)}{C\left(1-\left(s^{2}\right)^{m}\right)} Navg=SN=C1s21(s2)mN=C(1(s2)m)N(1s2)
第0层应该分配的特征点数量为:
N 0 = N ( 1 − s 2 ) 1 − ( s 2 ) m N_{0}=\frac{N\left(1-s^{2}\right)}{1-\left(s^{2}\right)^{m}} N0=1(s2)mN(1s2)
第 i 层应该分配的特征点数量为:
N i = N ( 1 − s 2 ) C ( 1 − ( s 2 ) m ) C ( s 2 ) i = N ( 1 − s 2 ) 1 − ( s 2 ) m ( s 2 ) i N_{i}=\frac{N\left(1-s^{2}\right)}{C\left(1-\left(s^{2}\right)^{m}\right)} C\left(s^{2}\right)^{i}=\frac{N\left(1-s^{2}\right)}{1-\left(s^{2}\right)^{m}}\left(s^{2}\right)^{i} Ni=C(1(s2)m)N(1s2)C(s2)i=1(s2)mN(1s2)(s2)i
在ORB-SLAM3 的代码里,不是按照面积均摊的,而是按照面积的开方来均摊特征点的,也就是将上述公式中的 s 2 s^2 s2换成 s s s 即可。

  1. 初始化pattern
    pattern为 32 ⋅ 8 ⋅ 4 = 1024 32\cdot8\cdot4 = 1024 3284=1024,其中pattern是ORB预设好的。
    参考文献:《BRIEF: Binary Robust Independent Elementary Features 》

  1. 预先计算灰度质心法每行对应的终点
    1. 先算弧A->B( v ∈ ( 0 , v m a x ) v\in(0,vmax ) v(0,vmax))段
    2. 再算弧C->B( v ∈ ( r , v m i n ) v\in(r,vmin ) v(r,vmin))段
	//umax存放u轴的最大值,因为只有1/4圆,所以size为半径+1
   umax.resize(HALF_PATCH_SIZE + 1);
	

    int v,v0,vmax = cvFloor(HALF_PATCH_SIZE * sqrt(2.f) / 2 + 1);//为v轴根号2/2处,也就是
    
    int vmin = cvCeil(HALF_PATCH_SIZE * sqrt(2.f) / 2);
	//半径的平方
    const double hp2 = HALF_PATCH_SIZE*HALF_PATCH_SIZE;

	//计算每行的umax
    for (v = 0; v <= vmax; ++v)
        umax[v] = cvRound(sqrt(hp2 - v * v));

    // Make sure we are symmetric
	//利用对称性,计算第一象限的另外的1/8圆的umax
	for (v = HALF_PATCH_SIZE, v0 = 0; v >= vmin; --v)
    {
        while (umax[v0] == umax[v0 + 1])
            ++v0;
        umax[v] = v0;
        ++v0;
    }


注意:这里算出来vmaxvmin是相等的,可以看打印出来的点中有一个红圈套篮圈

C.IMU预积分

从配置文件中读取IMU参数,创建IMU标定(IMU::Calib)、IMU预积分(IMU::Preintegrated)

  • Tbc:相机到IMU的变换矩阵
  • freq:IMU的频率
    • 单位: h z hz hz
    • 符号: 1 Δ t \frac{1}{\Delta t} Δt1
  • Ng:陀螺仪白噪声
    • 单位:  rad  s 1 H z \frac{\text { rad }}{s} \frac{1}{\sqrt{H_{z}}} s rad Hz 1
    • 符号: σ g \sigma_{g} σg
  • Na:加速计白噪声
    • 单位: m s 2 1 H z \frac{m}{s^{2}} \frac{1}{\sqrt{H z}} s2mHz 1
    • 符号: σ a \sigma_{a} σa
  • Ngw:陀螺仪随机游走噪声
    • 单位:  rad  s 2 1 H z \frac{\text { rad }}{s^{2}} \frac{1}{\sqrt{H z}} s2 rad Hz 1
    • 符号: σ b g \sigma_{bg} σbg
  • Naw:加速计随机游走噪声
    • 单位: m s 3 1 H z \frac{m}{s^{3}} \frac{1}{\sqrt{H z}} s3mHz 1
    • 符号: σ b a \sigma_{ba} σba

这里主要创建来自上一关键帧的IMU预积分,主要参数为高斯白噪声协方差随机游走协方差
高斯白噪声的方差从连续时间到离散时间需要乘以一个 1 f r e q \frac{1}{\sqrt{freq}} freq 1
N a = N a d f r e q N g = N g d f r e q \begin{array}{c} N_{a} = N_{a}^{d}\sqrt{freq} \\ N_{g} = N_{g}^{d}\sqrt{freq} \end{array} Na=Nadfreq Ng=Ngdfreq
随机游走方差从连续时间到离散时间乘以一个 f r e q \sqrt{freq} freq
N a w = N a w d 1 f r e q N g w = N g w d 1 f r e q \begin{array}{c} N_{aw} = N_{aw}^{d}\frac{1}{\sqrt{freq}} \\ N_{gw} = N_{gw}^{d}\frac{1}{\sqrt{freq}} \end{array} Naw=Nawdfreq 1Ngw=Ngwdfreq 1
高斯白噪声协方差Cov:
[ N g 2 0 0 0 0 0 0 N g 2 0 0 0 0 0 0 N g 2 0 0 0 0 0 0 N a 2 0 0 0 0 0 0 N a 2 0 0 0 0 0 0 N a 2 ] \begin{bmatrix} N_{g}^{2} & 0 & 0 & 0 & 0 & 0\\ 0 & N_{g}^{2} & 0 & 0 & 0 & 0\\ 0 & 0 &N_{g}^{2} & 0 & 0 & 0\\ 0 & 0& 0 &N_{a}^{2} & 0& 0\\ 0& 0& 0& 0&N_{a}^{2} & 0\\ 0& 0& 0& 0& 0&N_{a}^{2} \end{bmatrix} Ng2000000Ng2000000Ng2000000Na2000000Na2000000Na2
随机游走协方差CovWalk:
[ N g w 2 0 0 0 0 0 0 N g w 2 0 0 0 0 0 0 N g w 2 0 0 0 0 0 0 N a w 2 0 0 0 0 0 0 N a w 2 0 0 0 0 0 0 N a w 2 ] \begin{bmatrix} N_{gw}^{2} & 0 & 0 & 0 & 0 & 0\\ 0 & N_{gw}^{2} & 0 & 0 & 0 & 0\\ 0 & 0 &N_{gw}^{2} & 0 & 0 & 0\\ 0 & 0& 0 &N_{aw}^{2} & 0& 0\\ 0& 0& 0& 0&N_{aw}^{2} & 0\\ 0& 0& 0& 0& 0&N_{aw}^{2} \end{bmatrix} Ngw2000000Ngw2000000Ngw2000000Naw2000000Naw2000000Naw2

  • 2
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

火柴的初心

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值