SLAMflex SE  0.1.0
SLAMflex provides detection and tracking of dominant planes for smartphone devices. This plane can then be used to show AR content relative to the plane orientation. The detection of plane is performed in the field of view of the smartphone camera. In subsequent frames it is tracked. The interface returns the plane position and orientation.
MapMaker.cpp
Go to the documentation of this file.
1 // Copyright 2008 Isis Innovation Limited
2 #include "MapMaker.h"
3 #include "MapPoint.h"
4 #include "Bundle.h"
5 #include "PatchFinder.h"
6 #include "SmallMatrixOpts.h"
7 #include "HomographyInit.h"
8 
9 #include "vector_image_ref.h"
10 #include "vision.h"
11 #include "image_interpolate.h"
12 
13 #include "SVD.h"
14 #include "SymEigen.h"
15 
16 #include <fstream>
17 #include <algorithm>
18 
19 #ifdef WIN32
20 #define WIN32_LEAN_AND_MEAN
21 #include <windows.h>
22 #endif
23 
24 using namespace CVD;
25 using namespace std;
26 
27 // Constructor sets up internal reference variable to Map.
28 // Most of the intialisation is done by Reset()..
30  : mMap(m), mCamera(cam)
31 {
32  mbResetRequested = false;
33  Reset();
34  start(); // This CVD::thread func starts the map-maker thread with function run()
35  mgvdWiggleScale=MapMakerWiggleScale; // Default to 10cm between keyframes
36 };
37 
39 {
40  // This is only called from within the mapmaker thread...
41  mMap.Reset();
42  mvFailureQueue.clear();
43  while(!mqNewQueue.empty()) mqNewQueue.pop();
44  mMap.vpKeyFrames.clear(); // TODO: actually erase old keyframes
45  mvpKeyFrameQueue.clear(); // TODO: actually erase old keyframes
46  mbBundleRunning = false;
49  mbResetDone = true;
50  mbResetRequested = false;
51  mbBundleAbortRequested = false;
53 }
54 
55 
57 {
58  sendStringToUnity = sm;
59 }
60 
61 
62 // CHECK_RESET is a handy macro which makes the mapmaker thread stop
63 // what it's doing and reset, if required.
64 #define CHECK_RESET if(mbResetRequested) {Reset(); continue;};
65 
67 {
68  while(!shouldStop()) // ShouldStop is a CVD::Thread func which return true if the thread is told to exit.
69  {
71  sleep(5); // Sleep not really necessary, especially if mapmaker is busy
73 
74  // Handle any GUI commands encountered..
75  while(!mvQueuedCommands.empty())
76  {
77  GUICommandHandler(mvQueuedCommands.begin()->sCommand, mvQueuedCommands.begin()->sParams);
78  mvQueuedCommands.erase(mvQueuedCommands.begin());
79  }
80 
81  if(!mMap.IsGood()) // Nothing to do if there is no map yet!
82  continue;
83 
84  // From here on, mapmaker does various map-maintenance jobs in a certain priority
85  // Hierarchy. For example, if there's a new key-frame to be added (QueueSize() is >0)
86  // then that takes high priority.
87 
89  // Should we run local bundle adjustment?
90  if(!mbBundleConverged_Recent && QueueSize() == 0)
92 
94  // Are there any newly-made map points which need more measurements from older key-frames?
96  ReFindNewlyMade();
97 
99  // Run global bundle adjustment?
101  BundleAdjustAll();
102 
103  CHECK_RESET;
104  // Very low priorty: re-find measurements marked as outliers
105  if(mbBundleConverged_Recent && mbBundleConverged_Full && rand()%20 == 0 && QueueSize() == 0)
107 
108  CHECK_RESET;
109  HandleBadPoints();
110 
111  CHECK_RESET;
112  // Any new key-frames to be added?
113  if(QueueSize() > 0)
114  AddKeyFrameFromTopOfQueue(); // Integrate into map data struct, and process
115  }
116 }
117 
118 
119 // Tracker calls this to demand a reset
121 {
122  mbResetDone = false;
123  mbResetRequested = true;
124 }
125 
127 {
128  return mbResetDone;
129 }
130 
131 // HandleBadPoints() Does some heuristic checks on all points in the map to see if
132 // they should be flagged as bad, based on tracker feedback.
134 {
135  // Did the tracker see this point as an outlier more often than as an inlier?
136  for(unsigned int i=0; i<mMap.vpPoints.size(); i++)
137  {
138  MapPoint &p = *mMap.vpPoints[i];
140  p.bBad = true;
141  }
142 
143  // All points marked as bad will be erased - erase all records of them
144  // from keyframes in which they might have been measured.
145  for(unsigned int i=0; i<mMap.vpPoints.size(); i++)
146  if(mMap.vpPoints[i]->bBad)
147  {
148  MapPoint *p = mMap.vpPoints[i];
149  for(unsigned int j=0; j<mMap.vpKeyFrames.size(); j++)
150  {
151  KeyFrame &k = *mMap.vpKeyFrames[j];
152  if(k.mMeasurements.count(p))
153  k.mMeasurements.erase(p);
154  }
155  }
156  // Move bad points to the trash list.
158 }
159 
161 {
162  mbBundleAbortRequested = true;
163  stop(); // makes shouldStop() return true
164  cout << "Waiting for mapmaker to die.." << endl;
165  LOGV(LOG_TAG, "Info: %s", "Waiting for mapmaker to die..");
166  join();
167  cout << " .. mapmaker has died." << endl;
168  LOGV(LOG_TAG, "Info: %s", ".. mapmaker has died.");
169 }
170 
171 
172 // Finds 3d coords of point in reference frame B from two z=1 plane projections
173 Vector<3> MapMaker::ReprojectPoint(SE3<> se3AfromB, const Vector<2> &v2A, const Vector<2> &v2B)
174 {
175  Matrix<3,4> PDash;
176  PDash.slice<0,0,3,3>() = se3AfromB.get_rotation().get_matrix();
177  PDash.slice<0,3,3,1>() = se3AfromB.get_translation().as_col();
178 
179  Matrix<4> A;
180  A[0][0] = -1.0; A[0][1] = 0.0; A[0][2] = v2B[0]; A[0][3] = 0.0;
181  A[1][0] = 0.0; A[1][1] = -1.0; A[1][2] = v2B[1]; A[1][3] = 0.0;
182  A[2] = v2A[0] * PDash[2] - PDash[0];
183  A[3] = v2A[1] * PDash[2] - PDash[1];
184 
185  SVD<4,4> svd(A);
186  Vector<4> v4Smallest = svd.get_VT()[3];
187  if(v4Smallest[3] == 0.0)
188  v4Smallest[3] = 0.00001;
189  return project(v4Smallest);
190 }
191 
192 
193 
194 // InitFromStereo() generates the initial match from two keyframes
195 // and a vector of image correspondences. Uses the
197  KeyFrame &kS,
198  vector<pair<ImageRef, ImageRef> > &vTrailMatches,
199  SE3<> &se3TrackerPose)
200 {
201  mdWiggleScale = mgvdWiggleScale; // Cache this for the new map.
202 
204 
205 
206  vector<HomographyMatch> vMatches;
207  for(unsigned int i=0; i<vTrailMatches.size(); i++)
208  {
209  HomographyMatch m;
210  m.v2CamPlaneFirst = mCamera.UnProject(vTrailMatches[i].first);
211  m.v2CamPlaneSecond = mCamera.UnProject(vTrailMatches[i].second);
213  vMatches.push_back(m);
214  }
215 
216  SE3<> se3;
217  bool bGood;
219  bGood = HomographyInit.Compute(vMatches, 5.0, se3);
220  if(!bGood)
221  {
222  cout << " Could not init from stereo pair, try again." << endl;
223  LOGV(LOG_TAG, "Info: %s", "Could not init from stereo pair, try again.");
224  return false;
225  }
226 
227  // Check that the initialiser estimated a non-zero baseline
228  double dTransMagn = sqrt(se3.get_translation() * se3.get_translation());
229  if(dTransMagn == 0)
230  {
231  cout << " Estimated zero baseline from stereo pair, try again." << endl;
232  LOGV(LOG_TAG, "Info: %s", " Estimated zero baseline from stereo pair, try again.");
233  return false;
234  }
235  // change the scale of the map so the second camera is wiggleScale away from the first
236  se3.get_translation() *= mdWiggleScale/dTransMagn;
237 
238 
239  KeyFrame *pkFirst = new KeyFrame();
240  KeyFrame *pkSecond = new KeyFrame();
241  *pkFirst = kF;
242  *pkSecond = kS;
243 
244  pkFirst->bFixed = true;
245  pkFirst->se3CfromW = SE3<>();
246 
247  pkSecond->bFixed = false;
248  pkSecond->se3CfromW = se3;
249 
250  // Construct map from the stereo matches.
251  PatchFinder finder;
252 
253  for(unsigned int i=0; i<vMatches.size(); i++)
254  {
255  MapPoint *p = new MapPoint();
256 
257  // Patch source stuff:
258  p->pPatchSourceKF = pkFirst;
259  p->nSourceLevel = 0;
260  p->v3Normal_NC = makeVector( 0,0,-1);
261  p->irCenter = vTrailMatches[i].first;
268  p->RefreshPixelVectors();
269 
270  // Do sub-pixel alignment on the second image
271  finder.MakeTemplateCoarseNoWarp(*p);
272  finder.MakeSubPixTemplate();
273  finder.SetSubPixPos(vec(vTrailMatches[i].second));
274  bool bGood = finder.IterateSubPixToConvergence(*pkSecond,10);
275  if(!bGood)
276  {
277  delete p; continue;
278  }
279 
280  // Triangulate point:
281  Vector<2> v2SecondPos = finder.GetSubPixPos();
282  p->v3WorldPos = ReprojectPoint(se3, mCamera.UnProject(v2SecondPos), vMatches[i].v2CamPlaneFirst);
283  if(p->v3WorldPos[2] < 0.0)
284  {
285  delete p; continue;
286  }
287 
288  // Not behind map? Good, then add to map.
289  p->pMMData = new MapMakerData();
290  mMap.vpPoints.push_back(p);
291 
292  // Construct first two measurements and insert into relevant DBs:
293  Measurement mFirst;
294  mFirst.nLevel = 0;
295  mFirst.Source = Measurement::SRC_ROOT;
296  mFirst.v2RootPos = vec(vTrailMatches[i].first);
297  mFirst.bSubPix = true;
298  pkFirst->mMeasurements[p] = mFirst;
299  p->pMMData->sMeasurementKFs.insert(pkFirst);
300 
301  Measurement mSecond;
302  mSecond.nLevel = 0;
303  mSecond.Source = Measurement::SRC_TRAIL;
304  mSecond.v2RootPos = finder.GetSubPixPos();
305  mSecond.bSubPix = true;
306  pkSecond->mMeasurements[p] = mSecond;
307  p->pMMData->sMeasurementKFs.insert(pkSecond);
308  }
309 
310  mMap.vpKeyFrames.push_back(pkFirst);
311  mMap.vpKeyFrames.push_back(pkSecond);
312  pkFirst->MakeKeyFrame_Rest();
313  pkSecond->MakeKeyFrame_Rest();
314 
315  for(int i=0; i<5; i++)
316  BundleAdjustAll();
317 
318  // Estimate the feature depth distribution in the first two key-frames
319  // (Needed for epipolar search)
320  RefreshSceneDepth(pkFirst);
321  RefreshSceneDepth(pkSecond);
323 
324 
325  AddSomeMapPoints(0);
326  AddSomeMapPoints(3);
327  AddSomeMapPoints(1);
328  AddSomeMapPoints(2);
329 
330  mbBundleConverged_Full = false;
331  mbBundleConverged_Recent = false;
332 
334  while(!mbBundleConverged_Full)
335  {
337  {
339  }
340  else
341  {
342  return false;
343  }
344  BundleAdjustAll();
345  LOGV(LOG_TAG, "Info: mbBundleConverged_Full, counter: %i", counterForConvergence);
346  if(mbResetRequested)
347  return false;
348  }
349 
350  // Rotate and translate the map so the dominant plane is at z=0:
352  mMap.bGood = true;
353  se3TrackerPose = pkSecond->se3CfromW;
354 
355  cout << " MapMaker: made initial map with " << mMap.vpPoints.size() << " points." << endl;
356  LOGV(LOG_TAG, " MapMaker: made initial map with: %i", mMap.vpPoints.size());
357  ostringstream tmp;
358  tmp << "MapMaker: made initial map with "<<mMap.vpPoints.size()<<" points."<< endl;
359  sendStringToUnity.SendStringToUnity(tmp.str().c_str());
360 
361  return true;
362 }
363 
364 // ThinCandidates() Thins out a key-frame's candidate list.
365 // Candidates are those salient corners where the mapmaker will attempt
366 // to make a new map point by epipolar search. We don't want to make new points
367 // where there are already existing map points, this routine erases such candidates.
368 // Operates on a single level of a keyframe.
369 void MapMaker::ThinCandidates(KeyFrame &k, int nLevel)
370 {
371  vector<Candidate> &vCSrc = k.aLevels[nLevel].vCandidates;
372  vector<Candidate> vCGood;
373  vector<ImageRef> irBusyLevelPos;
374  // Make a list of `busy' image locations, which already have features at the same level
375  // or at one level higher.
376  for(meas_it it = k.mMeasurements.begin(); it!=k.mMeasurements.end(); it++)
377  {
378  if(!(it->second.nLevel == nLevel || it->second.nLevel == nLevel + 1))
379  continue;
380  irBusyLevelPos.push_back(ir_rounded(it->second.v2RootPos / LevelScale(nLevel)));
381  }
382 
383  // Only keep those candidates further than 10 pixels away from busy positions.
384  unsigned int nMinMagSquared = 10*10;
385  for(unsigned int i=0; i<vCSrc.size(); i++)
386  {
387  ImageRef irC = vCSrc[i].irLevelPos;
388  bool bGood = true;
389  for(unsigned int j=0; j<irBusyLevelPos.size(); j++)
390  {
391  ImageRef irB = irBusyLevelPos[j];
392  if((irB - irC).mag_squared() < nMinMagSquared)
393  {
394  bGood = false;
395  break;
396  }
397  }
398  if(bGood)
399  vCGood.push_back(vCSrc[i]);
400  }
401  vCSrc = vCGood;
402 }
403 
404 // Adds map points by epipolar search to the last-added key-frame, at a single
405 // specified pyramid level. Does epipolar search in the target keyframe as closest by
406 // the ClosestKeyFrame function.
408 {
409  KeyFrame &kSrc = *(mMap.vpKeyFrames[mMap.vpKeyFrames.size() - 1]); // The new keyframe
410  KeyFrame &kTarget = *(ClosestKeyFrame(kSrc));
411  Level &l = kSrc.aLevels[nLevel];
412 
413  ThinCandidates(kSrc, nLevel);
414 
415  for(unsigned int i = 0; i<l.vCandidates.size(); i++)
416  AddPointEpipolar(kSrc, kTarget, nLevel, i);
417 };
418 
419 // Rotates/translates the whole map and all keyframes
421 {
422  for(unsigned int i=0; i<mMap.vpKeyFrames.size(); i++)
423  mMap.vpKeyFrames[i]->se3CfromW = mMap.vpKeyFrames[i]->se3CfromW * se3NewFromOld.inverse();
424 
425  SO3<> so3Rot = se3NewFromOld.get_rotation();
426  for(unsigned int i=0; i<mMap.vpPoints.size(); i++)
427  {
428  mMap.vpPoints[i]->v3WorldPos =
429  se3NewFromOld * mMap.vpPoints[i]->v3WorldPos;
430  mMap.vpPoints[i]->RefreshPixelVectors();
431  }
432 }
433 
434 // Applies a global scale factor to the map
436 {
437  for(unsigned int i=0; i<mMap.vpKeyFrames.size(); i++)
438  mMap.vpKeyFrames[i]->se3CfromW.get_translation() *= dScale;
439 
440  for(unsigned int i=0; i<mMap.vpPoints.size(); i++)
441  {
442  (*mMap.vpPoints[i]).v3WorldPos *= dScale;
443  (*mMap.vpPoints[i]).v3PixelRight_W *= dScale;
444  (*mMap.vpPoints[i]).v3PixelDown_W *= dScale;
445  (*mMap.vpPoints[i]).RefreshPixelVectors();
446  }
447 }
448 
449 // The tracker entry point for adding a new keyframe;
450 // the tracker thread doesn't want to hang about, so
451 // just dumps it on the top of the mapmaker's queue to
452 // be dealt with later, and return.
454 {
455  KeyFrame *pK = new KeyFrame;
456  *pK = k;
457  pK->pSBI = NULL; // Mapmaker uses a different SBI than the tracker, so will re-gen its own
458  mvpKeyFrameQueue.push_back(pK);
459  if(mbBundleRunning) // Tell the mapmaker to stop doing low-priority stuff and concentrate on this KF first.
460  mbBundleAbortRequested = true;
461 }
462 
463 // Mapmaker's code to handle incoming key-frames.
465 {
466  if(mvpKeyFrameQueue.size() == 0)
467  return;
468 
469  KeyFrame *pK = mvpKeyFrameQueue[0];
470  mvpKeyFrameQueue.erase(mvpKeyFrameQueue.begin());
471  pK->MakeKeyFrame_Rest();
472  mMap.vpKeyFrames.push_back(pK);
473  // Any measurements? Update the relevant point's measurement counter status map
474  for(meas_it it = pK->mMeasurements.begin();
475  it!=pK->mMeasurements.end();
476  it++)
477  {
478  it->first->pMMData->sMeasurementKFs.insert(pK);
479  it->second.Source = Measurement::SRC_TRACKER;
480  }
481 
482  // And maybe we missed some - this now adds to the map itself, too.
484 
485  AddSomeMapPoints(3); // .. and add more map points by epipolar search.
486  AddSomeMapPoints(0);
487  AddSomeMapPoints(1);
488  AddSomeMapPoints(2);
489 
490  mbBundleConverged_Full = false;
491  mbBundleConverged_Recent = false;
492 }
493 
494 // Tries to make a new map point out of a single candidate point
495 // by searching for that point in another keyframe, and triangulating
496 // if a match is found.
498  KeyFrame &kTarget,
499  int nLevel,
500  int nCandidate)
501 {
502  static Image<Vector<2> > imUnProj;
503  static bool bMadeCache = false;
504  if(!bMadeCache)
505  {
506  imUnProj.resize(kSrc.aLevels[0].im.size());
507  ImageRef ir;
508  do imUnProj[ir] = mCamera.UnProject(ir);
509  while(ir.next(imUnProj.size()));
510  bMadeCache = true;
511  }
512 
513  int nLevelScale = LevelScale(nLevel);
514  Candidate &candidate = kSrc.aLevels[nLevel].vCandidates[nCandidate];
515  ImageRef irLevelPos = candidate.irLevelPos;
516  Vector<2> v2RootPos = LevelZeroPos(irLevelPos, nLevel);
517 
518  Vector<3> v3Ray_SC = unproject(mCamera.UnProject(v2RootPos));
519  normalize(v3Ray_SC);
520  Vector<3> v3LineDirn_TC = kTarget.se3CfromW.get_rotation() * (kSrc.se3CfromW.get_rotation().inverse() * v3Ray_SC);
521 
522  // Restrict epipolar search to a relatively narrow depth range
523  // to increase reliability
524  double dMean = kSrc.dSceneDepthMean;
525  double dSigma = kSrc.dSceneDepthSigma;
526  double dStartDepth = max(mdWiggleScale, dMean - dSigma);
527  double dEndDepth = min(40 * mdWiggleScale, dMean + dSigma);
528 
529  Vector<3> v3CamCenter_TC = kTarget.se3CfromW * kSrc.se3CfromW.inverse().get_translation(); // The camera end
530  Vector<3> v3RayStart_TC = v3CamCenter_TC + dStartDepth * v3LineDirn_TC; // the far-away end
531  Vector<3> v3RayEnd_TC = v3CamCenter_TC + dEndDepth * v3LineDirn_TC; // the far-away end
532 
533 
534  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
535  return false;
536  if(v3RayEnd_TC[2] <= 0.0 ) return false;
537  if(v3RayStart_TC[2] <= 0.0)
538  v3RayStart_TC += v3LineDirn_TC * (0.001 - v3RayStart_TC[2] / v3LineDirn_TC[2]);
539 
540  Vector<2> v2A = project(v3RayStart_TC);
541  Vector<2> v2B = project(v3RayEnd_TC);
542  Vector<2> v2AlongProjectedLine = v2A-v2B;
543 
544  if(v2AlongProjectedLine * v2AlongProjectedLine < 0.00000001)
545  {
546  cout << "v2AlongProjectedLine too small." << endl;
547  return false;
548  }
549  normalize(v2AlongProjectedLine);
550  Vector<2> v2Normal;
551  v2Normal[0] = v2AlongProjectedLine[1];
552  v2Normal[1] = -v2AlongProjectedLine[0];
553 
554  double dNormDist = v2A * v2Normal;
555  if(fabs(dNormDist) > mCamera.LargestRadiusInImage() )
556  return false;
557 
558  double dMinLen = min(v2AlongProjectedLine * v2A, v2AlongProjectedLine * v2B) - 0.05;
559  double dMaxLen = max(v2AlongProjectedLine * v2A, v2AlongProjectedLine * v2B) + 0.05;
560  if(dMinLen < -2.0) dMinLen = -2.0;
561  if(dMaxLen < -2.0) dMaxLen = -2.0;
562  if(dMinLen > 2.0) dMinLen = 2.0;
563  if(dMaxLen > 2.0) dMaxLen = 2.0;
564 
565  // Find current-frame corners which might match this
566  PatchFinder Finder;
567  Finder.MakeTemplateCoarseNoWarp(kSrc, nLevel, irLevelPos);
568  if(Finder.TemplateBad()) return false;
569 
570  vector<Vector<2> > &vv2Corners = kTarget.aLevels[nLevel].vImplaneCorners;
571  vector<ImageRef> &vIR = kTarget.aLevels[nLevel].vCorners;
572  if(!kTarget.aLevels[nLevel].bImplaneCornersCached)
573  {
574  for(unsigned int i=0; i<vIR.size(); i++) // over all corners in target img..
575  vv2Corners.push_back(imUnProj[ir(LevelZeroPos(vIR[i], nLevel))]);
576  kTarget.aLevels[nLevel].bImplaneCornersCached = true;
577  }
578 
579  int nBest = -1;
580  int nBestZMSSD = Finder.mnMaxSSD + 1;
581  double dMaxDistDiff = mCamera.OnePixelDist() * (4.0 + 1.0 * nLevelScale);
582  double dMaxDistSq = dMaxDistDiff * dMaxDistDiff;
583 
584  for(unsigned int i=0; i<vv2Corners.size(); i++) // over all corners in target img..
585  {
586  Vector<2> v2Im = vv2Corners[i];
587  double dDistDiff = dNormDist - v2Im * v2Normal;
588  if(dDistDiff * dDistDiff > dMaxDistSq) continue; // skip if not along epi line
589  if(v2Im * v2AlongProjectedLine < dMinLen) continue; // skip if not far enough along line
590  if(v2Im * v2AlongProjectedLine > dMaxLen) continue; // or too far
591  int nZMSSD = Finder.ZMSSDAtPoint(kTarget.aLevels[nLevel].im, vIR[i]);
592  if(nZMSSD < nBestZMSSD)
593  {
594  nBest = i;
595  nBestZMSSD = nZMSSD;
596  }
597  }
598 
599  if(nBest == -1) return false; // Nothing found.
600 
601  // Found a likely candidate along epipolar ray
602  Finder.MakeSubPixTemplate();
603  Finder.SetSubPixPos(LevelZeroPos(vIR[nBest], nLevel));
604  bool bSubPixConverges = Finder.IterateSubPixToConvergence(kTarget,10);
605  if(!bSubPixConverges)
606  return false;
607 
608  // Now triangulate the 3d point...
609  Vector<3> v3New;
610  v3New = kTarget.se3CfromW.inverse() *
611  ReprojectPoint(kSrc.se3CfromW * kTarget.se3CfromW.inverse(),
612  mCamera.UnProject(v2RootPos),
613  mCamera.UnProject(Finder.GetSubPixPos()));
614 
615  MapPoint *pNew = new MapPoint;
616  pNew->v3WorldPos = v3New;
617  pNew->pMMData = new MapMakerData();
618 
619  // Patch source stuff:
620  pNew->pPatchSourceKF = &kSrc;
621  pNew->nSourceLevel = nLevel;
622  pNew->v3Normal_NC = makeVector( 0,0,-1);
623  pNew->irCenter = irLevelPos;
624  pNew->v3Center_NC = unproject(mCamera.UnProject(v2RootPos));
625  pNew->v3OneRightFromCenter_NC = unproject(mCamera.UnProject(v2RootPos + vec(ImageRef(nLevelScale,0))));
626  pNew->v3OneDownFromCenter_NC = unproject(mCamera.UnProject(v2RootPos + vec(ImageRef(0,nLevelScale))));
627 
628  normalize(pNew->v3Center_NC);
631 
632  pNew->RefreshPixelVectors();
633 
634  mMap.vpPoints.push_back(pNew);
635  mqNewQueue.push(pNew);
636  Measurement m;
638  m.v2RootPos = v2RootPos;
639  m.nLevel = nLevel;
640  m.bSubPix = true;
641  kSrc.mMeasurements[pNew] = m;
642 
644  m.v2RootPos = Finder.GetSubPixPos();
645  kTarget.mMeasurements[pNew] = m;
646  pNew->pMMData->sMeasurementKFs.insert(&kSrc);
647  pNew->pMMData->sMeasurementKFs.insert(&kTarget);
648  return true;
649 }
650 
652 {
653  Vector<3> v3KF1_CamPos = k1.se3CfromW.inverse().get_translation();
654  Vector<3> v3KF2_CamPos = k2.se3CfromW.inverse().get_translation();
655  Vector<3> v3Diff = v3KF2_CamPos - v3KF1_CamPos;
656  double dDist = sqrt(v3Diff * v3Diff);
657  return dDist;
658 }
659 
660 vector<KeyFrame*> MapMaker::NClosestKeyFrames(KeyFrame &k, unsigned int N)
661 {
662  vector<pair<double, KeyFrame* > > vKFandScores;
663  for(unsigned int i=0; i<mMap.vpKeyFrames.size(); i++)
664  {
665  if(mMap.vpKeyFrames[i] == &k)
666  continue;
667  double dDist = KeyFrameLinearDist(k, *mMap.vpKeyFrames[i]);
668  vKFandScores.push_back(make_pair(dDist, mMap.vpKeyFrames[i]));
669  }
670  if(N > vKFandScores.size())
671  N = vKFandScores.size();
672  partial_sort(vKFandScores.begin(), vKFandScores.begin() + N, vKFandScores.end());
673 
674  vector<KeyFrame*> vResult;
675  for(unsigned int i=0; i<N; i++)
676  vResult.push_back(vKFandScores[i].second);
677  return vResult;
678 }
679 
681 {
682  double dClosestDist = 9999999999.9;
683  int nClosest = -1;
684  for(unsigned int i=0; i<mMap.vpKeyFrames.size(); i++)
685  {
686  if(mMap.vpKeyFrames[i] == &k)
687  continue;
688  double dDist = KeyFrameLinearDist(k, *mMap.vpKeyFrames[i]);
689  if(dDist < dClosestDist)
690  {
691  dClosestDist = dDist;
692  nClosest = i;
693  }
694  }
695  assert(nClosest != -1);
696  return mMap.vpKeyFrames[nClosest];
697 }
698 
700 {
701  KeyFrame *pClosest = ClosestKeyFrame(kCurrent);
702  double dDist = KeyFrameLinearDist(kCurrent, *pClosest);
703  return dDist;
704 }
705 
707 {
708  KeyFrame *pClosest = ClosestKeyFrame(kCurrent);
709  double dDist = KeyFrameLinearDist(kCurrent, *pClosest);
710  dDist *= (1.0 / kCurrent.dSceneDepthMean);
711 
713  return true;
714  return false;
715 }
716 
717 // Perform bundle adjustment on all keyframes, all map points
719 {
720  // construct the sets of kfs/points to be adjusted:
721  // in this case, all of them
722  set<KeyFrame*> sAdj;
723  set<KeyFrame*> sFixed;
724  for(unsigned int i=0; i<mMap.vpKeyFrames.size(); i++)
725  if(mMap.vpKeyFrames[i]->bFixed)
726  sFixed.insert(mMap.vpKeyFrames[i]);
727  else
728  sAdj.insert(mMap.vpKeyFrames[i]);
729 
730  set<MapPoint*> sMapPoints;
731  for(unsigned int i=0; i<mMap.vpPoints.size();i++)
732  sMapPoints.insert(mMap.vpPoints[i]);
733 
734  BundleAdjust(sAdj, sFixed, sMapPoints, false);
735 }
736 
737 // Peform a local bundle adjustment which only adjusts
738 // recently added key-frames
740 {
741  if(mMap.vpKeyFrames.size() < 8)
742  { // Ignore this unless map is big enough
744  return;
745  }
746 
747  // First, make a list of the keyframes we want adjusted in the adjuster.
748  // This will be the last keyframe inserted, and its four nearest neighbors
749  set<KeyFrame*> sAdjustSet;
750  KeyFrame *pkfNewest = mMap.vpKeyFrames.back();
751  sAdjustSet.insert(pkfNewest);
752  vector<KeyFrame*> vClosest = NClosestKeyFrames(*pkfNewest, 4);
753  for(int i=0; i<4; i++)
754  if(vClosest[i]->bFixed == false)
755  sAdjustSet.insert(vClosest[i]);
756 
757  // Now we find the set of features which they contain.
758  set<MapPoint*> sMapPoints;
759  for(set<KeyFrame*>::iterator iter = sAdjustSet.begin();
760  iter!=sAdjustSet.end();
761  iter++)
762  {
763  map<MapPoint*,Measurement> &mKFMeas = (*iter)->mMeasurements;
764  for(meas_it jiter = mKFMeas.begin(); jiter!= mKFMeas.end(); jiter++)
765  sMapPoints.insert(jiter->first);
766  };
767 
768  // Finally, add all keyframes which measure above points as fixed keyframes
769  set<KeyFrame*> sFixedSet;
770  for(vector<KeyFrame*>::iterator it = mMap.vpKeyFrames.begin(); it!=mMap.vpKeyFrames.end(); it++)
771  {
772  if(sAdjustSet.count(*it))
773  continue;
774  bool bInclude = false;
775  for(meas_it jiter = (*it)->mMeasurements.begin(); jiter!= (*it)->mMeasurements.end(); jiter++)
776  if(sMapPoints.count(jiter->first))
777  {
778  bInclude = true;
779  break;
780  }
781  if(bInclude)
782  sFixedSet.insert(*it);
783  }
784 
785  BundleAdjust(sAdjustSet, sFixedSet, sMapPoints, true);
786 }
787 
788 // Common bundle adjustment code. This creates a bundle-adjust instance, populates it, and runs it.
789 void MapMaker::BundleAdjust(set<KeyFrame*> sAdjustSet, set<KeyFrame*> sFixedSet, set<MapPoint*> sMapPoints, bool bRecent)
790 {
791  Bundle b(mCamera); // Our bundle adjuster
792  mbBundleRunning = true;
793  mbBundleRunningIsRecent = bRecent;
794 
795  // The bundle adjuster does different accounting of keyframes and map points;
796  // Translation maps are stored:
797  map<MapPoint*, int> mPoint_BundleID;
798  map<int, MapPoint*> mBundleID_Point;
799  map<KeyFrame*, int> mView_BundleID;
800  map<int, KeyFrame*> mBundleID_View;
801 
802  // Add the keyframes' poses to the bundle adjuster. Two parts: first nonfixed, then fixed.
803  for(set<KeyFrame*>::iterator it = sAdjustSet.begin(); it!= sAdjustSet.end(); it++)
804  {
805  int nBundleID = b.AddCamera((*it)->se3CfromW, (*it)->bFixed);
806  mView_BundleID[*it] = nBundleID;
807  mBundleID_View[nBundleID] = *it;
808  }
809  for(set<KeyFrame*>::iterator it = sFixedSet.begin(); it!= sFixedSet.end(); it++)
810  {
811  int nBundleID = b.AddCamera((*it)->se3CfromW, true);
812  mView_BundleID[*it] = nBundleID;
813  mBundleID_View[nBundleID] = *it;
814  }
815 
816  // Add the points' 3D position
817  for(set<MapPoint*>::iterator it = sMapPoints.begin(); it!=sMapPoints.end(); it++)
818  {
819  int nBundleID = b.AddPoint((*it)->v3WorldPos);
820  mPoint_BundleID[*it] = nBundleID;
821  mBundleID_Point[nBundleID] = *it;
822  }
823 
824  // Add the relevant point-in-keyframe measurements
825  for(unsigned int i=0; i<mMap.vpKeyFrames.size(); i++)
826  {
827  if(mView_BundleID.count(mMap.vpKeyFrames[i]) == 0)
828  continue;
829 
830  int nKF_BundleID = mView_BundleID[mMap.vpKeyFrames[i]];
831  for(meas_it it= mMap.vpKeyFrames[i]->mMeasurements.begin();
832  it!= mMap.vpKeyFrames[i]->mMeasurements.end();
833  it++)
834  {
835  if(mPoint_BundleID.count(it->first) == 0)
836  continue;
837  int nPoint_BundleID = mPoint_BundleID[it->first];
838  b.AddMeas(nKF_BundleID, nPoint_BundleID, it->second.v2RootPos, LevelScale(it->second.nLevel) * LevelScale(it->second.nLevel));
839  }
840  }
841 
842  // Run the bundle adjuster. This returns the number of successful iterations
843  int nAccepted = b.Compute(&mbBundleAbortRequested);
844 
845  if(nAccepted < 0)
846  {
847  // Crap: - LM Ran into a serious problem!
848  // This is probably because the initial stereo was messed up.
849  // Get rid of this map and start again!
850  cout << "!! MapMaker: Cholesky failure in bundle adjust. " << endl
851  << " The map is probably corrupt: Ditching the map. " << endl;
852  mbResetRequested = true;
853  return;
854  }
855 
856  // Bundle adjustment did some updates, apply these to the map
857  if(nAccepted > 0)
858  {
859 
860  for(map<MapPoint*,int>::iterator itr = mPoint_BundleID.begin();
861  itr!=mPoint_BundleID.end();
862  itr++)
863  itr->first->v3WorldPos = b.GetPoint(itr->second);
864 
865  for(map<KeyFrame*,int>::iterator itr = mView_BundleID.begin();
866  itr!=mView_BundleID.end();
867  itr++)
868  itr->first->se3CfromW = b.GetCamera(itr->second);
869  if(bRecent)
870  mbBundleConverged_Recent = false;
871  mbBundleConverged_Full = false;
872  };
873 
874  if(b.Converged())
875  {
877  if(!bRecent)
878  mbBundleConverged_Full = true;
879  }
880 
881  mbBundleRunning = false;
882  mbBundleAbortRequested = false;
883 
884  // Handle outlier measurements:
885  vector<pair<int,int> > vOutliers_PC_pair = b.GetOutlierMeasurements();
886  for(unsigned int i=0; i<vOutliers_PC_pair.size(); i++)
887  {
888  MapPoint *pp = mBundleID_Point[vOutliers_PC_pair[i].first];
889  KeyFrame *pk = mBundleID_View[vOutliers_PC_pair[i].second];
890  Measurement &m = pk->mMeasurements[pp];
891  if(pp->pMMData->GoodMeasCount() <= 2 || m.Source == Measurement::SRC_ROOT) // Is the original source kf considered an outlier? That's bad.
892  pp->bBad = true;
893  else
894  {
895  // Do we retry it? Depends where it came from!!
897  mvFailureQueue.push_back(pair<KeyFrame*,MapPoint*>(pk,pp));
898  else
899  pp->pMMData->sNeverRetryKFs.insert(pk);
900  pk->mMeasurements.erase(pp);
901  pp->pMMData->sMeasurementKFs.erase(pk);
902  }
903  }
904 }
905 
906 // Mapmaker's try-to-find-a-point-in-a-keyframe code. This is used to update
907 // data association if a bad measurement was detected, or if a point
908 // was never searched for in a keyframe in the first place. This operates
909 // much like the tracker! So most of the code looks just like in
910 // TrackerData.h.
912 {
913  // abort if either a measurement is already in the map, or we've
914  // decided that this point-kf combo is beyond redemption
915  if(p.pMMData->sMeasurementKFs.count(&k)
916  || p.pMMData->sNeverRetryKFs.count(&k))
917  return false;
918 
919  static PatchFinder Finder;
920  Vector<3> v3Cam = k.se3CfromW*p.v3WorldPos;
921  if(v3Cam[2] < 0.001)
922  {
923  p.pMMData->sNeverRetryKFs.insert(&k);
924  return false;
925  }
926  Vector<2> v2ImPlane = project(v3Cam);
927  if(v2ImPlane* v2ImPlane > mCamera.LargestRadiusInImage() * mCamera.LargestRadiusInImage())
928  {
929  p.pMMData->sNeverRetryKFs.insert(&k);
930  return false;
931  }
932 
933  Vector<2> v2Image = mCamera.Project(v2ImPlane);
934  if(mCamera.Invalid())
935  {
936  p.pMMData->sNeverRetryKFs.insert(&k);
937  return false;
938  }
939 
940  ImageRef irImageSize = k.aLevels[0].im.size();
941  if(v2Image[0] < 0 || v2Image[1] < 0 || v2Image[0] > irImageSize[0] || v2Image[1] > irImageSize[1])
942  {
943  p.pMMData->sNeverRetryKFs.insert(&k);
944  return false;
945  }
946 
947  Matrix<2> m2CamDerivs = mCamera.GetProjectionDerivs();
948  Finder.MakeTemplateCoarse(p, k.se3CfromW, m2CamDerivs);
949 
950  if(Finder.TemplateBad())
951  {
952  p.pMMData->sNeverRetryKFs.insert(&k);
953  return false;
954  }
955 
956  bool bFound = Finder.FindPatchCoarse(ir(v2Image), k, 4); // Very tight search radius!
957  if(!bFound)
958  {
959  p.pMMData->sNeverRetryKFs.insert(&k);
960  return false;
961  }
962 
963  // If we found something, generate a measurement struct and put it in the map
964  Measurement m;
965  m.nLevel = Finder.GetLevel();
967 
968  if(Finder.GetLevel() > 0)
969  {
970  Finder.MakeSubPixTemplate();
971  Finder.IterateSubPixToConvergence(k,8);
972  m.v2RootPos = Finder.GetSubPixPos();
973  m.bSubPix = true;
974  }
975  else
976  {
977  m.v2RootPos = Finder.GetCoarsePosAsVector();
978  m.bSubPix = false;
979  };
980 
981  if(k.mMeasurements.count(&p))
982  {
983  assert(0); // This should never happen, we checked for this at the start.
984  }
985  k.mMeasurements[&p] = m;
986  p.pMMData->sMeasurementKFs.insert(&k);
987  return true;
988 }
989 
990 // A general data-association update for a single keyframe
991 // Do this on a new key-frame when it's passed in by the tracker
993 {
994  vector<MapPoint*> vToFind;
995  for(unsigned int i=0; i<mMap.vpPoints.size(); i++)
996  vToFind.push_back(mMap.vpPoints[i]);
997 
998  int nFoundNow = 0;
999  for(unsigned int i=0; i<vToFind.size(); i++)
1000  if(ReFind_Common(k,*vToFind[i]))
1001  nFoundNow++;
1002 
1003  return nFoundNow;
1004 };
1005 
1006 // When new map points are generated, they're only created from a stereo pair
1007 // this tries to make additional measurements in other KFs which they might
1008 // be in.
1010 {
1011  if(mqNewQueue.empty())
1012  return;
1013  int nFound = 0;
1014  int nBad = 0;
1015  while(!mqNewQueue.empty() && mvpKeyFrameQueue.size() == 0)
1016  {
1017  MapPoint* pNew = mqNewQueue.front();
1018  mqNewQueue.pop();
1019  if(pNew->bBad)
1020  {
1021  nBad++;
1022  continue;
1023  }
1024  for(unsigned int i=0; i<mMap.vpKeyFrames.size(); i++)
1025  if(ReFind_Common(*mMap.vpKeyFrames[i], *pNew))
1026  nFound++;
1027  }
1028 };
1029 
1030 // Dud measurements get a second chance.
1032 {
1033  if(mvFailureQueue.size() == 0)
1034  return;
1035  sort(mvFailureQueue.begin(), mvFailureQueue.end());
1036  vector<pair<KeyFrame*, MapPoint*> >::iterator it;
1037  int nFound=0;
1038  for(it = mvFailureQueue.begin(); it!=mvFailureQueue.end(); it++)
1039  if(ReFind_Common(*it->first, *it->second))
1040  nFound++;
1041 
1042  mvFailureQueue.erase(mvFailureQueue.begin(), it);
1043 };
1044 
1045 // Is the tracker's camera pose in cloud-cuckoo land?
1047 {
1048  return DistToNearestKeyFrame(kCurrent) > mdWiggleScale * 10.0;
1049 }
1050 
1051 // Find a dominant plane in the map, find an SE3<> to put it as the z=0 plane
1053 {
1054  unsigned int nPoints = mMap.vpPoints.size();
1055  if(nPoints < 10)
1056  {
1057  cout << " MapMaker: CalcPlane: too few points to calc plane." << endl;
1058  return SE3<>();
1059  };
1060 
1061  int nRansacs = MapMakerPlaneAlignerRansacs;
1062  Vector<3> v3BestMean;
1063  Vector<3> v3BestNormal;
1064  double dBestDistSquared = 9999999999999999.9;
1065 
1066  for(int i=0; i<nRansacs; i++)
1067  {
1068  int nA = rand()%nPoints;
1069  int nB = nA;
1070  int nC = nA;
1071  while(nB == nA)
1072  nB = rand()%nPoints;
1073  while(nC == nA || nC==nB)
1074  nC = rand()%nPoints;
1075 
1076  Vector<3> v3Mean = 0.33333333 * (mMap.vpPoints[nA]->v3WorldPos +
1077  mMap.vpPoints[nB]->v3WorldPos +
1078  mMap.vpPoints[nC]->v3WorldPos);
1079 
1080  Vector<3> v3CA = mMap.vpPoints[nC]->v3WorldPos - mMap.vpPoints[nA]->v3WorldPos;
1081  Vector<3> v3BA = mMap.vpPoints[nB]->v3WorldPos - mMap.vpPoints[nA]->v3WorldPos;
1082  Vector<3> v3Normal = v3CA ^ v3BA;
1083  if(v3Normal * v3Normal == 0)
1084  continue;
1085  normalize(v3Normal);
1086 
1087  double dSumError = 0.0;
1088  for(unsigned int i=0; i<nPoints; i++)
1089  {
1090  Vector<3> v3Diff = mMap.vpPoints[i]->v3WorldPos - v3Mean;
1091  double dDistSq = v3Diff * v3Diff;
1092  if(dDistSq == 0.0)
1093  continue;
1094  double dNormDist = fabs(v3Diff * v3Normal);
1095 
1096  if(dNormDist > 0.05)
1097  dNormDist = 0.05;
1098  dSumError += dNormDist;
1099  }
1100  if(dSumError < dBestDistSquared)
1101  {
1102  dBestDistSquared = dSumError;
1103  v3BestMean = v3Mean;
1104  v3BestNormal = v3Normal;
1105  }
1106  }
1107 
1108  // Done the ransacs, now collect the supposed inlier set
1109  vector<Vector<3> > vv3Inliers;
1110  for(unsigned int i=0; i<nPoints; i++)
1111  {
1112  Vector<3> v3Diff = mMap.vpPoints[i]->v3WorldPos - v3BestMean;
1113  double dDistSq = v3Diff * v3Diff;
1114  if(dDistSq == 0.0)
1115  continue;
1116  double dNormDist = fabs(v3Diff * v3BestNormal);
1117  if(dNormDist < 0.05)
1118  vv3Inliers.push_back(mMap.vpPoints[i]->v3WorldPos);
1119  }
1120 
1121  // With these inliers, calculate mean and cov
1122  Vector<3> v3MeanOfInliers = Zeros;
1123  for(unsigned int i=0; i<vv3Inliers.size(); i++)
1124  v3MeanOfInliers+=vv3Inliers[i];
1125  v3MeanOfInliers *= (1.0 / vv3Inliers.size());
1126 
1127  Matrix<3> m3Cov = Zeros;
1128  for(unsigned int i=0; i<vv3Inliers.size(); i++)
1129  {
1130  Vector<3> v3Diff = vv3Inliers[i] - v3MeanOfInliers;
1131  m3Cov += v3Diff.as_col() * v3Diff.as_row();
1132  };
1133 
1134  // Find the principal component with the minimal variance: this is the plane normal
1135  SymEigen<3> sym(m3Cov);
1136  Vector<3> v3Normal = sym.get_evectors()[0];
1137 
1138  // Use the version of the normal which points towards the cam center
1139  if(v3Normal[2] > 0)
1140  v3Normal *= -1.0;
1141 
1142  Matrix<3> m3Rot = Identity;
1143  m3Rot[2] = v3Normal;
1144  m3Rot[0] = m3Rot[0] - (v3Normal * (m3Rot[0] * v3Normal));
1145  normalize(m3Rot[0]);
1146  m3Rot[1] = m3Rot[2] ^ m3Rot[0];
1147 
1148  SE3<> se3Aligner;
1149  se3Aligner.get_rotation() = m3Rot;
1150  Vector<3> v3RMean = se3Aligner * v3MeanOfInliers;
1151  se3Aligner.get_translation() = -v3RMean;
1152 
1153  return se3Aligner;
1154 }
1155 
1156 // Calculates the depth(z-) distribution of map points visible in a keyframe
1157 // This function is only used for the first two keyframes - all others
1158 // get this filled in by the tracker
1160 {
1161  double dSumDepth = 0.0;
1162  double dSumDepthSquared = 0.0;
1163  int nMeas = 0;
1164  for(meas_it it = pKF->mMeasurements.begin(); it!=pKF->mMeasurements.end(); it++)
1165  {
1166  MapPoint &point = *it->first;
1167  Vector<3> v3PosK = pKF->se3CfromW * point.v3WorldPos;
1168  dSumDepth += v3PosK[2];
1169  dSumDepthSquared += v3PosK[2] * v3PosK[2];
1170  nMeas++;
1171  }
1172 
1173  assert(nMeas > 2); // If not then something is seriously wrong with this KF!!
1174  pKF->dSceneDepthMean = dSumDepth / nMeas;
1175  pKF->dSceneDepthSigma = sqrt((dSumDepthSquared / nMeas) - (pKF->dSceneDepthMean) * (pKF->dSceneDepthMean));
1176 }
1177 
1178 void MapMaker::GUICommandCallBack(void* ptr, string sCommand, string sParams)
1179 {
1180  Command c;
1181  c.sCommand = sCommand;
1182  c.sParams = sParams;
1183  ((MapMaker*) ptr)->mvQueuedCommands.push_back(c);
1184 }
1185 
1186 void MapMaker::GUICommandHandler(string sCommand, string sParams) // Called by the callback func..
1187 {
1188  if(sCommand=="SaveMap")
1189  {
1190  cout << " MapMaker: Saving the map.... " << endl;
1191  ofstream ofs("map.dump");
1192  for(unsigned int i=0; i<mMap.vpPoints.size(); i++)
1193  {
1194  ofs << mMap.vpPoints[i]->v3WorldPos << " ";
1195  ofs << mMap.vpPoints[i]->nSourceLevel << endl;
1196  }
1197  ofs.close();
1198 
1199  for(unsigned int i=0; i<mMap.vpKeyFrames.size(); i++)
1200  {
1201  ostringstream ost1;
1202  ost1 << "keyframes/" << i << ".jpg";
1203 // img_save(mMap.vpKeyFrames[i]->aLevels[0].im, ost1.str());
1204 
1205  ostringstream ost2;
1206  ost2 << "keyframes/" << i << ".info";
1207  ofstream ofs2;
1208  ofs2.open(ost2.str().c_str());
1209  ofs2 << mMap.vpKeyFrames[i]->se3CfromW << endl;
1210  ofs2.close();
1211  }
1212  cout << " ... done saving map." << endl;
1213  return;
1214  }
1215 
1216  cout << "! MapMaker::GUICommandHandler: unhandled command "<< sCommand << endl;
1217  exit(1);
1218 };
1219 
1220 
1221 
1222 
1223 
1224 
1225 
1226 
1227 
1228 
1229 
1230 
void normalize(Vector< Size, Precision, Base > v)
Definition: helpers.h:138
bool mbBundleConverged_Recent
Definition: MapMaker.h:124
bool bBad
Definition: MapPoint.h:43
const int CounterForConvergenceLimit
Definition: globals.h:53
bool bSubPix
Definition: KeyFrame.h:47
KeyFrame * ClosestKeyFrame(KeyFrame &k)
Definition: MapMaker.cpp:680
std::map< MapPoint *, Measurement >::iterator meas_it
Definition: KeyFrame.h:97
bool Compute(std::vector< HomographyMatch > vMatches, double dMaxPixelError, SE3<> &se3SecondCameraPose)
int LevelScale(int nLevel)
Definition: LevelHelpers.h:20
SmallBlurryImage * pSBI
Definition: KeyFrame.h:94
Definition: so3.h:39
bool IsDistanceToNearestKeyFrameExcessive(KeyFrame &kCurrent)
Definition: MapMaker.cpp:1046
int AddPoint(Vector< 3 > v3Pos)
Definition: Bundle.cpp:65
void GUICommandHandler(std::string sCommand, std::string sParams)
Definition: MapMaker.cpp:1186
#define LOGV(LOG_TAG,...)
Definition: globals.h:10
std::queue< MapPoint * > mqNewQueue
Definition: MapMaker.h:115
#define LOG_TAG
Definition: globals.h:9
Vector< 3 > ReprojectPoint(SE3<> se3AfromB, const Vector< 2 > &v2A, const Vector< 2 > &v2B)
Definition: MapMaker.cpp:173
void AddSomeMapPoints(int nLevel)
Definition: MapMaker.cpp:407
int nMEstimatorOutlierCount
Definition: MapPoint.h:70
std::vector< KeyFrame * > NClosestKeyFrames(KeyFrame &k, unsigned int N)
Definition: MapMaker.cpp:660
int Compute(bool *pbAbortSignal)
Definition: Bundle.cpp:114
bool FindPatchCoarse(CVD::ImageRef ir, KeyFrame &kf, unsigned int nRange)
std::vector< Command > mvQueuedCommands
Definition: MapMaker.h:109
SO3< Precision > & get_rotation()
Returns the rotation part of the transformation as a SO3.
Definition: se3.h:64
static Operator< Internal::Identity< Internal::One > > Identity
Definition: objects.h:748
int GetLevel()
Definition: PatchFinder.h:63
int counterForConvergenceLimit
Definition: MapMaker.h:136
void resize(const ImageRef &size)
Definition: image.h:749
bool AddPointEpipolar(KeyFrame &kSrc, KeyFrame &kTarget, int nLevel, int nCandidate)
Definition: MapMaker.cpp:497
void SetSendMessageToUnity(SendMessage sm)
Definition: MapMaker.cpp:56
Vector< 3 > v3Center_NC
Definition: MapPoint.h:54
Vector< 2 > Project(const Vector< 2 > &camframe)
Definition: ATANCamera.cpp:109
SendMessage sendStringToUnity
Definition: MapMaker.h:134
void MakeTemplateCoarseNoWarp(MapPoint &p)
Vector< 3 > v3OneDownFromCenter_NC
Definition: MapPoint.h:55
void stop()
Tell the thread to stop.
Definition: thread.cpp:43
TooN::Vector< 2 > vec(const ImageRef &ir)
int QueueSize()
Definition: MapMaker.h:58
Definition: Bundle.h:105
CVD::Image< CVD::byte > im
Definition: KeyFrame.h:59
bool ResetDone()
Definition: MapMaker.cpp:126
ImageRef ir_rounded(const TooN::Vector< 2 > &v)
bool bFixed
Definition: KeyFrame.h:83
void MakeSubPixTemplate()
bool bGood
Definition: Map.h:37
double dSceneDepthSigma
Definition: KeyFrame.h:92
Vector< 3 > v3Normal_NC
Definition: MapPoint.h:57
void SetSubPixPos(Vector< 2 > v2)
Definition: PatchFinder.h:96
MapMakerData * pMMData
Definition: MapPoint.h:64
Vector<(Size==Dynamic?Dynamic:Size+1), Precision > unproject(const Vector< Size, Precision, Base > &v)
Definition: helpers.h:166
void SendStringToUnity(const char *st)
Send string to Unity3D
Definition: SendMessage.cpp:46
bool NeedNewKeyFrame(KeyFrame &kCurrent)
Definition: MapMaker.cpp:706
SE3 inverse() const
Definition: se3.h:86
const int MapMakerPlaneAlignerRansacs
Definition: globals.h:17
Definition: abs.h:24
bool ReFind_Common(KeyFrame &k, MapPoint &p)
Definition: MapMaker.cpp:911
void AddKeyFrame(KeyFrame &k)
Definition: MapMaker.cpp:453
double mdWiggleScaleDepthNormalized
Definition: MapMaker.h:120
SE3 CalcPlaneAligner()
Definition: MapMaker.cpp:1052
enum Measurement::@4 Source
Vector< 2 > GetSubPixPos()
Definition: PatchFinder.h:95
bool mbBundleRunningIsRecent
Definition: MapMaker.h:131
void start(Runnable *runnable=0)
Start execution of "run" method in separate thread.
Definition: thread.cpp:32
Vector< 2 > UnProject(const Vector< 2 > &imframe)
Definition: ATANCamera.cpp:125
Matrix< Size, Size, Precision > & get_evectors()
Definition: SymEigen.h:336
std::vector< MapPoint * > vpPoints
Definition: Map.h:33
virtual void run()
Override this method to do whatever it is the thread should do.
Definition: MapMaker.cpp:66
int AddCamera(SE3<> se3CamFromWorld, bool bFixed)
Definition: Bundle.cpp:45
Vector< 2 > GetCoarsePosAsVector()
Definition: PatchFinder.h:87
bool bImplaneCornersCached
Definition: KeyFrame.h:69
MapMaker(Map &m, const ATANCamera &cam)
Definition: MapMaker.cpp:29
const double MapMakerWiggleScale
Definition: globals.h:25
void BundleAdjustRecent()
Definition: MapMaker.cpp:739
void ApplyGlobalTransformationToMap(SE3<> se3NewFromOld)
Definition: MapMaker.cpp:420
std::string sParams
Definition: MapMaker.h:108
bool IterateSubPixToConvergence(KeyFrame &kf, int nMaxIts)
void ReFindFromFailureQueue()
Definition: MapMaker.cpp:1031
bool TemplateBad()
Definition: PatchFinder.h:76
bool mbBundleRunning
Definition: MapMaker.h:130
bool next(const ImageRef &max)
Definition: image_ref.h:220
Level aLevels[LEVELS]
Definition: KeyFrame.h:84
int nSourceLevel
Definition: MapPoint.h:47
Definition: SVD.h:89
CVD::ImageRef irCenter
Definition: MapPoint.h:48
ATANCamera mCamera
Definition: MapMaker.h:66
std::vector< CVD::ImageRef > vCorners
Definition: KeyFrame.h:62
void AddMeas(int nCam, int nPoint, Vector< 2 > v2Pos, double dSigmaSquared)
Definition: Bundle.cpp:80
Definition: se3.h:50
Matrix< 2 > m2PixelProjectionJac
std::vector< Vector< 2 > > vImplaneCorners
Definition: KeyFrame.h:70
void RequestReset()
Definition: MapMaker.cpp:120
void MakeKeyFrame_Rest()
Definition: KeyFrame.cpp:69
std::vector< KeyFrame * > vpKeyFrames
Definition: Map.h:35
std::vector< std::pair< KeyFrame *, MapPoint * > > mvFailureQueue
Definition: MapMaker.h:114
bool InitFromStereo(KeyFrame &kFirst, KeyFrame &kSecond, std::vector< std::pair< CVD::ImageRef, CVD::ImageRef > > &vMatches, SE3<> &se3CameraPos)
Definition: MapMaker.cpp:196
SE3 se3CfromW
Definition: KeyFrame.h:82
std::set< KeyFrame * > sMeasurementKFs
Definition: MapMaker.h:32
Vector< 3 > v3WorldPos
Definition: MapPoint.h:38
Definition: KeyFrame.h:54
int ReFindInSingleKeyFrame(KeyFrame &k)
Definition: MapMaker.cpp:992
bool IsGood()
Definition: Map.h:27
ImageRef size() const
What is the size of this image?
Definition: image.h:370
bool mbBundleConverged_Full
Definition: MapMaker.h:123
void HandleBadPoints()
Definition: MapMaker.cpp:133
#define CHECK_RESET
Definition: MapMaker.cpp:64
bool mbBundleAbortRequested
Definition: MapMaker.h:129
Vector< 2 > v2RootPos
Definition: KeyFrame.h:48
bool Invalid()
Definition: ATANCamera.h:89
Definition: Map.h:24
Vector< 3 > v3OneRightFromCenter_NC
Definition: MapPoint.h:56
int nLevel
Definition: KeyFrame.h:46
ImageRef ir(const TooN::Vector< 2 > &v)
int nMEstimatorInlierCount
Definition: MapPoint.h:71
double DistToNearestKeyFrame(KeyFrame &kCurrent)
Definition: MapMaker.cpp:699
void ThinCandidates(KeyFrame &k, int nLevel)
Definition: MapMaker.cpp:369
int ZMSSDAtPoint(CVD::BasicImage< CVD::byte > &im, const CVD::ImageRef &ir)
void RefreshSceneDepth(KeyFrame *pKF)
Definition: MapMaker.cpp:1159
bool mbResetRequested
Definition: MapMaker.h:127
void BundleAdjustAll()
Definition: MapMaker.cpp:718
Vector< 3, Precision > & get_translation()
Returns the translation part of the transformation as a Vector.
Definition: se3.h:69
std::map< MapPoint *, Measurement > mMeasurements
Definition: KeyFrame.h:85
Vector< 1 > makeVector(double x1)
Definition: make_vector.hh:4
Matrix< Min_Dim, Cols, Precision, Reference::RowMajor > get_VT()
Definition: SVD.h:254
double OnePixelDist()
Definition: ATANCamera.h:91
KeyFrame * pPatchSourceKF
Definition: MapPoint.h:46
SE3 GetCamera(int n)
Definition: Bundle.cpp:630
void SetImageSize(Vector< 2 > v2ImageSize)
Definition: ATANCamera.cpp:21
Vector< 2 > v2CamPlaneFirst
int GoodMeasCount()
Definition: MapMaker.h:34
static void GUICommandCallBack(void *ptr, std::string sCommand, std::string sParams)
Definition: MapMaker.cpp:1178
double dSceneDepthMean
Definition: KeyFrame.h:91
double mdWiggleScale
Definition: MapMaker.h:117
bool shouldStop() const
Returns true if the stop() method been called, false otherwise.
Definition: thread.cpp:48
Vector< 3 > GetPoint(int n)
Definition: Bundle.cpp:625
double LargestRadiusInImage()
Definition: ATANCamera.h:90
std::vector< KeyFrame * > mvpKeyFrameQueue
Definition: MapMaker.h:113
void MakeTemplateCoarse(MapPoint &p, SE3<> se3CFromW, Matrix< 2 > &m2CamDerivs)
Definition: PatchFinder.cpp:72
void AddKeyFrameFromTopOfQueue()
Definition: MapMaker.cpp:464
double LevelZeroPos(double dLevelPos, int nLevel)
Definition: LevelHelpers.h:26
void ApplyGlobalScaleToMap(double dScale)
Definition: MapMaker.cpp:435
bool Converged()
Definition: Bundle.h:114
void MoveBadPointsToTrash()
Definition: Map.cpp:19
std::vector< Candidate > vCandidates
Definition: KeyFrame.h:67
std::string sCommand
Definition: MapMaker.h:108
Map & mMap
Definition: MapMaker.h:65
int counterForConvergence
Definition: MapMaker.h:135
void Reset()
Definition: Map.cpp:10
void ReFindNewlyMade()
Definition: MapMaker.cpp:1009
Matrix< 2, 2 > GetProjectionDerivs()
Definition: ATANCamera.cpp:172
void RefreshPixelVectors()
Definition: MapPoint.cpp:4
std::set< KeyFrame * > sNeverRetryKFs
Definition: MapMaker.h:33
double KeyFrameLinearDist(KeyFrame &k1, KeyFrame &k2)
Definition: MapMaker.cpp:651
static Operator< Internal::Zero > Zeros
Definition: objects.h:727
bool mbResetDone
Definition: MapMaker.h:128
Vector<(Size==Dynamic?Dynamic:Size-1), Precision > project(const Vector< Size, Precision, Base > &v)
Definition: helpers.h:157
void Reset()
Definition: MapMaker.cpp:38
void BundleAdjust(std::set< KeyFrame * >, std::set< KeyFrame * >, std::set< MapPoint * >, bool)
Definition: MapMaker.cpp:789
Vector< 2 > v2CamPlaneSecond
#define cout
Definition: Bundle.cpp:16
void join()
This blocks until the thread has actually terminated.
Definition: thread.cpp:58
static void sleep(unsigned int milli)
Tell the current thread to sleep for milli milliseconds.
Definition: thread.cpp:79
CVD::ImageRef irLevelPos
Definition: KeyFrame.h:38
std::vector< std::pair< int, int > > GetOutlierMeasurements()
Definition: Bundle.cpp:649
double mgvdWiggleScale
Definition: MapMaker.h:119
const double MapMakerMaxKFDistWiggleMult
Definition: globals.h:16