Пример #1
0
// 先从历史数据中选出 K 个最近参考帧 + ALL 关键帧进行 match
// 选取一个帧ptr 序列
int TrackRunner::runKeyStep() {


	//printf("////////////////////////////////////////////\n");
	printf("//////////// idxImgCur: %06d ////////////\n",idxImgCur);
	//printf("////////////////////////////////////////////\n");

	TIME_BEGIN("MainLoop");

		TIME_BEGIN("FeatureDetect");
		/** TODO: 可以考虑 多线程并行计算,然后在这里放个 wait
		 *		  另外那个线程算好一个放个 signal
		 */
		// 读取当前帧数据
		FeatureState* ptrCurFeature = new FeatureState(idxImgCur);
		ptrCurFeature->detect(CFG_iMaxFeatures);
		TIME_END("FeatureDetect");
		
		//showImage(ptrCurFeature);

		// 确定当前帧需要比较的 历史帧集合
		std::vector<FeatureState*> vecKeyList;
		/** TODO: 可能需要靠 视觉磁带模型预估closure */
		vecKeyList = selectKeySequence(idxImgCur);

		// 对每一对历史-当前帧 进行运动估算
		std::vector<MotionState> vecCurMotions( vecKeyList.size() );
		

		// 调用 FrameParser 分别处理 参考帧<->当前帧 的 matR和MatT
		TIME_BEGIN(cv::format("Match&Motion[%d]", vecKeyList.size()));
#pragma omp parallel for
		for (int idx = 0; idx < vecKeyList.size();idx++) {
			FeatureState* ptrFeature = vecKeyList[idx];

			/** TODO: 考虑对不同情况设置不同过滤规则 */
			// 初始化 帧间处理器
			FrameParser fparser(ptrFeature, ptrCurFeature);
			fparser.match(CFG_dOpticalFlowThreshold);

			// 对极几何 计算运动matR和matT
			bool motionStatus = fparser.computeMotion(vecCurMotions[idx]);
			vecEnableIdxs[idxImgCur] = cntRunOk;
			// 运动参数计算失败
			if (motionStatus == false) {
				printf("运动参数计算失败\n");
				//TODO: 解不出来默认 运动,然后 强制一个默认尺度
				// 以上这句话只能用在 iDequeNumber == 1的时候,否则会有问题
				//vecCurMotions[idx].setInited(true);
				////按照CFG设置
				//vecCurMotions[idx].setScale(1.65f / CFG_dScaleRatioErrorDefault, true);
				//vecCurMotions[idx].errType.set(0);
				continue;
			}

			// 位移旋转限值
			if (CFG_bIsLimitRotationDiff && limitRotationDiff(vecCurMotions[idx],CFG_dRotationDiffLimit) == false) {
				printf("旋转跳\n");
				vecCurMotions[idx].setInited(false);
				

				continue;
			}

			// 尺度估算开启
			ScaleEstimator sEstimator;
			sEstimator.updateMotion(&vecCurMotions[idx]);
			double curScale = sEstimator.computeScaleTransform();

			if (curScale <= 0) {
				printf("尺度没算出来\n");
				curScale = 200;
			}
			// 尺度增量限制
			// 如果被跳帧了,跳帧后出现一个多间隔值,在这个间隔值之后,再允许任意一个。
			// 如果连跳多帧,那
			if (limitScaleDiff(vecCurMotions[idx], curScale, CFG_dScaleInvIncreaseDiffLimit) == false) {
				vecCurMotions[idx].setInited( false );
				
				continue;
			}
			int idxDelta = vecCurMotions[idx].getIdxImg(1) - vecCurMotions[idx].getIdxImg(0);
			if (CFG_iPreAverageFilter > 0) {
				auto& qDist = cDrawer.qDist;
				auto iter =  qDist.rbegin();
				double aver = 0.0f;
				int cnt = 0;
				for (; cnt < CFG_iPreAverageFilter && iter != qDist.rend(); iter++, cnt++) {
					printf("%d %f\n", idxImgCur, *iter);
					aver += *iter;
				}
				aver += 1.65f / curScale / idxDelta;
				aver /= cnt + 1;
				//可以做限制 只限制上升或者只限制下降
				//if (aver < 1.65f / curScale / idxDelta) {
				//	curScale = 1.65 / aver / idxDelta;
				//}
			}

			/** TODO: 这里需要一个合适的尺度评价 */
			
			if ((curScale*idxDelta < CFG_dScaleRatioLimitBottom /*/ idxDelta*/ || curScale*idxDelta > CFG_dScaleRatioLimitTop)) {
				
				printf("Scale LIMIT %d-%d:%f %f\n", vecCurMotions[idx].getIdxImg(0), vecCurMotions[idx].getIdxImg(1), curScale, 1.65f / curScale);
				if (curScale*idxDelta < CFG_dScaleRatioLimitBottom) {
					curScale = CFG_dScaleRatioLimitBottom / idxDelta;
					vecCurMotions[idx].errType.set(Const::Error::LimitSCALEPEAK);
				}
				else {
					curScale = CFG_dScaleRatioLimitTop / idxDelta;
					vecCurMotions[idx].errType.set(Const::Error::LimitSCALEPEAK);
				}

				
			}


			// 目前使用 GroundTruth的 运动尺度,因此目前误差只在旋转角度上
			if (CFG_bIsUseGroundTruthDistance) {
				vecCurMotions[idx].setScale(1.65f / cv::norm(pHelper.getPosition(vecCurMotions[idx].getIdxImg(1), vecCurMotions[idx].getIdxImg(0))));
				//vecCurMotions[idx].scale = 1.65f / cv::norm(pVisio.getPosition(vecCurMotions[idx].idxImg[1], vecCurMotions[idx].idxImg[0]));
			}
			else {
				vecCurMotions[idx].setScale(curScale);
			}
			//vecCurMotions[idx]._matR_ = vecCurMotions[idx].matR * vecPoses[vecCurMotions[idx].idxImg[0]].dir3;

		}
		TIME_END(cv::format("Match&Motion[%d]", vecKeyList.size()));

		if ( idxImgCur <= 2 || vecEnableIdxs[idxImgCur-1] > 0) {
			curError.set(0);
		}
		else {
			printf("Pre Error: %d\n", curError.get());
		}
			
		for (auto& motion : vecCurMotions) {
			curError.set(motion.errType, false);
		}

		//按照一定规则过滤 vecCurMotions,目前先过滤掉 inited为false的
		int cntValid = filterMotions(vecCurMotions,0);

		// 如果过滤完没有了, 就跳帧
		if (cntValid < 1) {
			delete ptrCurFeature;
			vecEnableIdxs[idxImgCur] = 0;
		}
		else {
			/** TODO: 对算出来的这么多有效的, 1是要判定closure; 2是要综合(取平均哈哈哈)运动状态 */
			TIME_BEGIN("PoseEstimate");

			// 对于计算出来的每对Motion, 应用该运动
			std::vector<PoseState> vecEstiPoses;
			for (int idx = 0; idx < vecCurMotions.size(); idx++) {
				MotionState& curMotion = vecCurMotions[idx];
				if (curMotion.getInited() == true) {
					// 对vecPose的对应位姿,应用Motion得到 vecEstiPoses新位姿
					vecEstiPoses.push_back(vecPoses[curMotion.getIdxImg(0)].move(curMotion));

					//加入骨架
					vecMotionLinks[curMotion.getIdxImg(1)].insert(std::make_pair(curMotion.getIdxImg(0), curMotion));
				}
			}
			

			/** TODO: 新的多位姿选择方法 */
			PoseState curPoseState = PoseState::calcAverage(vecEstiPoses);
			curPoseState.errType.set(curError);

			// 更新队列和关键帧
			updateKeyList(ptrCurFeature);
			cntRunOk++;

			vecPoses[idxImgCur] = curPoseState;

			TIME_END("PoseEstimate");
			//if (CFG_bIsLogGlobal)
			std::cout << vecPoses[idxImgCur] << std::endl;
			// 画布画出当前位姿, 以及GroundTruth实际路径
			// 内部修改 vecPoses 的数据,不能用 curPoseState 了
			cDrawer.drawCanvas(vecPoses[idxImgCur]);

			/*
			 *	本来用于测试 梯度下降优化方法,在计算完50个点之后执行
			 *  现废弃
			 */
			if (false && idxImgCur == 50) {
				printf("开始调整\n");

				Skeleton skl;
				skl.initData(vecPoses, vecMotionLinks);
				double err = skl.calcError();
				double preErr = err;
				printf("i=%d err=%f\n", -1, err);
				if (CFG_bIsLogGlobal)
				std::cout << skl.vecX[0] << std::endl;
				if (CFG_bIsLogGlobal)
				std::cout << skl.vecX[1] << std::endl;
				for (int i = 0; i < 1000; i++) {
					skl.calcDiff();
					skl.merge(1e-3);
					skl.fixMatrix();
					err = skl.calcError();
					
					printf("i=%d err=%f\n", i, err);
					if (CFG_bIsLogGlobal)
					std::cout << skl.vecX[0] << std::endl;
					if (CFG_bIsLogGlobal)
					std::cout << skl.vecX[1] << std::endl;
					if (preErr< err) {
						break;
					}
					preErr = err;
				}
				
				for (int i = idxImgBegin + 1; i < idxImgCur; i++) {
					if ( skl.vecX[i].rows) {
						PoseState t(i);
						t.setInited( true );
						t.pos.x = skl.vecX[i].at<double>(0, 0);
						t.pos.y = skl.vecX[i].at<double>(1, 0);
						t.pos.z = skl.vecX[i].at<double>(2, 0);
						if (CFG_bIsLogGlobal)
						std::cout << t.pos << std::endl;
					}

				}
				cv::waitKey();

				printf("结束调整\n");
			}


		}

	TIME_END("MainLoop");

	return ++idxImgCur;
}