📄 mapmaker.cc
字号:
};// Rotates/translates the whole map and all keyframesvoid MapMaker::ApplyGlobalTransformationToMap(SE3 se3NewFromOld){ for(unsigned int i=0; i<mMap.vpKeyFrames.size(); i++) mMap.vpKeyFrames[i]->se3CfromW = mMap.vpKeyFrames[i]->se3CfromW * se3NewFromOld.inverse(); SO3 so3Rot = se3NewFromOld.get_rotation(); for(unsigned int i=0; i<mMap.vpPoints.size(); i++) { mMap.vpPoints[i]->v3WorldPos = se3NewFromOld * mMap.vpPoints[i]->v3WorldPos; mMap.vpPoints[i]->RefreshPixelVectors(); }}// Applies a global scale factor to the mapvoid MapMaker::ApplyGlobalScaleToMap(double dScale){ for(unsigned int i=0; i<mMap.vpKeyFrames.size(); i++) mMap.vpKeyFrames[i]->se3CfromW.get_translation() *= dScale; for(unsigned int i=0; i<mMap.vpPoints.size(); i++) { (*mMap.vpPoints[i]).v3WorldPos *= dScale; (*mMap.vpPoints[i]).v3PixelRight_W *= dScale; (*mMap.vpPoints[i]).v3PixelDown_W *= dScale; (*mMap.vpPoints[i]).RefreshPixelVectors(); }}// The tracker entry point for adding a new keyframe;// the tracker thread doesn't want to hang about, so // just dumps it on the top of the mapmaker's queue to // be dealt with later, and return.void MapMaker::AddKeyFrame(KeyFrame &k){ KeyFrame *pK = new KeyFrame; *pK = k; mvpKeyFrameQueue.push_back(pK); if(mbBundleRunning) // Tell the mapmaker to stop doing low-priority stuff and concentrate on this KF first. mbBundleAbortRequested = true;}// Mapmaker's code to handle incoming key-frames.void MapMaker::AddKeyFrameFromTopOfQueue(){ if(mvpKeyFrameQueue.size() == 0) return; KeyFrame *pK = mvpKeyFrameQueue[0]; mvpKeyFrameQueue.erase(mvpKeyFrameQueue.begin()); pK->MakeKeyFrame_Rest(); mMap.vpKeyFrames.push_back(pK); // Any measurements? Update the relevant point's measurement counter status map for(meas_it it = pK->mMeasurements.begin(); it!=pK->mMeasurements.end(); it++) { it->first->pMMData->sMeasurementKFs.insert(pK); it->second.Source = Measurement::SRC_TRACKER; } // And maybe we missed some - this now adds to the map itself, too. ReFindInSingleKeyFrame(*pK); AddSomeMapPoints(3); // .. and add more map points by epipolar search. AddSomeMapPoints(0); AddSomeMapPoints(1); AddSomeMapPoints(2); mbBundleConverged_Full = false; mbBundleConverged_Recent = false;}// Tries to make a new map point out of a single candidate point// by searching for that point in another keyframe, and triangulating// if a match is found.bool MapMaker::AddPointEpipolar(KeyFrame &kSrc, KeyFrame &kTarget, int nLevel, int nCandidate){ static Image<Vector<2> > imUnProj; static bool bMadeCache = false; if(!bMadeCache) { imUnProj.resize(kSrc.aLevels[0].im.size()); ImageRef ir; do imUnProj[ir] = mCamera.UnProject(ir); while(ir.next(imUnProj.size())); bMadeCache = true; } int nLevelScale = LevelScale(nLevel); Candidate &candidate = kSrc.aLevels[nLevel].vCandidates[nCandidate]; ImageRef irLevelPos = candidate.irLevelPos; Vector<2> v2RootPos = LevelZeroPos(irLevelPos, nLevel); Vector<3> v3Ray_SC = unproject(mCamera.UnProject(v2RootPos)); normalize(v3Ray_SC); Vector<3> v3LineDirn_TC = kTarget.se3CfromW.get_rotation() * (kSrc.se3CfromW.get_rotation().inverse() * v3Ray_SC); // Restrict epipolar search to a relatively narrow depth range // to increase reliability double dMean = kSrc.dSceneDepthMean; double dSigma = kSrc.dSceneDepthSigma; double dStartDepth = max(0.1, dMean - dSigma); double dEndDepth = min(4.0, dMean + dSigma); Vector<3> v3CamCenter_TC = kTarget.se3CfromW * kSrc.se3CfromW.inverse().get_translation(); // The camera end Vector<3> v3RayStart_TC = v3CamCenter_TC + dStartDepth * v3LineDirn_TC; // the far-away end Vector<3> v3RayEnd_TC = v3CamCenter_TC + dEndDepth * v3LineDirn_TC; // the far-away end if(v3RayEnd_TC[2] <= v3RayStart_TC[2]) // it's highly unlikely that we'll manage to get anything out if we're facing backwards wrt the other camera's view-ray return false; if(v3RayEnd_TC[2] <= 0.0 ) return false; if(v3RayStart_TC[2] <= 0.0) v3RayStart_TC += v3LineDirn_TC * (0.001 - v3RayStart_TC[2] / v3LineDirn_TC[2]); Vector<2> v2A = project(v3RayStart_TC); Vector<2> v2B = project(v3RayEnd_TC); Vector<2> v2AlongProjectedLine = v2A-v2B; if(v2AlongProjectedLine * v2AlongProjectedLine < 0.00000001) { cout << "v2AlongProjectedLine too small." << endl; return false; } normalize(v2AlongProjectedLine); Vector<2> v2Normal; v2Normal[0] = v2AlongProjectedLine[1]; v2Normal[1] = -v2AlongProjectedLine[0]; double dNormDist = v2A * v2Normal; if(fabs(dNormDist) > mCamera.LargestRadiusInImage() ) return false; double dMinLen = min(v2AlongProjectedLine * v2A, v2AlongProjectedLine * v2B) - 0.05; double dMaxLen = max(v2AlongProjectedLine * v2A, v2AlongProjectedLine * v2B) + 0.05; if(dMinLen < -2.0) dMinLen = -2.0; if(dMaxLen < -2.0) dMaxLen = -2.0; if(dMinLen > 2.0) dMinLen = 2.0; if(dMaxLen > 2.0) dMaxLen = 2.0; // Find current-frame corners which might match this PatchFinder Finder; Finder.MakeTemplateCoarseNoWarp(kSrc, nLevel, irLevelPos); if(Finder.TemplateBad()) return false; vector<Vector<2> > &vv2Corners = kTarget.aLevels[nLevel].vImplaneCorners; vector<ImageRef> &vIR = kTarget.aLevels[nLevel].vCorners; if(!kTarget.aLevels[nLevel].bImplaneCornersCached) { for(unsigned int i=0; i<vIR.size(); i++) // over all corners in target img.. vv2Corners.push_back(imUnProj[ir(LevelZeroPos(vIR[i], nLevel))]); kTarget.aLevels[nLevel].bImplaneCornersCached = true; } int nBest = -1; int nBestZMSSD = Finder.mnMaxSSD + 1; double dMaxDistDiff = mCamera.OnePixelDist() * (4.0 + 1.0 * nLevelScale); double dMaxDistSq = dMaxDistDiff * dMaxDistDiff; for(unsigned int i=0; i<vv2Corners.size(); i++) // over all corners in target img.. { Vector<2> v2Im = vv2Corners[i]; double dDistDiff = dNormDist - v2Im * v2Normal; if(dDistDiff * dDistDiff > dMaxDistSq) continue; // skip if not along epi line if(v2Im * v2AlongProjectedLine < dMinLen) continue; // skip if not far enough along line if(v2Im * v2AlongProjectedLine > dMaxLen) continue; // or too far int nZMSSD = Finder.ZMSSDAtPoint(kTarget.aLevels[nLevel].im, vIR[i]); if(nZMSSD < nBestZMSSD) { nBest = i; nBestZMSSD = nZMSSD; } } if(nBest == -1) return false; // Nothing found. // Found a likely candidate along epipolar ray Finder.MakeSubPixTemplate(); Finder.SetSubPixPos(LevelZeroPos(vIR[nBest], nLevel)); bool bSubPixConverges = Finder.IterateSubPixToConvergence(kTarget,10); if(!bSubPixConverges) return false; // Now triangulate the 3d point... Vector<3> v3New; v3New = kTarget.se3CfromW.inverse() * ReprojectPoint(kSrc.se3CfromW * kTarget.se3CfromW.inverse(), mCamera.UnProject(v2RootPos), mCamera.UnProject(Finder.GetSubPixPos())); MapPoint *pNew = new MapPoint; pNew->v3WorldPos = v3New; pNew->pMMData = new MapMakerData(); // Patch source stuff: pNew->pPatchSourceKF = &kSrc; pNew->nSourceLevel = nLevel; pNew->v3Normal_NC = (make_Vector, 0,0,-1); pNew->irCenter = irLevelPos; pNew->v3Center_NC = unproject(mCamera.UnProject(v2RootPos)); pNew->v3OneRightFromCenter_NC = unproject(mCamera.UnProject(v2RootPos + vec(ImageRef(nLevelScale,0)))); pNew->v3OneDownFromCenter_NC = unproject(mCamera.UnProject(v2RootPos + vec(ImageRef(0,nLevelScale)))); normalize(pNew->v3Center_NC); normalize(pNew->v3OneDownFromCenter_NC); normalize(pNew->v3OneRightFromCenter_NC); pNew->RefreshPixelVectors(); mMap.vpPoints.push_back(pNew); mqNewQueue.push(pNew); Measurement m; m.Source = Measurement::SRC_ROOT; m.v2RootPos = v2RootPos; m.nLevel = nLevel; m.bSubPix = true; kSrc.mMeasurements[pNew] = m; m.Source = Measurement::SRC_EPIPOLAR; m.v2RootPos = Finder.GetSubPixPos(); kTarget.mMeasurements[pNew] = m; pNew->pMMData->sMeasurementKFs.insert(&kSrc); pNew->pMMData->sMeasurementKFs.insert(&kTarget); return true;}double MapMaker::KeyFrameLinearDist(KeyFrame &k1, KeyFrame &k2){ Vector<3> v3KF1_CamPos = k1.se3CfromW.inverse().get_translation(); Vector<3> v3KF2_CamPos = k2.se3CfromW.inverse().get_translation(); Vector<3> v3Diff = v3KF2_CamPos - v3KF1_CamPos; double dDist = sqrt(v3Diff * v3Diff); return dDist;}vector<KeyFrame*> MapMaker::NClosestKeyFrames(KeyFrame &k, unsigned int N){ vector<pair<double, KeyFrame* > > vKFandScores; for(unsigned int i=0; i<mMap.vpKeyFrames.size(); i++) { if(mMap.vpKeyFrames[i] == &k) continue; double dDist = KeyFrameLinearDist(k, *mMap.vpKeyFrames[i]); vKFandScores.push_back(make_pair(dDist, mMap.vpKeyFrames[i])); } if(N > vKFandScores.size()) N = vKFandScores.size(); partial_sort(vKFandScores.begin(), vKFandScores.begin() + N, vKFandScores.end()); vector<KeyFrame*> vResult; for(unsigned int i=0; i<N; i++) vResult.push_back(vKFandScores[i].second); return vResult;}KeyFrame* MapMaker::ClosestKeyFrame(KeyFrame &k){ double dClosestDist = 9999999999.9; int nClosest = -1; for(unsigned int i=0; i<mMap.vpKeyFrames.size(); i++) { if(mMap.vpKeyFrames[i] == &k) continue; double dDist = KeyFrameLinearDist(k, *mMap.vpKeyFrames[i]); if(dDist < dClosestDist) { dClosestDist = dDist; nClosest = i; } } assert(nClosest != -1); return mMap.vpKeyFrames[nClosest];}double MapMaker::DistToNearestKeyFrame(KeyFrame &kCurrent){ KeyFrame *pClosest = ClosestKeyFrame(kCurrent); double dDist = KeyFrameLinearDist(kCurrent, *pClosest); return dDist;}bool MapMaker::NeedNewKeyFrame(KeyFrame &kCurrent){ KeyFrame *pClosest = ClosestKeyFrame(kCurrent); double dDist = KeyFrameLinearDist(kCurrent, *pClosest); dDist *= (1.0 / kCurrent.dSceneDepthMean); if(dDist > GV2.GetDouble("MapMaker.MaxKFDistWiggleMult",1.0,SILENT) * mdWiggleScale) return true; return false;}// Perform bundle adjustment on all keyframes, all map pointsvoid MapMaker::BundleAdjustAll(){ // construct the sets of kfs/points to be adjusted: // in this case, all of them set<KeyFrame*> sAdj; set<KeyFrame*> sFixed; for(unsigned int i=0; i<mMap.vpKeyFrames.size(); i++) if(mMap.vpKeyFrames[i]->bFixed) sFixed.insert(mMap.vpKeyFrames[i]); else sAdj.insert(mMap.vpKeyFrames[i]); set<MapPoint*> sMapPoints; for(unsigned int i=0; i<mMap.vpPoints.size();i++) sMapPoints.insert(mMap.vpPoints[i]); BundleAdjust(sAdj, sFixed, sMapPoints, false);}// Peform a local bundle adjustment which only adjusts// recently added key-framesvoid MapMaker::BundleAdjustRecent(){ if(mMap.vpKeyFrames.size() < 8) { // Ignore this unless map is big enough mbBundleConverged_Recent = true; return; } // First, make a list of the keyframes we want adjusted in the adjuster. // This will be the last keyframe inserted, and its four nearest neighbors set<KeyFrame*> sAdjustSet; KeyFrame *pkfNewest = mMap.vpKeyFrames.back(); sAdjustSet.insert(pkfNewest); vector<KeyFrame*> vClosest = NClosestKeyFrames(*pkfNewest, 4); for(int i=0; i<4; i++) if(vClosest[i]->bFixed == false) sAdjustSet.insert(vClosest[i]); // Now we find the set of features which they contain. set<MapPoint*> sMapPoints; for(set<KeyFrame*>::iterator iter = sAdjustSet.begin(); iter!=sAdjustSet.end(); iter++) { map<MapPoint*,Measurement> &mKFMeas = (*iter)->mMeasurements; for(meas_it jiter = mKFMeas.begin(); jiter!= mKFMeas.end(); jiter++) sMapPoints.insert(jiter->first); }; // Finally, add all keyframes which measure above points as fixed keyframes set<KeyFrame*> sFixedSet; for(vector<KeyFrame*>::iterator it = mMap.vpKeyFrames.begin(); it!=mMap.vpKeyFrames.end(); it++) { if(sAdjustSet.count(*it)) continue; bool bInclude = false; for(meas_it jiter = (*it)->mMeasurements.begin(); jiter!= (*it)->mMeasurements.end(); jiter++) if(sMapPoints.count(jiter->first)) { bInclude = true; break; } if(bInclude) sFixedSet.insert(*it); } BundleAdjust(sAdjustSet, sFixedSet, sMapPoints, true);}// Common bundle adjustment code. This creates a bundle-adjust instance, populates it, and runs it.void MapMaker::BundleAdjust(set<KeyFrame*> sAdjustSet, set<KeyFrame*> sFixedSet, set<MapPoint*> sMapPoints, bool bRecent){ Bundle b(mCamera); // Our bundle adjuster mbBundleRunning = true; mbBundleRunningIsRecent = bRecent; // The bundle adjuster does different accounting of keyframes and map points; // Translation maps are stored: map<MapPoint*, int> mPoint_BundleID; map<int, MapPoint*> mBundleID_Point; map<KeyFrame*, int> mView_BundleID; map<int, KeyFrame*> mBundleID_View; // Add the keyframes' poses to the bundle adjuster. Two parts: first nonfixed, then fixed. for(set<KeyFrame*>::iterator it = sAdjustSet.begin(); it!= sAdjustSet.end(); it++) { int nBundleID = b.AddCamera((*it)->se3CfromW, (*it)->bFixed); mView_BundleID[*it] = nBundleID; mBundleID_View[nBundleID] = *it; } for(set<KeyFrame*>::iterator it = sFixedSet.begin(); it!= sFixedSet.end(); it++) { int nBundleID = b.AddCamera((*it)->se3CfromW, true); mView_BundleID[*it] = nBundleID; mBundleID_View[nBundleID] = *it;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -