📄 mapmaker.cc
字号:
} // Add the points' 3D position for(set<MapPoint*>::iterator it = sMapPoints.begin(); it!=sMapPoints.end(); it++) { int nBundleID = b.AddPoint((*it)->v3WorldPos); mPoint_BundleID[*it] = nBundleID; mBundleID_Point[nBundleID] = *it; } // Add the relevant point-in-keyframe measurements for(unsigned int i=0; i<mMap.vpKeyFrames.size(); i++) { if(mView_BundleID.count(mMap.vpKeyFrames[i]) == 0) continue; int nKF_BundleID = mView_BundleID[mMap.vpKeyFrames[i]]; for(meas_it it= mMap.vpKeyFrames[i]->mMeasurements.begin(); it!= mMap.vpKeyFrames[i]->mMeasurements.end(); it++) { if(mPoint_BundleID.count(it->first) == 0) continue; int nPoint_BundleID = mPoint_BundleID[it->first]; b.AddMeas(nKF_BundleID, nPoint_BundleID, it->second.v2RootPos, LevelScale(it->second.nLevel) * LevelScale(it->second.nLevel)); } } // Run the bundle adjuster. This returns the number of successful iterations int nAccepted = b.Compute(&mbBundleAbortRequested); if(nAccepted < 0) { // Crap: - LM Ran into a serious problem! // This is probably because the initial stereo was messed up. // Get rid of this map and start again! cout << "!! MapMaker: Cholesky failure in bundle adjust. " << endl << " The map is probably corrupt: Ditching the map. " << endl; mbResetRequested = true; return; } // Bundle adjustment did some updates, apply these to the map if(nAccepted > 0) { for(map<MapPoint*,int>::iterator itr = mPoint_BundleID.begin(); itr!=mPoint_BundleID.end(); itr++) itr->first->v3WorldPos = b.GetPoint(itr->second); for(map<KeyFrame*,int>::iterator itr = mView_BundleID.begin(); itr!=mView_BundleID.end(); itr++) itr->first->se3CfromW = b.GetCamera(itr->second); if(bRecent) mbBundleConverged_Recent = false; mbBundleConverged_Full = false; }; if(b.Converged()) { mbBundleConverged_Recent = true; if(!bRecent) mbBundleConverged_Full = true; } mbBundleRunning = false; mbBundleAbortRequested = false; // Handle outlier measurements: vector<pair<int,int> > vOutliers_PC_pair = b.GetOutlierMeasurements(); for(unsigned int i=0; i<vOutliers_PC_pair.size(); i++) { MapPoint *pp = mBundleID_Point[vOutliers_PC_pair[i].first]; KeyFrame *pk = mBundleID_View[vOutliers_PC_pair[i].second]; Measurement &m = pk->mMeasurements[pp]; if(pp->pMMData->GoodMeasCount() <= 2 || m.Source == Measurement::SRC_ROOT) // Is the original source kf considered an outlier? That's bad. pp->bBad = true; else { // Do we retry it? Depends where it came from!! if(m.Source == Measurement::SRC_TRACKER || m.Source == Measurement::SRC_EPIPOLAR) mvFailureQueue.push_back(pair<KeyFrame*,MapPoint*>(pk,pp)); else pp->pMMData->sNeverRetryKFs.insert(pk); pk->mMeasurements.erase(pp); pp->pMMData->sMeasurementKFs.erase(pk); } }}// Mapmaker's try-to-find-a-point-in-a-keyframe code. This is used to update// data association if a bad measurement was detected, or if a point// was never searched for in a keyframe in the first place. This operates// much like the tracker! So most of the code looks just like in // TrackerData.h.bool MapMaker::ReFind_Common(KeyFrame &k, MapPoint &p){ // abort if either a measurement is already in the map, or we've // decided that this point-kf combo is beyond redemption if(p.pMMData->sMeasurementKFs.count(&k) || p.pMMData->sNeverRetryKFs.count(&k)) return false; static PatchFinder Finder; Vector<3> v3Cam = k.se3CfromW*p.v3WorldPos; if(v3Cam[2] < 0.001) { p.pMMData->sNeverRetryKFs.insert(&k); return false; } Vector<2> v2ImPlane = project(v3Cam); if(v2ImPlane* v2ImPlane > mCamera.LargestRadiusInImage() * mCamera.LargestRadiusInImage()) { p.pMMData->sNeverRetryKFs.insert(&k); return false; } Vector<2> v2Image = mCamera.Project(v2ImPlane); if(mCamera.Invalid()) { p.pMMData->sNeverRetryKFs.insert(&k); return false; } ImageRef irImageSize = k.aLevels[0].im.size(); if(v2Image[0] < 0 || v2Image[1] < 0 || v2Image[0] > irImageSize[0] || v2Image[1] > irImageSize[1]) { p.pMMData->sNeverRetryKFs.insert(&k); return false; } Matrix<2> m2CamDerivs = mCamera.GetProjectionDerivs(); Finder.MakeTemplateCoarse(p, k.se3CfromW, m2CamDerivs); if(Finder.TemplateBad()) { p.pMMData->sNeverRetryKFs.insert(&k); return false; } bool bFound = Finder.FindPatchCoarse(ir(v2Image), k, 4); // Very tight search radius! if(!bFound) { p.pMMData->sNeverRetryKFs.insert(&k); return false; } // If we found something, generate a measurement struct and put it in the map Measurement m; m.nLevel = Finder.GetLevel(); m.Source = Measurement::SRC_REFIND; if(Finder.GetLevel() > 0) { Finder.MakeSubPixTemplate(); Finder.IterateSubPixToConvergence(k,8); m.v2RootPos = Finder.GetSubPixPos(); m.bSubPix = true; } else { m.v2RootPos = Finder.GetCoarsePosAsVector(); m.bSubPix = false; }; if(k.mMeasurements.count(&p)) { assert(0); // This should never happen, we checked for this at the start. } k.mMeasurements[&p] = m; p.pMMData->sMeasurementKFs.insert(&k); return true;}// A general data-association update for a single keyframe// Do this on a new key-frame when it's passed in by the trackerint MapMaker::ReFindInSingleKeyFrame(KeyFrame &k){ vector<MapPoint*> vToFind; for(unsigned int i=0; i<mMap.vpPoints.size(); i++) vToFind.push_back(mMap.vpPoints[i]); int nFoundNow = 0; for(unsigned int i=0; i<vToFind.size(); i++) if(ReFind_Common(k,*vToFind[i])) nFoundNow++; return nFoundNow;};// When new map points are generated, they're only created from a stereo pair// this tries to make additional measurements in other KFs which they might// be in.void MapMaker::ReFindNewlyMade(){ if(mqNewQueue.empty()) return; int nFound = 0; int nBad = 0; while(!mqNewQueue.empty() && mvpKeyFrameQueue.size() == 0) { MapPoint* pNew = mqNewQueue.front(); mqNewQueue.pop(); if(pNew->bBad) { nBad++; continue; } for(unsigned int i=0; i<mMap.vpKeyFrames.size(); i++) if(ReFind_Common(*mMap.vpKeyFrames[i], *pNew)) nFound++; }};// Dud measurements get a second chance.void MapMaker::ReFindFromFailureQueue(){ if(mvFailureQueue.size() == 0) return; sort(mvFailureQueue.begin(), mvFailureQueue.end()); vector<pair<KeyFrame*, MapPoint*> >::iterator it; int nFound=0; for(it = mvFailureQueue.begin(); it!=mvFailureQueue.end(); it++) if(ReFind_Common(*it->first, *it->second)) nFound++; mvFailureQueue.erase(mvFailureQueue.begin(), it);};// Is the tracker's camera pose in cloud-cuckoo land?bool MapMaker::IsDistanceToNearestKeyFrameExcessive(KeyFrame &kCurrent){ return DistToNearestKeyFrame(kCurrent) > mdWiggleScale * 10.0;}// Find a dominant plane in the map, find an SE3 to put it as the z=0 planeSE3 MapMaker::CalcPlaneAligner(){ unsigned int nPoints = mMap.vpPoints.size(); if(nPoints < 10) { cout << " MapMaker: CalcPlane: too few points to calc plane." << endl; return SE3(); }; int nRansacs = GV2.GetInt("MapMaker.PlaneAlignerRansacs", 100, HIDDEN|SILENT); Vector<3> v3BestMean; Vector<3> v3BestNormal; double dBestDistSquared = 9999999999999999.9; for(int i=0; i<nRansacs; i++) { int nA = rand()%nPoints; int nB = nA; int nC = nA; while(nB == nA) nB = rand()%nPoints; while(nC == nA || nC==nB) nC = rand()%nPoints; Vector<3> v3Mean = 0.33333333 * (mMap.vpPoints[nA]->v3WorldPos + mMap.vpPoints[nB]->v3WorldPos + mMap.vpPoints[nC]->v3WorldPos); Vector<3> v3CA = mMap.vpPoints[nC]->v3WorldPos - mMap.vpPoints[nA]->v3WorldPos; Vector<3> v3BA = mMap.vpPoints[nB]->v3WorldPos - mMap.vpPoints[nA]->v3WorldPos; Vector<3> v3Normal = v3CA ^ v3BA; if(v3Normal * v3Normal == 0) continue; normalize(v3Normal); double dSumError = 0.0; for(unsigned int i=0; i<nPoints; i++) { Vector<3> v3Diff = mMap.vpPoints[i]->v3WorldPos - v3Mean; double dDistSq = v3Diff * v3Diff; if(dDistSq == 0.0) continue; double dNormDist = fabs(v3Diff * v3Normal); if(dNormDist > 0.05) dNormDist = 0.05; dSumError += dNormDist; } if(dSumError < dBestDistSquared) { dBestDistSquared = dSumError; v3BestMean = v3Mean; v3BestNormal = v3Normal; } } // Done the ransacs, now collect the supposed inlier set vector<Vector<3> > vv3Inliers; for(unsigned int i=0; i<nPoints; i++) { Vector<3> v3Diff = mMap.vpPoints[i]->v3WorldPos - v3BestMean; double dDistSq = v3Diff * v3Diff; if(dDistSq == 0.0) continue; double dNormDist = fabs(v3Diff * v3BestNormal); if(dNormDist < 0.05) vv3Inliers.push_back(mMap.vpPoints[i]->v3WorldPos); } // With these inliers, calculate mean and cov Vector<3> v3MeanOfInliers; Zero(v3MeanOfInliers); for(unsigned int i=0; i<vv3Inliers.size(); i++) v3MeanOfInliers+=vv3Inliers[i]; v3MeanOfInliers *= (1.0 / vv3Inliers.size()); Matrix<3> m3Cov; Zero(m3Cov); for(unsigned int i=0; i<vv3Inliers.size(); i++) { Vector<3> v3Diff = vv3Inliers[i] - v3MeanOfInliers; m3Cov += v3Diff.as_col() * v3Diff.as_row(); }; // Find the principal component with the minimal variance: this is the plane normal SymEigen<3> sym(m3Cov); Vector<3> v3Normal = sym.get_evectors()[0]; // Use the version of the normal which points towards the cam center if(v3Normal[2] > 0) v3Normal *= -1.0; Matrix<3> m3Rot; Identity(m3Rot); m3Rot[2] = v3Normal; m3Rot[0] = m3Rot[0] - (v3Normal * (m3Rot[0] * v3Normal)); normalize(m3Rot[0]); m3Rot[1] = m3Rot[2] ^ m3Rot[0]; SE3 se3Aligner; se3Aligner.get_rotation() = m3Rot; Vector<3> v3RMean = se3Aligner * v3MeanOfInliers; se3Aligner.get_translation() = -v3RMean; return se3Aligner;}void MapMaker::GUICommandCallBack(void* ptr, string sCommand, string sParams){ Command c; c.sCommand = sCommand; c.sParams = sParams; ((MapMaker*) ptr)->mvQueuedCommands.push_back(c);}void MapMaker::GUICommandHandler(string sCommand, string sParams) // Called by the callback func..{ if(sCommand=="SaveMap") { cout << " MapMaker: Saving the map.... " << endl; ofstream ofs("map.dump"); for(unsigned int i=0; i<mMap.vpPoints.size(); i++) { ofs << mMap.vpPoints[i]->v3WorldPos << " "; ofs << mMap.vpPoints[i]->nSourceLevel << endl; } ofs.close(); for(unsigned int i=0; i<mMap.vpKeyFrames.size(); i++) { ostringstream ost1; ost1 << "keyframes/" << i << ".jpg";// img_save(mMap.vpKeyFrames[i]->aLevels[0].im, ost1.str()); ostringstream ost2; ost2 << "keyframes/" << i << ".info"; ofstream ofs2; ofs2.open(ost2.str().c_str()); ofs2 << mMap.vpKeyFrames[i]->se3CfromW << endl; ofs2.close(); } cout << " ... done saving map." << endl; return; } cout << "! MapMaker::GUICommandHandler: unhandled command "<< sCommand << endl; exit(1);};
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -