SLProject  4.2.000
A platform independent 3D computer graphics framework for desktop OS, Android, iOS and online in web browsers
WAIKeyFrame.cpp
Go to the documentation of this file.
1 /**
2  * \file WAIKeyframe.cpp
3  * \authors Michael Goettlicher
4  * \date October 2017
5 // Codestyle: https://github.com/cpvrlab/SLProject/wiki/Coding-Style-Guidelines
6  * \authors Marcus Hudritsch
7  * \copyright http://opensource.org/licenses/GPL-3.0
8 */
9 
10 /**
11  * This file is part of ORB-SLAM2.
12  *
13  * Copyright (C) 2014-2016 Ra�l Mur-Artal <raulmur at unizar dot es> (University of Zaragoza)
14  * For more information see <https://github.com/raulmur/ORB_SLAM2>
15  *
16  * ORB-SLAM2 is free software: you can redistribute it and/or modify
17  * it under the terms of the GNU General Public License as published by
18  * the Free Software Foundation, either version 3 of the License, or
19  * (at your option) any later version.
20  *
21  * ORB-SLAM2 is distributed in the hope that it will be useful,
22  * but WITHOUT ANY WARRANTY; without even the implied warranty of
23  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
24  * GNU General Public License for more details.
25  *
26  * You should have received a copy of the GNU General Public License
27  * along with ORB-SLAM2. If not, see <http://www.gnu.org/licenses/>.
28  */
29 
30 #include <WAIKeyFrame.h>
31 #include <WAIMapPoint.h>
32 #include <WAIKeyFrameDB.h>
33 #include <orb_slam/Converter.h>
34 #include <Profiler.h>
35 
36 long unsigned int WAIKeyFrame::nNextId = 0;
37 
38 //-----------------------------------------------------------------------------
39 //!load an existing keyframe (used during file load)
40 WAIKeyFrame::WAIKeyFrame(const cv::Mat& Tcw,
41  unsigned long id,
42  bool fixKF,
43  float fx,
44  float fy,
45  float cx,
46  float cy,
47  size_t N,
48  const std::vector<cv::KeyPoint>& vKeysUn,
49  const cv::Mat& descriptors,
50  WAIOrbVocabulary* vocabulary,
51  int nScaleLevels,
52  float fScaleFactor,
53  const std::vector<float>& vScaleFactors,
54  const std::vector<float>& vLevelSigma2,
55  const std::vector<float>& vInvLevelSigma2,
56  int nMinX,
57  int nMinY,
58  int nMaxX,
59  int nMaxY,
60  const cv::Mat& K)
61  : mnId(id),
62  mnFrameId(0),
63  mTimeStamp(0),
64  mnGridCols(FRAME_GRID_COLS),
65  mnGridRows(FRAME_GRID_ROWS),
66  mfGridElementWidthInv(static_cast<float>(FRAME_GRID_COLS) / (nMaxX - nMinX)),
67  mfGridElementHeightInv(static_cast<float>(FRAME_GRID_ROWS) / (nMaxY - nMinY)),
68  _fixed(fixKF),
69  mnLoopQuery(0),
70  mnLoopWords(0),
71  mnRelocQuery(0),
72  mnRelocWords(0),
73  fx(fx),
74  fy(fy),
75  cx(cx),
76  cy(cy),
77  invfx(1 / fx),
78  invfy(1 / fy),
79  N((int)N),
80  mvKeysUn(vKeysUn),
81  mDescriptors(descriptors.clone()),
82  mnScaleLevels(nScaleLevels),
83  mfScaleFactor(fScaleFactor),
84  mfLogScaleFactor(log(fScaleFactor)),
85  mvScaleFactors(vScaleFactors),
86  mvLevelSigma2(vLevelSigma2),
87  mvInvLevelSigma2(vInvLevelSigma2),
88  mnMinX(nMinX),
89  mnMinY(nMinY),
90  mnMaxX(nMaxX),
91  mnMaxY(nMaxY),
92  mK(K.clone()),
93  mbFirstConnection(true),
94  mpParent(NULL),
95  mbNotErase(false),
96  mbToBeErased(false),
97  mbBad(false)
98 {
99  mnMarker[0] = 0;
100  mnMarker[1] = 0;
101  mnMarker[2] = 0;
102  mnMarker[3] = 0;
103  mnMarker[4] = 0;
104  mnMarker[5] = 0;
105  mnMarker[6] = 0;
106  //Update next id so we never have twice the same id and especially only one with 0 (this is important)
107  if (id >= nNextId)
108  nNextId = id + 1;
109 
110  mvpMapPoints = vector<WAIMapPoint*>(N, static_cast<WAIMapPoint*>(NULL));
111  //set camera position
112  SetPose(Tcw);
113 
114  //compute mBowVec and mFeatVec
115  ComputeBoW(vocabulary);
116 
117  //assign features to grid
119 }
120 //-----------------------------------------------------------------------------
122  : mnFrameId(F.mnId),
123  mTimeStamp(F.mTimeStamp),
124  mnGridCols(FRAME_GRID_COLS),
125  mnGridRows(FRAME_GRID_ROWS),
126  mfGridElementWidthInv(F.mfGridElementWidthInv),
127  mfGridElementHeightInv(F.mfGridElementHeightInv),
128  _fixed(false),
129  mnLoopQuery(0),
130  mnLoopWords(0),
131  mnRelocQuery(0),
132  mnRelocWords(0),
133  fx(F.fx),
134  fy(F.fy),
135  cx(F.cx),
136  cy(F.cy),
137  invfx(F.invfx),
138  invfy(F.invfy),
139  /* mbf(F.mbf), mb(F.mb), mThDepth(F.mThDepth),*/ N(F.N),
140  /*mvKeys(F.mvKeys),*/ mvKeysUn(F.mvKeysUn),
141  /* mvuRight(F.mvuRight), mvDepth(F.mvDepth),*/ mDescriptors(F.mDescriptors.clone()),
142  mBowVec(F.mBowVec),
143  mFeatVec(F.mFeatVec),
144  mnScaleLevels(F.mnScaleLevels),
145  mfScaleFactor(F.mfScaleFactor),
146  mfLogScaleFactor(F.mfLogScaleFactor),
147  mvScaleFactors(F.mvScaleFactors),
148  mvLevelSigma2(F.mvLevelSigma2),
149  mvInvLevelSigma2(F.mvInvLevelSigma2),
150  mnMinX((int)F.mnMinX),
151  mnMinY((int)F.mnMinY),
152  mnMaxX((int)F.mnMaxX),
153  mnMaxY((int)F.mnMaxY),
154  mK(F.mK),
155  mvpMapPoints(F.mvpMapPoints),
156  /*mpORBvocabulary(F.mpORBvocabulary),*/ mbFirstConnection(true),
157  mpParent(NULL),
158  mbNotErase(false),
159  mbToBeErased(false),
160  mbBad(false) /*, mHalfBaseline(F.mb / 2)*/
161 {
162  mnMarker[0] = 0;
163  mnMarker[1] = 0;
164  mnMarker[2] = 0;
165  mnMarker[3] = 0;
166  mnMarker[4] = 0;
167  mnMarker[5] = 0;
168  mnMarker[6] = 0;
169  mnId = nNextId++;
170 
171  for (int i = 0; i < FRAME_GRID_COLS; i++)
172  for (int j = 0; j < FRAME_GRID_ROWS; j++)
173  mGrid[i][j] = F.mGrid[i][j];
174 
175  //mGrid.resize(mnGridCols);
176  //for (int i = 0; i<mnGridCols; i++)
177  //{
178  // mGrid[i].resize(mnGridRows);
179  // for (int j = 0; j<mnGridRows; j++)
180  // mGrid[i][j] = F.mGrid[i][j];
181  //}
182 
183  SetPose(F.mTcw);
184 
185  if (retainImg && !F.imgGray.empty())
186  imgGray = F.imgGray;
187 }
188 //-----------------------------------------------------------------------------
189 
191 {
192  mBowVec = bow;
193 }
194 
195 //TODO: set levels according to vocabulary
197 {
198  PROFILE_SCOPE("WAI::WAIKeyFrame::ComputeBoW");
199 
200  if (mBowVec.data.empty() || mFeatVec.data.empty())
201  {
202  //vector<cv::Mat> vCurrentDesc = ORB_SLAM2::Converter::toDescriptorVector(mDescriptors);
203  // Feature vector associate features with nodes in the 4th level (from leaves up)
204  // We assume the vocabulary tree has 6 levels, change the 4 otherwise
205 
206  // Luc: In a 6 levels and 10 branch per level voc, 4 levelup mean the 2nd level from the top
207  // that make a total of 100 words. More words means more variance between keyframe and less
208  // preselected keyframe but that will make also the relocalization less invariant to changes
209  //vCurrentDesc, mBowVec, mFeatVec, orbVocabulary->getDepthLevels() - 2
210 
211  //TODO ensure level is now from the top
212  vocabulary->transform(mDescriptors, mBowVec, mFeatVec);
213  }
214 }
215 //-----------------------------------------------------------------------------
216 void WAIKeyFrame::SetPose(const cv::Mat& Tcw)
217 {
218  PROFILE_SCOPE("WAI::WAIKeyFrame::SetPose");
219 
220  unique_lock<mutex> lock(mMutexPose);
221  Tcw.copyTo(_Tcw);
222  cv::Mat Rcw = _Tcw.rowRange(0, 3).colRange(0, 3);
223  cv::Mat tcw = _Tcw.rowRange(0, 3).col(3);
224  cv::Mat Rwc = Rcw.t();
225  Ow = -Rwc * tcw;
226 
227  _Twc = cv::Mat::eye(4, 4, Tcw.type());
228  Rwc.copyTo(_Twc.rowRange(0, 3).colRange(0, 3));
229  Ow.copyTo(_Twc.rowRange(0, 3).col(3));
230  //ghm1: unused code fragments because of monocular usage
231  //cv::Mat center = (cv::Mat_<float>(4, 1) << mHalfBaseline, 0, 0, 1);
232  //Cw = Twc*center;
233 }
234 //-----------------------------------------------------------------------------
236 {
237  unique_lock<mutex> lock(mMutexPose);
238  return _Tcw.clone();
239 }
240 //-----------------------------------------------------------------------------
242 {
243  unique_lock<mutex> lock(mMutexPose);
244  return _Twc.clone();
245 }
246 //-----------------------------------------------------------------------------
248 {
249  unique_lock<mutex> lock(mMutexPose);
250  return Ow.clone();
251 }
252 //-----------------------------------------------------------------------------
254 {
255  unique_lock<mutex> lock(mMutexPose);
256  return _Tcw.rowRange(0, 3).colRange(0, 3).clone();
257 }
258 //-----------------------------------------------------------------------------
260 {
261  unique_lock<mutex> lock(mMutexPose);
262  return _Tcw.rowRange(0, 3).col(3).clone();
263 }
264 //-----------------------------------------------------------------------------
266 {
267  {
268  unique_lock<mutex> lock(mMutexConnections);
269  if (!mConnectedKeyFrameWeights.count(pKF))
270  mConnectedKeyFrameWeights[pKF] = weight;
271  else if (mConnectedKeyFrameWeights[pKF] != weight)
272  mConnectedKeyFrameWeights[pKF] = weight;
273  else
274  return;
275  }
276 
278 }
279 //-----------------------------------------------------------------------------
281 {
282  unique_lock<mutex> lock(mMutexConnections);
283  vector<pair<int, WAIKeyFrame*>> vPairs;
284  vPairs.reserve(mConnectedKeyFrameWeights.size());
285  for (map<WAIKeyFrame*, int>::iterator mit = mConnectedKeyFrameWeights.begin(), mend = mConnectedKeyFrameWeights.end(); mit != mend; mit++)
286  vPairs.push_back(make_pair(mit->second, mit->first));
287 
288  sort(vPairs.begin(), vPairs.end());
289  list<WAIKeyFrame*> lKFs;
290  list<int> lWs;
291  for (size_t i = 0, iend = vPairs.size(); i < iend; i++)
292  {
293  lKFs.push_front(vPairs[i].second);
294  lWs.push_front(vPairs[i].first);
295  }
296 
297  mvpOrderedConnectedKeyFrames = vector<WAIKeyFrame*>(lKFs.begin(), lKFs.end());
298  mvOrderedWeights = vector<int>(lWs.begin(), lWs.end());
299 }
300 //-----------------------------------------------------------------------------
302 {
303  unique_lock<mutex> lock(mMutexConnections);
304  set<WAIKeyFrame*> s;
305  for (map<WAIKeyFrame*, int>::iterator mit = mConnectedKeyFrameWeights.begin(); mit != mConnectedKeyFrameWeights.end(); mit++)
306  s.insert(mit->first);
307  return s;
308 }
309 //-----------------------------------------------------------------------------
311 {
312  unique_lock<mutex> lock(mMutexConnections);
314 }
315 //-----------------------------------------------------------------------------
316 vector<WAIKeyFrame*> WAIKeyFrame::GetBestCovisibilityKeyFrames(const int& N)
317 {
318  unique_lock<mutex> lock(mMutexConnections);
319  if ((int)mvpOrderedConnectedKeyFrames.size() < N)
321  else
322  return vector<WAIKeyFrame*>(mvpOrderedConnectedKeyFrames.begin(), mvpOrderedConnectedKeyFrames.begin() + N);
323 }
324 //-----------------------------------------------------------------------------
325 vector<WAIKeyFrame*> WAIKeyFrame::GetCovisiblesByWeight(const int& w)
326 {
327  unique_lock<mutex> lock(mMutexConnections);
328 
329  if (mvpOrderedConnectedKeyFrames.empty())
330  return vector<WAIKeyFrame*>();
331 
332  vector<int>::iterator it = upper_bound(mvOrderedWeights.begin(), mvOrderedWeights.end(), w, WAIKeyFrame::weightComp);
333  if (it == mvOrderedWeights.end())
334  return vector<WAIKeyFrame*>();
335  else
336  {
337  int n = (int)(it - mvOrderedWeights.begin());
338  return vector<WAIKeyFrame*>(mvpOrderedConnectedKeyFrames.begin(), mvpOrderedConnectedKeyFrames.begin() + n);
339  }
340 }
341 //-----------------------------------------------------------------------------
343 {
344  unique_lock<mutex> lock(mMutexConnections);
345  if (mConnectedKeyFrameWeights.count(pKF))
346  return mConnectedKeyFrameWeights[pKF];
347  else
348  return 0;
349 }
350 //-----------------------------------------------------------------------------
351 const std::map<WAIKeyFrame*, int>& WAIKeyFrame::GetConnectedKfWeights()
352 {
353  unique_lock<mutex> lock(mMutexConnections);
355 }
356 //-----------------------------------------------------------------------------
357 void WAIKeyFrame::AddMapPoint(WAIMapPoint* pMP, size_t idx)
358 {
359  unique_lock<mutex> lock(mMutexFeatures);
360 
361  mvpMapPoints[idx] = pMP;
362 }
363 //-----------------------------------------------------------------------------
364 void WAIKeyFrame::EraseMapPointMatch(const size_t& idx)
365 {
366  unique_lock<mutex> lock(mMutexFeatures);
367  mvpMapPoints[idx] = static_cast<WAIMapPoint*>(NULL);
368 }
369 //-----------------------------------------------------------------------------
371 {
372  unique_lock<mutex> lock(mMutexFeatures);
373  int idx = pMP->GetIndexInKeyFrame(this);
374  if (idx >= 0)
375  mvpMapPoints[idx] = static_cast<WAIMapPoint*>(NULL);
376 }
377 //-----------------------------------------------------------------------------
378 void WAIKeyFrame::ReplaceMapPointMatch(const size_t& idx, WAIMapPoint* pMP)
379 {
380  mvpMapPoints[idx] = pMP;
381 }
382 //-----------------------------------------------------------------------------
383 set<WAIMapPoint*> WAIKeyFrame::GetMapPoints()
384 {
385  unique_lock<mutex> lock(mMutexFeatures);
386  set<WAIMapPoint*> s;
387  for (size_t i = 0, iend = mvpMapPoints.size(); i < iend; i++)
388  {
389  if (!mvpMapPoints[i])
390  continue;
391  WAIMapPoint* pMP = mvpMapPoints[i];
392  if (!pMP->isBad())
393  s.insert(pMP);
394  }
395  return s;
396 }
397 //-----------------------------------------------------------------------------
398 int WAIKeyFrame::TrackedMapPoints(const int& minObs)
399 {
400  unique_lock<mutex> lock(mMutexFeatures);
401 
402  int nPoints = 0;
403  const bool bCheckObs = minObs > 0;
404  for (int i = 0; i < N; i++)
405  {
406  WAIMapPoint* pMP = mvpMapPoints[i];
407  if (pMP)
408  {
409  if (!pMP->isBad())
410  {
411  if (bCheckObs)
412  {
413  if (mvpMapPoints[i]->Observations() >= minObs)
414  nPoints++;
415  }
416  else
417  nPoints++;
418  }
419  }
420  }
421 
422  return nPoints;
423 }
424 //-----------------------------------------------------------------------------
425 vector<WAIMapPoint*> WAIKeyFrame::GetMapPointMatches()
426 {
427  unique_lock<mutex> lock(mMutexFeatures);
428  return mvpMapPoints;
429 }
430 //-----------------------------------------------------------------------------
432 {
433  unique_lock<mutex> lock(mMutexFeatures);
434  return mvpMapPoints[idx];
435 }
436 //-----------------------------------------------------------------------------
437 void WAIKeyFrame::FindAndUpdateConnections(bool buildSpanningTree)
438 {
439  //ghm1: a covisibility graph between keyframes (nodes) is maintained:
440  //if two keyframes share more than 15 observations of the same map points an edge is added. The number of the common observations is the edge weight.
441  map<WAIKeyFrame*, int> KFcounter;
442 
443  vector<WAIMapPoint*> vpMP;
444 
445  {
446  unique_lock<mutex> lockMPs(mMutexFeatures);
447  vpMP = mvpMapPoints;
448  }
449 
450  //For all map points in keyframe check in which other keyframes are they seen
451  //Increase counter for those keyframes
452  for (vector<WAIMapPoint*>::iterator vit = vpMP.begin(), vend = vpMP.end(); vit != vend; vit++)
453  {
454  WAIMapPoint* pMP = *vit;
455 
456  if (!pMP)
457  continue;
458 
459  if (pMP->isBad())
460  continue;
461 
462  map<WAIKeyFrame*, size_t> observations = pMP->GetObservations();
463 
464  for (map<WAIKeyFrame*, size_t>::iterator mit = observations.begin(), mend = observations.end(); mit != mend; mit++)
465  {
466  if (mit->first->mnId == mnId)
467  continue;
468  KFcounter[mit->first]++;
469  }
470  }
471 
472  UpdateConnections(KFcounter, buildSpanningTree);
473 }
474 //-----------------------------------------------------------------------------
475 void WAIKeyFrame::UpdateConnections(std::map<WAIKeyFrame*, int> KFcounter, bool buildSpanningTree)
476 {
477  // This should not happen
478  if (KFcounter.empty())
479  return;
480 
481  //If the counter is greater than threshold add connection
482  //In case no keyframe counter is over threshold add the one with maximum counter
483  int nmax = 0;
484  WAIKeyFrame* pKFmax = NULL;
485  int th = 15;
486 
487  vector<pair<int, WAIKeyFrame*>> vPairs;
488  vPairs.reserve(KFcounter.size());
489  for (map<WAIKeyFrame*, int>::iterator mit = KFcounter.begin(), mend = KFcounter.end(); mit != mend; mit++)
490  {
491  if (mit->second > nmax)
492  {
493  nmax = mit->second;
494  pKFmax = mit->first;
495  }
496  if (mit->second >= th)
497  {
498  vPairs.push_back(make_pair(mit->second, mit->first));
499  (mit->first)->AddConnection(this, mit->second);
500  }
501  }
502 
503  if (vPairs.empty())
504  {
505  vPairs.push_back(make_pair(nmax, pKFmax));
506  pKFmax->AddConnection(this, nmax);
507  }
508 
509  sort(vPairs.begin(), vPairs.end());
510  list<WAIKeyFrame*> lKFs;
511  list<int> lWs;
512  for (size_t i = 0; i < vPairs.size(); i++)
513  {
514  lKFs.push_front(vPairs[i].second);
515  lWs.push_front(vPairs[i].first);
516  }
517 
518  {
519  unique_lock<mutex> lockCon(mMutexConnections);
520 
521  // mspConnectedKeyFrames = spConnectedKeyFrames;
522  mConnectedKeyFrameWeights = KFcounter;
523  mvpOrderedConnectedKeyFrames = vector<WAIKeyFrame*>(lKFs.begin(), lKFs.end());
524  mvOrderedWeights = vector<int>(lWs.begin(), lWs.end());
525 
526  if (mbFirstConnection && mnId != 0)
527  {
528  if (buildSpanningTree)
529  {
531  mpParent->AddChild(this);
532  }
533  mbFirstConnection = false;
534  }
535  }
536 }
537 //-----------------------------------------------------------------------------
539 {
540  unique_lock<mutex> lockCon(mMutexConnections);
541  mspChildrens.insert(pKF);
542 }
543 //-----------------------------------------------------------------------------
545 {
546  unique_lock<mutex> lockCon(mMutexConnections);
547  mspChildrens.erase(pKF);
548 }
549 //-----------------------------------------------------------------------------
551 {
552  unique_lock<mutex> lockCon(mMutexConnections);
553  mpParent = pKF;
554  pKF->AddChild(this);
555 }
556 //-----------------------------------------------------------------------------
557 std::set<WAIKeyFrame*> WAIKeyFrame::GetChilds()
558 {
559  unique_lock<mutex> lockCon(mMutexConnections);
560  return mspChildrens;
561 }
562 //-----------------------------------------------------------------------------
564 {
565  unique_lock<mutex> lockCon(mMutexConnections);
566  return mpParent;
567 }
568 //-----------------------------------------------------------------------------
570 {
571  unique_lock<mutex> lockCon(mMutexConnections);
572  return mspChildrens.count(pKF);
573 }
574 //-----------------------------------------------------------------------------
576 {
577  unique_lock<mutex> lockCon(mMutexConnections);
578  mbNotErase = true;
579  mspLoopEdges.insert(pKF);
580 }
581 //-----------------------------------------------------------------------------
582 set<WAIKeyFrame*> WAIKeyFrame::GetLoopEdges()
583 {
584  unique_lock<mutex> lockCon(mMutexConnections);
585  return mspLoopEdges;
586 }
587 //-----------------------------------------------------------------------------
589 {
590  unique_lock<mutex> lock(mMutexConnections);
591  mbNotErase = true;
592 }
593 //-----------------------------------------------------------------------------
595 {
596  {
597  unique_lock<mutex> lock(mMutexConnections);
598  if (mspLoopEdges.empty())
599  {
600  mbNotErase = false;
601  }
602  }
603 
604  if (mbToBeErased)
605  {
606  SetBadFlag();
607  }
608 }
609 //-----------------------------------------------------------------------------
611 {
612  {
613  unique_lock<mutex> lock(mMutexConnections);
614  if (mnId == 0)
615  {
616  //never delete first keyframe
617  return;
618  }
619  else if (mbNotErase)
620  {
621  //never delete keyframes with this flag
622  mbToBeErased = true;
623  return;
624  }
625  }
626 
627  //for all connected keyframes remove this as a neighbour
628  for (map<WAIKeyFrame*, int>::iterator mit = mConnectedKeyFrameWeights.begin(), mend = mConnectedKeyFrameWeights.end(); mit != mend; mit++)
629  {
630  mit->first->EraseConnection(this);
631  }
632 
633  //erase observation from keypoints observed by this keyframe
634  for (size_t i = 0; i < mvpMapPoints.size(); i++)
635  {
636  if (mvpMapPoints[i])
637  {
638  mvpMapPoints[i]->EraseObservation(this);
639  }
640  }
641 
642  {
643  unique_lock<mutex> lock(mMutexConnections);
644  unique_lock<mutex> lock1(mMutexFeatures);
645 
648 
649  // ghm1: Update Spanning Tree: As we try to cull a keyframe we have to update the parent keyframe from all his children.
650  // A parent keyframe is the one that has the best covisibility with his potential child. So it is not necessaryly the parent of the culled keyframe.
651  // Rather we search all connected keyframes in covisibilty graph (see GetWeight) for every child to find the best parent
652  set<WAIKeyFrame*> sParentCandidates;
653  sParentCandidates.insert(mpParent);
654 
655  // Assign at each iteration one child with a parent (the pair with highest covisibility weight)
656  // Include that child as new parent candidate for the rest
657  while (!mspChildrens.empty())
658  {
659  bool bContinue = false;
660 
661  int max = -1;
662  WAIKeyFrame* pC;
663  WAIKeyFrame* pP;
664 
665  for (set<WAIKeyFrame*>::iterator sit = mspChildrens.begin(), send = mspChildrens.end(); sit != send;)
666  {
667  WAIKeyFrame* pKF = *sit;
668  if (pKF->isBad())
669  {
670  sit = mspChildrens.erase(sit);
671  continue;
672  }
673 
674  // Check if a parent candidate is connected to the keyframe
675  vector<WAIKeyFrame*> vpConnected = pKF->GetVectorCovisibleKeyFrames();
676  for (size_t i = 0, iend = vpConnected.size(); i < iend; i++)
677  {
678  if (vpConnected[i]->mnId == this->mnId || vpConnected[i]->isBad()) { continue; }
679 
680  for (set<WAIKeyFrame*>::iterator spcit = sParentCandidates.begin(), spcend = sParentCandidates.end(); spcit != spcend; spcit++)
681  {
682  if (vpConnected[i]->mnId == (*spcit)->mnId)
683  {
684  int w = pKF->GetWeight(vpConnected[i]);
685  if (w > max)
686  {
687  pC = pKF;
688  pP = vpConnected[i];
689  max = w;
690  bContinue = true;
691  }
692  }
693  }
694  }
695 
696  sit++;
697  }
698 
699  if (bContinue)
700  {
701  pC->ChangeParent(pP);
702  sParentCandidates.insert(pC);
703  mspChildrens.erase(pC);
704  }
705  else
706  {
707  break;
708  }
709  }
710 
711  // If a children has no covisibility links with any parent candidate, assign to the original parent of this KF
712  //ghm1: (change because of exception in ChangeParent) check that the parent is not the child itself. If this is
713  //the case, remove itself from covisibles and use the second best covisible as parent.
714  if (!mspChildrens.empty())
715  {
716  for (set<WAIKeyFrame*>::iterator sit = mspChildrens.begin(); sit != mspChildrens.end(); sit++)
717  {
718  (*sit)->ChangeParent(mpParent);
719  }
720  }
721 
722  mpParent->EraseChild(this);
724  mbBad = true;
725  }
726 
727  //_kfDb->erase(this);
728 }
729 //-----------------------------------------------------------------------------
731 {
732  for (auto it = mspChildrens.begin(); it != mspChildrens.end(); ++it)
733  {
734  if (*it != kf)
735  {
736  return (*it)->findChildRecursive(kf);
737  }
738  else
739  {
740  std::cout << "findChildRecursive found among children of id: " << (*it)->mnId << std::endl;
741  return true;
742  }
743  }
744 
745  return false;
746 }
747 //-----------------------------------------------------------------------------
749 {
750  unique_lock<mutex> lock(mMutexConnections);
751  return mbBad;
752 }
753 //-----------------------------------------------------------------------------
755 {
756  bool bUpdate = false;
757  {
758  unique_lock<mutex> lock(mMutexConnections);
759  if (mConnectedKeyFrameWeights.count(pKF))
760  {
761  mConnectedKeyFrameWeights.erase(pKF);
762  bUpdate = true;
763  }
764  }
765 
766  if (bUpdate)
768 }
769 //-----------------------------------------------------------------------------
770 vector<size_t> WAIKeyFrame::GetFeaturesInArea(const float& x, const float& y, const float& r) const
771 {
772  vector<size_t> vIndices;
773  vIndices.reserve(N);
774 
775  const int nMinCellX = max(0, (int)floor((x - mnMinX - r) * mfGridElementWidthInv));
776  if (nMinCellX >= mnGridCols)
777  return vIndices;
778 
779  const int nMaxCellX = min(mnGridCols - 1, (int)ceil((x - mnMinX + r) * mfGridElementWidthInv));
780  if (nMaxCellX < 0)
781  return vIndices;
782 
783  const int nMinCellY = max(0, (int)floor((y - mnMinY - r) * mfGridElementHeightInv));
784  if (nMinCellY >= mnGridRows)
785  return vIndices;
786 
787  const int nMaxCellY = min(mnGridRows - 1, (int)ceil((y - mnMinY + r) * mfGridElementHeightInv));
788  if (nMaxCellY < 0)
789  return vIndices;
790 
791  for (int ix = nMinCellX; ix <= nMaxCellX; ix++)
792  {
793  for (int iy = nMinCellY; iy <= nMaxCellY; iy++)
794  {
795  const vector<size_t> vCell = mGrid[ix][iy];
796  for (size_t j = 0, jend = vCell.size(); j < jend; j++)
797  {
798  const cv::KeyPoint& kpUn = mvKeysUn[vCell[j]];
799  const float distx = kpUn.pt.x - x;
800  const float disty = kpUn.pt.y - y;
801 
802  if (fabs(distx) < r && fabs(disty) < r)
803  vIndices.push_back(vCell[j]);
804  }
805  }
806  }
807 
808  return vIndices;
809 }
810 //-----------------------------------------------------------------------------
811 bool WAIKeyFrame::IsInImage(const float& x, const float& y) const
812 {
813  return (x >= mnMinX && x < mnMaxX && y >= mnMinY && y < mnMaxY);
814 }
815 //-----------------------------------------------------------------------------
816 //compute median z distance of all map points in the keyframe coordinate system
818 {
819  vector<WAIMapPoint*> vpMapPoints;
820  cv::Mat Tcw_;
821  {
822  unique_lock<mutex> lock(mMutexFeatures);
823  unique_lock<mutex> lock2(mMutexPose);
824  vpMapPoints = mvpMapPoints;
825  Tcw_ = _Tcw.clone();
826  }
827 
828  vector<float> vDepths;
829  vDepths.reserve(N);
830  cv::Mat Rcw2 = Tcw_.row(2).colRange(0, 3);
831  Rcw2 = Rcw2.t();
832  float zcw = Tcw_.at<float>(2, 3);
833  for (int i = 0; i < N; i++)
834  {
835  if (mvpMapPoints[i])
836  {
837  WAIMapPoint* pMP = mvpMapPoints[i];
838  cv::Mat x3Dw = pMP->GetWorldPos();
839  float z = (float)Rcw2.dot(x3Dw) + zcw;
840  vDepths.push_back(z);
841  }
842  }
843 
844  sort(vDepths.begin(), vDepths.end());
845 
846  return vDepths[(vDepths.size() - 1) / q];
847 }
848 //-----------------------------------------------------------------------------
850 {
851  cv::Mat result = _Twc.clone();
852 
853  return result;
854 }
855 //-----------------------------------------------------------------------------
856 //! this is a function from Frame, but we need it here for map loading
858 {
859  PROFILE_SCOPE("WAI::WAIKeyFrame::AssignFeaturesToGrid");
860 
861  int nReserve = (int)(0.5f * N / (FRAME_GRID_COLS * FRAME_GRID_ROWS));
862  for (unsigned int i = 0; i < FRAME_GRID_COLS; i++)
863  for (unsigned int j = 0; j < FRAME_GRID_ROWS; j++)
864  mGrid[i][j].reserve(nReserve);
865 
866  for (int i = 0; i < N; i++)
867  {
868  const cv::KeyPoint& kp = mvKeysUn[i];
869 
870  int nGridPosX, nGridPosY;
871  if (PosInGrid(kp, nGridPosX, nGridPosY))
872  mGrid[nGridPosX][nGridPosY].push_back(i);
873  }
874 }
875 //-----------------------------------------------------------------------------
876 //! this is a function from Frame, but we need it here for map loading
877 bool WAIKeyFrame::PosInGrid(const cv::KeyPoint& kp, int& posX, int& posY)
878 {
879  posX = (int)round((kp.pt.x - mnMinX) * mfGridElementWidthInv);
880  posY = (int)round((kp.pt.y - mnMinY) * mfGridElementHeightInv);
881 
882  //Keypoint's coordinates are undistorted, which could cause to go out of the image
883  if (posX < 0 || posX >= FRAME_GRID_COLS || posY < 0 || posY >= FRAME_GRID_ROWS)
884  return false;
885 
886  return true;
887 }
888 //-----------------------------------------------------------------------------
889 size_t WAIKeyFrame::getSizeOfCvMat(const cv::Mat& mat)
890 {
891  size_t size = 0;
892  if (mat.isContinuous())
893  size = mat.total() * mat.elemSize();
894  else
895  {
896  size = mat.step[0] * mat.rows;
897  }
898  return size;
899 }
900 //-----------------------------------------------------------------------------
901 //get estimated size of this object
903 {
904  size_t size = 0;
905 
906  size += sizeof(*this);
907 
908  //size_t testImg = sizeof(imgGray);
909  //size_t testImg2 = getSizeOfCvMat(imgGray);
910 
911  //size_t test1 = sizeof(mDescriptors);
912  //size_t test2 = getSizeOfCvMat(mDescriptors);
913  //add space for cv mats:
914  size += getSizeOfCvMat(mTcwGBA);
915  size += getSizeOfCvMat(mTcwRefGBA);
916  size += getSizeOfCvMat(mDescriptors);
917  size += getSizeOfCvMat(mTcp);
918  size += getSizeOfCvMat(imgGray);
919  size += getSizeOfCvMat(_Twc);
920  size += getSizeOfCvMat(Ow);
921 
922  return size;
923 }
924 
926 {
927  bool result = false;
928 
929  for (WAIMapPoint* mmp : mvpMapPoints)
930  {
931  if (mmp == mp)
932  {
933  result = true;
934  break;
935  }
936  }
937 
938  return result;
939 }
940 
942 {
943  return _fixed;
944 }
#define PROFILE_SCOPE(name)
Definition: Instrumentor.h:40
SLScene * s
Definition: SLScene.h:31
#define FRAME_GRID_COLS
Definition: WAIFrame.h:44
#define FRAME_GRID_ROWS
Definition: WAIFrame.h:43
The SLScene class represents the top level instance holding the scene structure.
Definition: SLScene.h:47
cv::Mat mTcw
Definition: WAIFrame.h:155
cv::Mat imgGray
Definition: WAIFrame.h:185
std::vector< std::size_t > mGrid[64][36]
Definition: WAIFrame.h:152
AR Keyframe node class.
Definition: WAIKeyFrame.h:60
WAIKeyFrame(const cv::Mat &Tcw, unsigned long id, bool fixKF, float fx, float fy, float cx, float cy, size_t N, const std::vector< cv::KeyPoint > &vKeysUn, const cv::Mat &descriptors, WAIOrbVocabulary *vocabulary, int nScaleLevels, float fScaleFactor, const std::vector< float > &vScaleFactors, const std::vector< float > &vLevelSigma2, const std::vector< float > &vInvLevelSigma2, int nMinX, int nMinY, int nMaxX, int nMaxY, const cv::Mat &KB)
keyframe generation during map loading
Definition: WAIKeyFrame.cpp:40
std::vector< int > mvOrderedWeights
Definition: WAIKeyFrame.h:272
void SetBowVector(WAIBowVector &bow)
float ComputeSceneMedianDepth(const int q)
void AddLoopEdge(WAIKeyFrame *pKF)
bool mbFirstConnection
Definition: WAIKeyFrame.h:275
std::mutex mMutexConnections
Definition: WAIKeyFrame.h:287
bool hasChild(WAIKeyFrame *pKF)
void SetPose(const cv::Mat &Tcw)
cv::Mat GetCameraCenter()
std::vector< WAIKeyFrame * > GetCovisiblesByWeight(const int &w)
void AddChild(WAIKeyFrame *pKF)
cv::Mat mTcwRefGBA
Definition: WAIKeyFrame.h:211
WAIBowVector mBowVec
Definition: WAIKeyFrame.h:226
std::vector< WAIKeyFrame * > GetBestCovisibilityKeyFrames(const int &N)
bool IsInImage(const float &x, const float &y) const
cv::Mat Ow
camera center
Definition: WAIKeyFrame.h:259
void SetBadFlag()
void AddMapPoint(WAIMapPoint *pMP, size_t idx)
const float mfGridElementHeightInv
Definition: WAIKeyFrame.h:187
std::vector< WAIMapPoint * > mvpMapPoints
Definition: WAIKeyFrame.h:263
const int mnGridCols
Definition: WAIKeyFrame.h:184
const int mnMinY
Definition: WAIKeyFrame.h:242
void ChangeParent(WAIKeyFrame *pKF)
WAIMapPoint * GetMapPoint(const size_t &idx)
std::set< WAIKeyFrame * > mspLoopEdges
Definition: WAIKeyFrame.h:278
static bool weightComp(int a, int b)
Definition: WAIKeyFrame.h:158
bool findChildRecursive(WAIKeyFrame *kf)
cv::Mat mTcp
Definition: WAIKeyFrame.h:230
bool mbNotErase
Definition: WAIKeyFrame.h:281
cv::Mat GetTranslation()
std::set< WAIMapPoint * > GetMapPoints()
void EraseConnection(WAIKeyFrame *pKF)
void SetErase()
cv::Mat _Twc
Definition: WAIKeyFrame.h:256
std::map< WAIKeyFrame *, int > mConnectedKeyFrameWeights
Definition: WAIKeyFrame.h:269
WAIKeyFrame * GetParent()
long unsigned int mnId
Definition: WAIKeyFrame.h:175
void FindAndUpdateConnections(bool buildSpanningTree=true)
std::set< WAIKeyFrame * > GetLoopEdges()
bool PosInGrid(const cv::KeyPoint &kp, int &posX, int &posY)
this is a function from Frame, but we need it here for map loading
bool isFixed() const
cv::Mat GetPose()
std::mutex mMutexPose
Definition: WAIKeyFrame.h:286
std::vector< std::size_t > mGrid[FRAME_GRID_COLS][FRAME_GRID_ROWS]
Definition: WAIKeyFrame.h:266
void AddConnection(WAIKeyFrame *pKF, int weight)
int TrackedMapPoints(const int &minObs)
std::set< WAIKeyFrame * > GetChilds()
const int mnMaxY
Definition: WAIKeyFrame.h:244
WAIKeyFrame * mpParent
Definition: WAIKeyFrame.h:276
const int mnMinX
Definition: WAIKeyFrame.h:241
const int mnGridRows
Definition: WAIKeyFrame.h:185
WAIFeatVector mFeatVec
Definition: WAIKeyFrame.h:227
void UpdateBestCovisibles()
size_t getSizeOf()
const bool _fixed
Definition: WAIKeyFrame.h:181
const std::vector< cv::KeyPoint > mvKeysUn
Definition: WAIKeyFrame.h:220
const float mfGridElementWidthInv
Definition: WAIKeyFrame.h:186
std::vector< size_t > GetFeaturesInArea(const float &x, const float &y, const float &r) const
cv::Mat _Tcw
Definition: WAIKeyFrame.h:257
cv::Mat imgGray
Definition: WAIKeyFrame.h:248
size_t getSizeOfCvMat(const cv::Mat &mat)
std::mutex mMutexFeatures
Definition: WAIKeyFrame.h:288
const std::map< WAIKeyFrame *, int > & GetConnectedKfWeights()
cv::Mat GetRotation()
cv::Mat getObjectMatrix()
get visual representation as SLPoints
bool mbToBeErased
Definition: WAIKeyFrame.h:282
std::set< WAIKeyFrame * > GetConnectedKeyFrames()
void AssignFeaturesToGrid()
this is a function from Frame, but we need it here for map loading
cv::Mat mTcwGBA
Definition: WAIKeyFrame.h:210
void EraseChild(WAIKeyFrame *pKF)
std::vector< WAIKeyFrame * > mvpOrderedConnectedKeyFrames
Definition: WAIKeyFrame.h:271
long unsigned int mnMarker[7]
Definition: WAIKeyFrame.h:199
const int N
Definition: WAIKeyFrame.h:217
void UpdateConnections(std::map< WAIKeyFrame *, int > KFcounter, bool buildSpanningTree)
std::vector< WAIKeyFrame * > GetVectorCovisibleKeyFrames()
void EraseMapPointMatch(WAIMapPoint *pMP)
void SetNotErase()
std::vector< WAIMapPoint * > GetMapPointMatches()
void ComputeBoW(WAIOrbVocabulary *vocabulary)
std::set< WAIKeyFrame * > mspChildrens
Definition: WAIKeyFrame.h:277
const cv::Mat mDescriptors
Definition: WAIKeyFrame.h:223
cv::Mat GetPoseInverse()
bool hasMapPoint(WAIMapPoint *mp)
static long unsigned int nNextId
Definition: WAIKeyFrame.h:174
int GetWeight(WAIKeyFrame *pKF)
void ReplaceMapPointMatch(const size_t &idx, WAIMapPoint *pMP)
std::map< WAIKeyFrame *, size_t > GetObservations()
int GetIndexInKeyFrame(WAIKeyFrame *pKF)
cv::Mat GetWorldPos()
void transform(const cv::Mat &descriptors, WAIBowVector &bow, WAIFeatVector &feat)
T ceil(T a)
Definition: Utils.h:247
T floor(T a)
Definition: Utils.h:246
void log(const char *tag, const char *format,...)
logs a formatted string platform independently
Definition: Utils.cpp:1103
fbow::fBow data
fbow::fBow2 data