/** * This file is part of ORB-SLAM3 * * Copyright (C) 2017-2021 Carlos Campos, Richard Elvira, Juan J. Gómez Rodríguez, José M.M. Montiel and Juan D. Tardós, University of Zaragoza. * Copyright (C) 2014-2016 Raúl Mur-Artal, José M.M. Montiel and Juan D. Tardós, University of Zaragoza. * * ORB-SLAM3 is free software: you can redistribute it and/or modify it under the terms of the GNU General Public * License as published by the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * ORB-SLAM3 is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even * the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License along with ORB-SLAM3. * If not, see . */ #include "KeyFrame.h" #include "Converter.h" #include "ImuTypes.h" #include namespace ORB_SLAM3 { long unsigned int KeyFrame::nNextId=0; KeyFrame::KeyFrame(): mnFrameId(0), mTimeStamp(0), mnGridCols(FRAME_GRID_COLS), mnGridRows(FRAME_GRID_ROWS), mfGridElementWidthInv(0), mfGridElementHeightInv(0), mnTrackReferenceForFrame(0), mnFuseTargetForKF(0), mnBALocalForKF(0), mnBAFixedForKF(0), mnBALocalForMerge(0), mnLoopQuery(0), mnLoopWords(0), mnRelocQuery(0), mnRelocWords(0), mnMergeQuery(0), mnMergeWords(0), mnBAGlobalForKF(0), fx(0), fy(0), cx(0), cy(0), invfx(0), invfy(0), mnPlaceRecognitionQuery(0), mnPlaceRecognitionWords(0), mPlaceRecognitionScore(0), mbf(0), mb(0), mThDepth(0), N(0), mvKeys(static_cast >(NULL)), mvKeysUn(static_cast >(NULL)), mvuRight(static_cast >(NULL)), mvDepth(static_cast >(NULL)), mnScaleLevels(0), mfScaleFactor(0), mfLogScaleFactor(0), mvScaleFactors(0), mvLevelSigma2(0), mvInvLevelSigma2(0), mnMinX(0), mnMinY(0), mnMaxX(0), mnMaxY(0), mPrevKF(static_cast(NULL)), mNextKF(static_cast(NULL)), mbFirstConnection(true), mpParent(NULL), mbNotErase(false), mbToBeErased(false), mbBad(false), mHalfBaseline(0), mbCurrentPlaceRecognition(false), mnMergeCorrectedForKF(0), NLeft(0),NRight(0), mnNumberOfOpt(0), mbHasVelocity(false) { } KeyFrame::KeyFrame(Frame &F, Map *pMap, KeyFrameDatabase *pKFDB): bImu(pMap->isImuInitialized()), mnFrameId(F.mnId), mTimeStamp(F.mTimeStamp), mnGridCols(FRAME_GRID_COLS), mnGridRows(FRAME_GRID_ROWS), mfGridElementWidthInv(F.mfGridElementWidthInv), mfGridElementHeightInv(F.mfGridElementHeightInv), mnTrackReferenceForFrame(0), mnFuseTargetForKF(0), mnBALocalForKF(0), mnBAFixedForKF(0), mnBALocalForMerge(0), mnLoopQuery(0), mnLoopWords(0), mnRelocQuery(0), mnRelocWords(0), mnBAGlobalForKF(0), mnPlaceRecognitionQuery(0), mnPlaceRecognitionWords(0), mPlaceRecognitionScore(0), fx(F.fx), fy(F.fy), cx(F.cx), cy(F.cy), invfx(F.invfx), invfy(F.invfy), mbf(F.mbf), mb(F.mb), mThDepth(F.mThDepth), N(F.N), mvKeys(F.mvKeys), mvKeysUn(F.mvKeysUn), mvuRight(F.mvuRight), mvDepth(F.mvDepth), mDescriptors(F.mDescriptors.clone()), mBowVec(F.mBowVec), mFeatVec(F.mFeatVec), mnScaleLevels(F.mnScaleLevels), mfScaleFactor(F.mfScaleFactor), mfLogScaleFactor(F.mfLogScaleFactor), mvScaleFactors(F.mvScaleFactors), mvLevelSigma2(F.mvLevelSigma2), mvInvLevelSigma2(F.mvInvLevelSigma2), mnMinX(F.mnMinX), mnMinY(F.mnMinY), mnMaxX(F.mnMaxX), mnMaxY(F.mnMaxY), mK_(F.mK_), mPrevKF(NULL), mNextKF(NULL), mpImuPreintegrated(F.mpImuPreintegrated), mImuCalib(F.mImuCalib), mvpMapPoints(F.mvpMapPoints), mpKeyFrameDB(pKFDB), mpORBvocabulary(F.mpORBvocabulary), mbFirstConnection(true), mpParent(NULL), mDistCoef(F.mDistCoef), mbNotErase(false), mnDataset(F.mnDataset), mbToBeErased(false), mbBad(false), mHalfBaseline(F.mb/2), mpMap(pMap), mbCurrentPlaceRecognition(false), mNameFile(F.mNameFile), mnMergeCorrectedForKF(0), mpCamera(F.mpCamera), mpCamera2(F.mpCamera2), mvLeftToRightMatch(F.mvLeftToRightMatch),mvRightToLeftMatch(F.mvRightToLeftMatch), mTlr(F.GetRelativePoseTlr()), mvKeysRight(F.mvKeysRight), NLeft(F.Nleft), NRight(F.Nright), mTrl(F.GetRelativePoseTrl()), mnNumberOfOpt(0), mbHasVelocity(false) { mnId=nNextId++; mGrid.resize(mnGridCols); if(F.Nleft != -1) mGridRight.resize(mnGridCols); for(int i=0; iGetId(); } void KeyFrame::ComputeBoW() { if(mBowVec.empty() || mFeatVec.empty()) { vector vCurrentDesc = Converter::toDescriptorVector(mDescriptors); // Feature vector associate features with nodes in the 4th level (from leaves up) // We assume the vocabulary tree has 6 levels, change the 4 otherwise mpORBvocabulary->transform(vCurrentDesc,mBowVec,mFeatVec,4); } } void KeyFrame::SetPose(const Sophus::SE3f &Tcw) { unique_lock lock(mMutexPose); mTcw = Tcw; mRcw = mTcw.rotationMatrix(); mTwc = mTcw.inverse(); mRwc = mTwc.rotationMatrix(); if (mImuCalib.mbIsSet) // TODO Use a flag instead of the OpenCV matrix { mOwb = mRwc * mImuCalib.mTcb.translation() + mTwc.translation(); } } void KeyFrame::SetVelocity(const Eigen::Vector3f &Vw) { unique_lock lock(mMutexPose); mVw = Vw; mbHasVelocity = true; } Sophus::SE3f KeyFrame::GetPose() { unique_lock lock(mMutexPose); return mTcw; } Sophus::SE3f KeyFrame::GetPoseInverse() { unique_lock lock(mMutexPose); return mTwc; } Eigen::Vector3f KeyFrame::GetCameraCenter(){ unique_lock lock(mMutexPose); return mTwc.translation(); } Eigen::Vector3f KeyFrame::GetImuPosition() { unique_lock lock(mMutexPose); return mOwb; } Eigen::Matrix3f KeyFrame::GetImuRotation() { unique_lock lock(mMutexPose); return (mTwc * mImuCalib.mTcb).rotationMatrix(); } Sophus::SE3f KeyFrame::GetImuPose() { unique_lock lock(mMutexPose); return mTwc * mImuCalib.mTcb; } Eigen::Matrix3f KeyFrame::GetRotation(){ unique_lock lock(mMutexPose); return mRcw; } Eigen::Vector3f KeyFrame::GetTranslation() { unique_lock lock(mMutexPose); return mTcw.translation(); } Eigen::Vector3f KeyFrame::GetVelocity() { unique_lock lock(mMutexPose); return mVw; } bool KeyFrame::isVelocitySet() { unique_lock lock(mMutexPose); return mbHasVelocity; } void KeyFrame::AddConnection(KeyFrame *pKF, const int &weight) { { unique_lock lock(mMutexConnections); if(!mConnectedKeyFrameWeights.count(pKF)) mConnectedKeyFrameWeights[pKF]=weight; else if(mConnectedKeyFrameWeights[pKF]!=weight) mConnectedKeyFrameWeights[pKF]=weight; else return; } UpdateBestCovisibles(); } void KeyFrame::UpdateBestCovisibles() { unique_lock lock(mMutexConnections); vector > vPairs; vPairs.reserve(mConnectedKeyFrameWeights.size()); for(map::iterator mit=mConnectedKeyFrameWeights.begin(), mend=mConnectedKeyFrameWeights.end(); mit!=mend; mit++) vPairs.push_back(make_pair(mit->second,mit->first)); sort(vPairs.begin(),vPairs.end()); list lKFs; list lWs; for(size_t i=0, iend=vPairs.size(); iisBad()) { lKFs.push_front(vPairs[i].second); lWs.push_front(vPairs[i].first); } } mvpOrderedConnectedKeyFrames = vector(lKFs.begin(),lKFs.end()); mvOrderedWeights = vector(lWs.begin(), lWs.end()); } set KeyFrame::GetConnectedKeyFrames() { unique_lock lock(mMutexConnections); set s; for(map::iterator mit=mConnectedKeyFrameWeights.begin();mit!=mConnectedKeyFrameWeights.end();mit++) s.insert(mit->first); return s; } vector KeyFrame::GetVectorCovisibleKeyFrames() { unique_lock lock(mMutexConnections); return mvpOrderedConnectedKeyFrames; } vector KeyFrame::GetBestCovisibilityKeyFrames(const int &N) { unique_lock lock(mMutexConnections); if((int)mvpOrderedConnectedKeyFrames.size()(mvpOrderedConnectedKeyFrames.begin(),mvpOrderedConnectedKeyFrames.begin()+N); } vector KeyFrame::GetCovisiblesByWeight(const int &w) { unique_lock lock(mMutexConnections); if(mvpOrderedConnectedKeyFrames.empty()) { return vector(); } vector::iterator it = upper_bound(mvOrderedWeights.begin(),mvOrderedWeights.end(),w,KeyFrame::weightComp); if(it==mvOrderedWeights.end() && mvOrderedWeights.back() < w) { return vector(); } else { int n = it-mvOrderedWeights.begin(); return vector(mvpOrderedConnectedKeyFrames.begin(), mvpOrderedConnectedKeyFrames.begin()+n); } } int KeyFrame::GetWeight(KeyFrame *pKF) { unique_lock lock(mMutexConnections); if(mConnectedKeyFrameWeights.count(pKF)) return mConnectedKeyFrameWeights[pKF]; else return 0; } int KeyFrame::GetNumberMPs() { unique_lock lock(mMutexFeatures); int numberMPs = 0; for(size_t i=0, iend=mvpMapPoints.size(); i lock(mMutexFeatures); mvpMapPoints[idx]=pMP; } void KeyFrame::EraseMapPointMatch(const int &idx) { unique_lock lock(mMutexFeatures); mvpMapPoints[idx]=static_cast(NULL); } void KeyFrame::EraseMapPointMatch(MapPoint* pMP) { tuple indexes = pMP->GetIndexInKeyFrame(this); size_t leftIndex = get<0>(indexes), rightIndex = get<1>(indexes); if(leftIndex != -1) mvpMapPoints[leftIndex]=static_cast(NULL); if(rightIndex != -1) mvpMapPoints[rightIndex]=static_cast(NULL); } void KeyFrame::ReplaceMapPointMatch(const int &idx, MapPoint* pMP) { mvpMapPoints[idx]=pMP; } set KeyFrame::GetMapPoints() { unique_lock lock(mMutexFeatures); set s; for(size_t i=0, iend=mvpMapPoints.size(); iisBad()) s.insert(pMP); } return s; } int KeyFrame::TrackedMapPoints(const int &minObs) { unique_lock lock(mMutexFeatures); int nPoints=0; const bool bCheckObs = minObs>0; for(int i=0; iisBad()) { if(bCheckObs) { if(mvpMapPoints[i]->Observations()>=minObs) nPoints++; } else nPoints++; } } } return nPoints; } vector KeyFrame::GetMapPointMatches() { unique_lock lock(mMutexFeatures); return mvpMapPoints; } MapPoint* KeyFrame::GetMapPoint(const size_t &idx) { unique_lock lock(mMutexFeatures); return mvpMapPoints[idx]; } void KeyFrame::UpdateConnections(bool upParent) { map KFcounter; vector vpMP; { unique_lock lockMPs(mMutexFeatures); vpMP = mvpMapPoints; } //For all map points in keyframe check in which other keyframes are they seen //Increase counter for those keyframes for(vector::iterator vit=vpMP.begin(), vend=vpMP.end(); vit!=vend; vit++) { MapPoint* pMP = *vit; if(!pMP) continue; if(pMP->isBad()) continue; map> observations = pMP->GetObservations(); for(map>::iterator mit=observations.begin(), mend=observations.end(); mit!=mend; mit++) { if(mit->first->mnId==mnId || mit->first->isBad() || mit->first->GetMap() != mpMap) continue; KFcounter[mit->first]++; } } // This should not happen if(KFcounter.empty()) return; //If the counter is greater than threshold add connection //In case no keyframe counter is over threshold add the one with maximum counter int nmax=0; KeyFrame* pKFmax=NULL; int th = 15; vector > vPairs; vPairs.reserve(KFcounter.size()); if(!upParent) cout << "UPDATE_CONN: current KF " << mnId << endl; for(map::iterator mit=KFcounter.begin(), mend=KFcounter.end(); mit!=mend; mit++) { if(!upParent) cout << " UPDATE_CONN: KF " << mit->first->mnId << " ; num matches: " << mit->second << endl; if(mit->second>nmax) { nmax=mit->second; pKFmax=mit->first; } if(mit->second>=th) { vPairs.push_back(make_pair(mit->second,mit->first)); (mit->first)->AddConnection(this,mit->second); } } if(vPairs.empty()) { vPairs.push_back(make_pair(nmax,pKFmax)); pKFmax->AddConnection(this,nmax); } sort(vPairs.begin(),vPairs.end()); list lKFs; list lWs; for(size_t i=0; i lockCon(mMutexConnections); mConnectedKeyFrameWeights = KFcounter; mvpOrderedConnectedKeyFrames = vector(lKFs.begin(),lKFs.end()); mvOrderedWeights = vector(lWs.begin(), lWs.end()); if(mbFirstConnection && mnId!=mpMap->GetInitKFid()) { mpParent = mvpOrderedConnectedKeyFrames.front(); mpParent->AddChild(this); mbFirstConnection = false; } } } void KeyFrame::AddChild(KeyFrame *pKF) { unique_lock lockCon(mMutexConnections); mspChildrens.insert(pKF); } void KeyFrame::EraseChild(KeyFrame *pKF) { unique_lock lockCon(mMutexConnections); mspChildrens.erase(pKF); } void KeyFrame::ChangeParent(KeyFrame *pKF) { unique_lock lockCon(mMutexConnections); if(pKF == this) { cout << "ERROR: Change parent KF, the parent and child are the same KF" << endl; throw std::invalid_argument("The parent and child can not be the same"); } mpParent = pKF; pKF->AddChild(this); } set KeyFrame::GetChilds() { unique_lock lockCon(mMutexConnections); return mspChildrens; } KeyFrame* KeyFrame::GetParent() { unique_lock lockCon(mMutexConnections); return mpParent; } bool KeyFrame::hasChild(KeyFrame *pKF) { unique_lock lockCon(mMutexConnections); return mspChildrens.count(pKF); } void KeyFrame::SetFirstConnection(bool bFirst) { unique_lock lockCon(mMutexConnections); mbFirstConnection=bFirst; } void KeyFrame::AddLoopEdge(KeyFrame *pKF) { unique_lock lockCon(mMutexConnections); mbNotErase = true; mspLoopEdges.insert(pKF); } set KeyFrame::GetLoopEdges() { unique_lock lockCon(mMutexConnections); return mspLoopEdges; } void KeyFrame::AddMergeEdge(KeyFrame* pKF) { unique_lock lockCon(mMutexConnections); mbNotErase = true; mspMergeEdges.insert(pKF); } set KeyFrame::GetMergeEdges() { unique_lock lockCon(mMutexConnections); return mspMergeEdges; } void KeyFrame::SetNotErase() { unique_lock lock(mMutexConnections); mbNotErase = true; } void KeyFrame::SetErase() { { unique_lock lock(mMutexConnections); if(mspLoopEdges.empty()) { mbNotErase = false; } } if(mbToBeErased) { SetBadFlag(); } } void KeyFrame::SetBadFlag() { { unique_lock lock(mMutexConnections); if(mnId==mpMap->GetInitKFid()) { return; } else if(mbNotErase) { mbToBeErased = true; return; } } for(map::iterator mit = mConnectedKeyFrameWeights.begin(), mend=mConnectedKeyFrameWeights.end(); mit!=mend; mit++) { mit->first->EraseConnection(this); } for(size_t i=0; iEraseObservation(this); } } { unique_lock lock(mMutexConnections); unique_lock lock1(mMutexFeatures); mConnectedKeyFrameWeights.clear(); mvpOrderedConnectedKeyFrames.clear(); // Update Spanning Tree set sParentCandidates; if(mpParent) sParentCandidates.insert(mpParent); // Assign at each iteration one children with a parent (the pair with highest covisibility weight) // Include that children as new parent candidate for the rest while(!mspChildrens.empty()) { bool bContinue = false; int max = -1; KeyFrame* pC; KeyFrame* pP; for(set::iterator sit=mspChildrens.begin(), send=mspChildrens.end(); sit!=send; sit++) { KeyFrame* pKF = *sit; if(pKF->isBad()) continue; // Check if a parent candidate is connected to the keyframe vector vpConnected = pKF->GetVectorCovisibleKeyFrames(); for(size_t i=0, iend=vpConnected.size(); i::iterator spcit=sParentCandidates.begin(), spcend=sParentCandidates.end(); spcit!=spcend; spcit++) { if(vpConnected[i]->mnId == (*spcit)->mnId) { int w = pKF->GetWeight(vpConnected[i]); if(w>max) { pC = pKF; pP = vpConnected[i]; max = w; bContinue = true; } } } } } if(bContinue) { pC->ChangeParent(pP); sParentCandidates.insert(pC); mspChildrens.erase(pC); } else break; } // If a children has no covisibility links with any parent candidate, assign to the original parent of this KF if(!mspChildrens.empty()) { for(set::iterator sit=mspChildrens.begin(); sit!=mspChildrens.end(); sit++) { (*sit)->ChangeParent(mpParent); } } if(mpParent){ mpParent->EraseChild(this); mTcp = mTcw * mpParent->GetPoseInverse(); } mbBad = true; } mpMap->EraseKeyFrame(this); mpKeyFrameDB->erase(this); } bool KeyFrame::isBad() { unique_lock lock(mMutexConnections); return mbBad; } void KeyFrame::EraseConnection(KeyFrame* pKF) { bool bUpdate = false; { unique_lock lock(mMutexConnections); if(mConnectedKeyFrameWeights.count(pKF)) { mConnectedKeyFrameWeights.erase(pKF); bUpdate=true; } } if(bUpdate) UpdateBestCovisibles(); } vector KeyFrame::GetFeaturesInArea(const float &x, const float &y, const float &r, const bool bRight) const { vector vIndices; vIndices.reserve(N); float factorX = r; float factorY = r; const int nMinCellX = max(0,(int)floor((x-mnMinX-factorX)*mfGridElementWidthInv)); if(nMinCellX>=mnGridCols) return vIndices; const int nMaxCellX = min((int)mnGridCols-1,(int)ceil((x-mnMinX+factorX)*mfGridElementWidthInv)); if(nMaxCellX<0) return vIndices; const int nMinCellY = max(0,(int)floor((y-mnMinY-factorY)*mfGridElementHeightInv)); if(nMinCellY>=mnGridRows) return vIndices; const int nMaxCellY = min((int)mnGridRows-1,(int)ceil((y-mnMinY+factorY)*mfGridElementHeightInv)); if(nMaxCellY<0) return vIndices; for(int ix = nMinCellX; ix<=nMaxCellX; ix++) { for(int iy = nMinCellY; iy<=nMaxCellY; iy++) { const vector vCell = (!bRight) ? mGrid[ix][iy] : mGridRight[ix][iy]; for(size_t j=0, jend=vCell.size(); j=mnMinX && x=mnMinY && y0) { const float u = mvKeys[i].pt.x; const float v = mvKeys[i].pt.y; const float x = (u-cx)*z*invfx; const float y = (v-cy)*z*invfy; Eigen::Vector3f x3Dc(x, y, z); unique_lock lock(mMutexPose); x3D = mRwc * x3Dc + mTwc.translation(); return true; } else return false; } float KeyFrame::ComputeSceneMedianDepth(const int q) { if(N==0) return -1.0; vector vpMapPoints; Eigen::Matrix3f Rcw; Eigen::Vector3f tcw; { unique_lock lock(mMutexFeatures); unique_lock lock2(mMutexPose); vpMapPoints = mvpMapPoints; tcw = mTcw.translation(); Rcw = mRcw; } vector vDepths; vDepths.reserve(N); Eigen::Matrix Rcw2 = Rcw.row(2); float zcw = tcw(2); for(int i=0; iGetWorldPos(); float z = Rcw2.dot(x3Dw) + zcw; vDepths.push_back(z); } } sort(vDepths.begin(),vDepths.end()); return vDepths[(vDepths.size()-1)/q]; } void KeyFrame::SetNewBias(const IMU::Bias &b) { unique_lock lock(mMutexPose); mImuBias = b; if(mpImuPreintegrated) mpImuPreintegrated->SetNewBias(b); } Eigen::Vector3f KeyFrame::GetGyroBias() { unique_lock lock(mMutexPose); return Eigen::Vector3f(mImuBias.bwx, mImuBias.bwy, mImuBias.bwz); } Eigen::Vector3f KeyFrame::GetAccBias() { unique_lock lock(mMutexPose); return Eigen::Vector3f(mImuBias.bax, mImuBias.bay, mImuBias.baz); } IMU::Bias KeyFrame::GetImuBias() { unique_lock lock(mMutexPose); return mImuBias; } Map* KeyFrame::GetMap() { unique_lock lock(mMutexMap); return mpMap; } void KeyFrame::UpdateMap(Map* pMap) { unique_lock lock(mMutexMap); mpMap = pMap; } void KeyFrame::PreSave(set& spKF,set& spMP, set& spCam) { // Save the id of each MapPoint in this KF, there can be null pointer in the vector mvBackupMapPointsId.clear(); mvBackupMapPointsId.reserve(N); for(int i = 0; i < N; ++i) { if(mvpMapPoints[i] && spMP.find(mvpMapPoints[i]) != spMP.end()) // Checks if the element is not null mvBackupMapPointsId.push_back(mvpMapPoints[i]->mnId); else // If the element is null his value is -1 because all the id are positives mvBackupMapPointsId.push_back(-1); } // Save the id of each connected KF with it weight mBackupConnectedKeyFrameIdWeights.clear(); for(std::map::const_iterator it = mConnectedKeyFrameWeights.begin(), end = mConnectedKeyFrameWeights.end(); it != end; ++it) { if(spKF.find(it->first) != spKF.end()) mBackupConnectedKeyFrameIdWeights[it->first->mnId] = it->second; } // Save the parent id mBackupParentId = -1; if(mpParent && spKF.find(mpParent) != spKF.end()) mBackupParentId = mpParent->mnId; // Save the id of the childrens KF mvBackupChildrensId.clear(); mvBackupChildrensId.reserve(mspChildrens.size()); for(KeyFrame* pKFi : mspChildrens) { if(spKF.find(pKFi) != spKF.end()) mvBackupChildrensId.push_back(pKFi->mnId); } // Save the id of the loop edge KF mvBackupLoopEdgesId.clear(); mvBackupLoopEdgesId.reserve(mspLoopEdges.size()); for(KeyFrame* pKFi : mspLoopEdges) { if(spKF.find(pKFi) != spKF.end()) mvBackupLoopEdgesId.push_back(pKFi->mnId); } // Save the id of the merge edge KF mvBackupMergeEdgesId.clear(); mvBackupMergeEdgesId.reserve(mspMergeEdges.size()); for(KeyFrame* pKFi : mspMergeEdges) { if(spKF.find(pKFi) != spKF.end()) mvBackupMergeEdgesId.push_back(pKFi->mnId); } //Camera data mnBackupIdCamera = -1; if(mpCamera && spCam.find(mpCamera) != spCam.end()) mnBackupIdCamera = mpCamera->GetId(); mnBackupIdCamera2 = -1; if(mpCamera2 && spCam.find(mpCamera2) != spCam.end()) mnBackupIdCamera2 = mpCamera2->GetId(); //Inertial data mBackupPrevKFId = -1; if(mPrevKF && spKF.find(mPrevKF) != spKF.end()) mBackupPrevKFId = mPrevKF->mnId; mBackupNextKFId = -1; if(mNextKF && spKF.find(mNextKF) != spKF.end()) mBackupNextKFId = mNextKF->mnId; if(mpImuPreintegrated) mBackupImuPreintegrated.CopyFrom(mpImuPreintegrated); } void KeyFrame::PostLoad(map& mpKFid, map& mpMPid, map& mpCamId){ // Rebuild the empty variables // Pose SetPose(mTcw); mTrl = mTlr.inverse(); // Reference reconstruction // Each MapPoint sight from this KeyFrame mvpMapPoints.clear(); mvpMapPoints.resize(N); for(int i=0; i(NULL); } // Conected KeyFrames with him weight mConnectedKeyFrameWeights.clear(); for(map::const_iterator it = mBackupConnectedKeyFrameIdWeights.begin(), end = mBackupConnectedKeyFrameIdWeights.end(); it != end; ++it) { KeyFrame* pKFi = mpKFid[it->first]; mConnectedKeyFrameWeights[pKFi] = it->second; } // Restore parent KeyFrame if(mBackupParentId>=0) mpParent = mpKFid[mBackupParentId]; // KeyFrame childrens mspChildrens.clear(); for(vector::const_iterator it = mvBackupChildrensId.begin(), end = mvBackupChildrensId.end(); it!=end; ++it) { mspChildrens.insert(mpKFid[*it]); } // Loop edge KeyFrame mspLoopEdges.clear(); for(vector::const_iterator it = mvBackupLoopEdgesId.begin(), end = mvBackupLoopEdgesId.end(); it != end; ++it) { mspLoopEdges.insert(mpKFid[*it]); } // Merge edge KeyFrame mspMergeEdges.clear(); for(vector::const_iterator it = mvBackupMergeEdgesId.begin(), end = mvBackupMergeEdgesId.end(); it != end; ++it) { mspMergeEdges.insert(mpKFid[*it]); } //Camera data if(mnBackupIdCamera >= 0) { mpCamera = mpCamId[mnBackupIdCamera]; } else { cout << "ERROR: There is not a main camera in KF " << mnId << endl; } if(mnBackupIdCamera2 >= 0) { mpCamera2 = mpCamId[mnBackupIdCamera2]; } //Inertial data if(mBackupPrevKFId != -1) { mPrevKF = mpKFid[mBackupPrevKFId]; } if(mBackupNextKFId != -1) { mNextKF = mpKFid[mBackupNextKFId]; } mpImuPreintegrated = &mBackupImuPreintegrated; // Remove all backup container mvBackupMapPointsId.clear(); mBackupConnectedKeyFrameIdWeights.clear(); mvBackupChildrensId.clear(); mvBackupLoopEdgesId.clear(); UpdateBestCovisibles(); } bool KeyFrame::ProjectPointDistort(MapPoint* pMP, cv::Point2f &kp, float &u, float &v) { // 3D in absolute coordinates Eigen::Vector3f P = pMP->GetWorldPos(); // 3D in camera coordinates Eigen::Vector3f Pc = mRcw * P + mTcw.translation(); float &PcX = Pc(0); float &PcY = Pc(1); float &PcZ = Pc(2); // Check positive depth if(PcZ<0.0f) { cout << "Negative depth: " << PcZ << endl; return false; } // Project in image and check it is not outside float invz = 1.0f/PcZ; u=fx*PcX*invz+cx; v=fy*PcY*invz+cy; // cout << "c"; if(umnMaxX) return false; if(vmnMaxY) return false; float x = (u - cx) * invfx; float y = (v - cy) * invfy; float r2 = x * x + y * y; float k1 = mDistCoef.at(0); float k2 = mDistCoef.at(1); float p1 = mDistCoef.at(2); float p2 = mDistCoef.at(3); float k3 = 0; if(mDistCoef.total() == 5) { k3 = mDistCoef.at(4); } // Radial distorsion float x_distort = x * (1 + k1 * r2 + k2 * r2 * r2 + k3 * r2 * r2 * r2); float y_distort = y * (1 + k1 * r2 + k2 * r2 * r2 + k3 * r2 * r2 * r2); // Tangential distorsion x_distort = x_distort + (2 * p1 * x * y + p2 * (r2 + 2 * x * x)); y_distort = y_distort + (p1 * (r2 + 2 * y * y) + 2 * p2 * x * y); float u_distort = x_distort * fx + cx; float v_distort = y_distort * fy + cy; u = u_distort; v = v_distort; kp = cv::Point2f(u, v); return true; } bool KeyFrame::ProjectPointUnDistort(MapPoint* pMP, cv::Point2f &kp, float &u, float &v) { // 3D in absolute coordinates Eigen::Vector3f P = pMP->GetWorldPos(); // 3D in camera coordinates Eigen::Vector3f Pc = mRcw * P + mTcw.translation(); float &PcX = Pc(0); float &PcY= Pc(1); float &PcZ = Pc(2); // Check positive depth if(PcZ<0.0f) { cout << "Negative depth: " << PcZ << endl; return false; } // Project in image and check it is not outside const float invz = 1.0f/PcZ; u = fx * PcX * invz + cx; v = fy * PcY * invz + cy; if(umnMaxX) return false; if(vmnMaxY) return false; kp = cv::Point2f(u, v); return true; } Sophus::SE3f KeyFrame::GetRelativePoseTrl() { unique_lock lock(mMutexPose); return mTrl; } Sophus::SE3f KeyFrame::GetRelativePoseTlr() { unique_lock lock(mMutexPose); return mTlr; } Sophus::SE3 KeyFrame::GetRightPose() { unique_lock lock(mMutexPose); return mTrl * mTcw; } Sophus::SE3 KeyFrame::GetRightPoseInverse() { unique_lock lock(mMutexPose); return mTwc * mTlr; } Eigen::Vector3f KeyFrame::GetRightCameraCenter() { unique_lock lock(mMutexPose); return (mTwc * mTlr).translation(); } Eigen::Matrix KeyFrame::GetRightRotation() { unique_lock lock(mMutexPose); return (mTrl.so3() * mTcw.so3()).matrix(); } Eigen::Vector3f KeyFrame::GetRightTranslation() { unique_lock lock(mMutexPose); return (mTrl * mTcw).translation(); } void KeyFrame::SetORBVocabulary(ORBVocabulary* pORBVoc) { mpORBvocabulary = pORBVoc; } void KeyFrame::SetKeyFrameDatabase(KeyFrameDatabase* pKFDB) { mpKeyFrameDB = pKFDB; } } //namespace ORB_SLAM