LSD-SLAM的SE3Tracking线程笔记

就SE3Tracker.cpp中trackFrame

// ============ track frame ============
    //将初始估计记录下来(记录了参考帧到当前帧的刚度变换),然后定义一个6自由度矩阵的误差判别计算对象ls,定义cell数量以及最终的残差
	Sophus::SE3f referenceToFrame = frameToReference_initialEstimate.inverse().cast<float>();
	LGS6 ls;


	int numCalcResidualCalls[PYRAMID_LEVELS];  //cell数量  5层 金字塔
	int numCalcWarpUpdateCalls[PYRAMID_LEVELS];

	float last_residual = 0;  //最终残差


	for(int lvl=SE3TRACKING_MAX_LEVEL-1;lvl >= SE3TRACKING_MIN_LEVEL;lvl--) //金字塔的迭代从level-4到level-1
	{
		numCalcResidualCalls[lvl] = 0;
		numCalcWarpUpdateCalls[lvl] = 0;

		//有参考帧的逆深度信息和对应的像素点坐标  计算在参考帧坐标系下的3D点
		reference->makePointCloud(lvl);


		//对参考帧当前层构建点云,然后使用callOptimized函数调用calcResidualAndBuffers计算参考帧3D点变换到当前帧的残差(灰度)和(对应点像素)梯度,
        /// 参数为后面括号里面的所有数据,这是调用的宏定义
		callOptimized(calcResidualAndBuffers, (reference->posData[lvl], reference->colorAndVarData[lvl], SE3TRACKING_MIN_LEVEL == lvl ? reference->pointPosInXYGrid[lvl] : 0, reference->numData[lvl], frame, referenceToFrame, lvl, (plotTracking && lvl == SE3TRACKING_MIN_LEVEL)));

		// buf_warped_size 记录了 匹配点数量 包括好的匹配点 和 不好的匹配点 数量 
		//判断这个warp的好坏(如果改变的太多,已经超过了这一层图片的1%),那么我们认为差别太大,Tracking失败,返回一个空的SE3
		if(buf_warped_size < MIN_GOODPERALL_PIXEL_ABSMIN * (width>>lvl)*(height>>lvl))
		{
			diverged = true;
			trackingWasGood = false;
			return SE3();
		}

		//是否使用了简单的仿射变换,
        // 那么把通过calcResidualAndBuffers函数更新的affineEstimation_a_lastIt以及affineEstimation_b_lastIt,赋值给仿射变换系数
		if(useAffineLightningEstimation)
		{
			affineEstimation_a = affineEstimation_a_lastIt;
			affineEstimation_b = affineEstimation_b_lastIt;
		}
		//调用calcWeightsAndResidual用方差归一化残差,并记录调用次数
        ///这里直接使用calcResidualAndBuffers的结果.
		float lastErr = callOptimized(calcWeightsAndResidual,(referenceToFrame));

		numCalcResidualCalls[lvl]++;


		float LM_lambda = settings.lambdaInitial[lvl];   //λ  LM优化的 调整量  与高斯牛顿的区别之处 (A+λI)x=b

		for(int iteration=0; iteration < settings.maxItsPerLvl[lvl]; iteration++)
		{

		    //计算雅克比向量以及A和b
            // 计算 加权平均误差 以及误差权重
            ///这一步跟上面的calcWeightsAndResidual没有关系.
			callOptimized(calculateWarpUpdate,(ls));

			numCalcWarpUpdateCalls[lvl]++;

			iterationNumber = iteration;

			int incTry=0;
			while(true)
			{
				// solve LS system with current lambda
				Vector6 b = -ls.b;
				Matrix6x6 A = ls.A;
				for(int i=0;i<6;i++) A(i,i) *= 1+LM_lambda;  //(A+λI)  LM 调整量 
				//计算收敛的delta更新SE3
                //LDLT矩阵分解 dse3李代数更新量
				Vector6 inc = A.ldlt().solve(b);
				incTry++;

				// apply increment. pretty sure this way round is correct, but hard to test.
                 // 对 变换矩阵 左乘 se3指数映射 进行 更新
				Sophus::SE3f new_referenceToFrame = Sophus::SE
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值