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.
Bundle.cpp
Go to the documentation of this file.
1 // Copyright 2008 Isis Innovation Limited
2 //#include <BundleHelpers.h>
3 #include "Bundle.h"
4 #include "MEstimator.h"
5 #include "helpers.h"
6 #include "Cholesky.h"
7 #include <fstream>
8 #include <iomanip>
9 
10 using namespace std;
11 
12 #ifdef WIN32
13 inline bool isnan(double d) {return !(d==d);}
14 #endif
15 
16 #define cout if(mgvnBundleCout) cout
17 
18 // Some inlines which replace standard matrix multiplications
19 // with LL-triangle-only versions.
21 {
22  for(int r=0; r<6; r++)
23  for(int c=0; c<=r; c++)
24  m6U(r,c)+= m26A.T()(r,0)*m26A(0,c) + m26A.T()(r,1)*m26A(1,c);
25 }
27 {
28  for(int r=0; r<3; r++)
29  for(int c=0; c<=r; c++)
30  m3V(r,c)+= m23B.T()(r,0)*m23B(0,c) + m23B.T()(r,1)*m23B(1,c);
31 }
32 
33 // Constructor copies MapMaker's camera parameters
35  : mCamera(TCam)
36 {
37  mnCamsToUpdate = 0;
38  mnStartRow = 0;
42 };
43 
44 // Add a camera to the system, return value is the bundle adjuster's ID for the camera
45 int Bundle::AddCamera(SE3<> se3CamFromWorld, bool bFixed)
46 {
47  int n = mvCameras.size();
48  Camera c;
49  c.bFixed = bFixed;
50  c.se3CfW = se3CamFromWorld;
51  if(!bFixed)
52  {
54  mnStartRow += 6;
56  }
57  else
58  c.nStartRow = -999999999;
59  mvCameras.push_back(c);
60 
61  return n;
62 }
63 
64 // Add a map point to the system, return value is the bundle adjuster's ID for the point
66 {
67  int n = mvPoints.size();
69 // if(isnan(v3Pos * v3Pos))
70 // {
71 // cerr << " You sucker, tried to give me a nan " << v3Pos << endl;
72 // v3Pos = Zeros;
73 // }
74  p.v3Pos = v3Pos;
75  mvPoints.push_back(p);
76  return n;
77 }
78 
79 // Add a measurement of one point with one camera
80 void Bundle::AddMeas(int nCam, int nPoint, Vector<2> v2Pos, double dSigmaSquared)
81 {
82  assert(nCam < (int) mvCameras.size());
83  assert(nPoint < (int) mvPoints.size());
84  mvPoints[nPoint].nMeasurements++;
85  mvPoints[nPoint].sCameras.insert(nCam);
86  Meas m;
87  m.p = nPoint;
88  m.c = nCam;
89  m.v2Found = v2Pos;
90  m.dSqrtInvNoise = sqrt(1.0 / dSigmaSquared);
91  mMeasList.push_back(m);
92 }
93 
94 // Zero temporary quantities stored in cameras and points
96 {
97  for(size_t i=0; i<mvPoints.size(); ++i)
98  {
99  mvPoints[i].m3V = Zeros;
100  mvPoints[i].v3EpsilonB = Zeros;
101  }
102  for(size_t i=0; i<mvCameras.size(); ++i)
103  {
104  mvCameras[i].m6U = Zeros;
105  mvCameras[i].v6EpsilonA = Zeros;
106  }
107 }
108 
109 // Perform bundle adjustment. The parameter points to a signal bool
110 // which mapmaker will set to high if another keyframe is incoming
111 // and bundle adjustment needs to be aborted.
112 // Returns number of accepted iterations if all good, negative
113 // value for big error.
114 int Bundle::Compute(bool *pbAbortSignal)
115 {
116  mpbAbortSignal = pbAbortSignal;
117 
118  // Some speedup data structures
121 
122  // Initially behave like gauss-newton
123  mdLambda = 0.0001;
124  mdLambdaFactor = 2.0;
125  mbConverged = false;
126  mbHitMaxIterations = false;
127  mnCounter = 0;
128  mnAccepted = 0;
129  double lastMdSigmaSquared = 0;
130 
131  // What MEstimator are we using today?
132  static string gvsMEstimator=BundleMEstimator;
133 
134  while(!mbConverged && !mbHitMaxIterations && !*pbAbortSignal)
135  {
136  bool bNoError;
137  if(gvsMEstimator == "Cauchy")
138  bNoError = Do_LM_Step<Cauchy>(pbAbortSignal, &lastMdSigmaSquared);
139  else if(gvsMEstimator == "Tukey")
140  bNoError = Do_LM_Step<Tukey>(pbAbortSignal, &lastMdSigmaSquared);
141  else if(gvsMEstimator == "Huber")
142  bNoError = Do_LM_Step<Huber>(pbAbortSignal, &lastMdSigmaSquared);
143  else
144  {
145  cout << "Invalid BundleMEstimator selected !! " << endl;
146  cout << "Defaulting to Tukey." << endl;
147  gvsMEstimator = "Tukey";
148  bNoError = Do_LM_Step<Tukey>(pbAbortSignal, &lastMdSigmaSquared);
149  };
150 
151  if(!bNoError)
152  return -1;
153  }
154 
156  {
157  cout << " Hit max iterations." << endl;
158  LOGV(LOG_TAG, "Info: %s", " Hit max iterations.");
159  }
160  cout << "Final Sigma Squared: " << mdSigmaSquared << " (= " << sqrt(mdSigmaSquared) / 4.685 << " pixels.)" << endl;
161 
162  return mnAccepted;
163 };
164 
165 // Reproject a single measurement, find error
167 {
168  Camera &cam = mvCameras[meas.c];
169  ExtendedMapPoint &point = mvPoints[meas.p];
170 
171  // Project the point.
172  meas.v3Cam = cam.se3CfW * point.v3Pos;
173  if(meas.v3Cam[2] <= 0)
174  {
175  meas.bBad = true;
176  return;
177  }
178  meas.bBad = false;
179  Vector<2> v2ImPlane = project(meas.v3Cam);
180  Vector<2> v2Image = mCamera.Project(v2ImPlane);
182  meas.v2Epsilon = meas.dSqrtInvNoise * (meas.v2Found - v2Image);
183  meas.dErrorSquared = meas.v2Epsilon * meas.v2Epsilon;
184 }
185 
186 template<class MEstimator>
187 bool Bundle::Do_LM_Step(bool *pbAbortSignal, double *lastMdSigmaSquared)
188 {
189  // Reset all accumulators to zero
191 
192  // Do a LM step according to Hartley and Zisserman Algo A6.4 in MVG 2nd Edition
193  // Actual work starts a bit further down - first we have to work out the
194  // projections and errors for each point, so we can do tukey reweighting
195  vector<double> vdErrorSquared;
196  for(list<Meas>::iterator itr = mMeasList.begin(); itr!=mMeasList.end(); itr++)
197  {
198  Meas &meas = *itr;
200  if(!meas.bBad)
201  vdErrorSquared.push_back(meas.dErrorSquared);
202  };
203 
204  // Projected all points and got vector of errors; find the median,
205  // And work out robust estimate of sigma, then scale this for the tukey
206  // estimator
207  mdSigmaSquared = MEstimator::FindSigmaSquared(vdErrorSquared);
208 
209  // Initially the median error might be very small - set a minimum
210  // value so that good measurements don't get erased!
211  static double gvdMinSigma=BundleMinTukeySigma;
212  const double dMinSigmaSquared = gvdMinSigma * gvdMinSigma;
213  if(mdSigmaSquared < dMinSigmaSquared)
214  mdSigmaSquared = dMinSigmaSquared;
215 
216 
217  // OK - good to go! weights can now be calced on second run through the loop.
218  // Back to Hartley and Zisserman....
219  // `` (i) Compute the derivative matrices Aij = [dxij/daj]
220  // and Bij = [dxij/dbi] and the error vectors eij''
221  //
222  // Here we do this by looping over all measurements
223  //
224  // While we're here, might as well update the accumulators U, ea, B, eb
225  // from part (ii) as well, and let's calculate Wij while we're here as well.
226 
227  double dCurrentError = 0.0;
228  for(list<Meas>::iterator itr = mMeasList.begin(); itr!=mMeasList.end(); itr++)
229  {
230  Meas &meas = *itr;
231  Camera &cam = mvCameras[meas.c];
232  ExtendedMapPoint &point = mvPoints[meas.p];
233 
234  // Project the point.
235  // We've done this before - results are still cached in meas.
236  if(meas.bBad)
237  {
238  dCurrentError += 1.0;
239  continue;
240  };
241 
242  // What to do with the weights? The easiest option is to independently weight
243  // The two jacobians, A and B, with sqrt of the tukey weight w;
244  // And also weight the error vector v2Epsilon.
245  // That makes everything else automatic.
246  // Calc the square root of the tukey weight:
247  double dWeight= MEstimator::SquareRootWeight(meas.dErrorSquared, mdSigmaSquared);
248  // Re-weight error:
249  meas.v2Epsilon = dWeight * meas.v2Epsilon;
250 
251  if(dWeight == 0)
252  {
253  meas.bBad = true;
254  dCurrentError += 1.0;
255  continue;
256  }
257 
258  dCurrentError += MEstimator::ObjectiveScore(meas.dErrorSquared, mdSigmaSquared);
259 
260  // To re-weight the jacobians, I'll just re-weight the camera param matrix
261  // This is only used for the jacs and will save a few fmuls
262  Matrix<2> m2CamDerivs = dWeight * meas.m2CamDerivs;
263 
264  const double dOneOverCameraZ = 1.0 / meas.v3Cam[2];
265  const Vector<4> v4Cam = unproject(meas.v3Cam);
266 
267  // Calculate A: (the proj derivs WRT the camera)
268  if(cam.bFixed)
269  meas.m26A = Zeros;
270  else
271  {
272  for(int m=0;m<6;m++)
273  {
274  const Vector<4> v4Motion = SE3<>::generator_field(m, v4Cam);
275  Vector<2> v2CamFrameMotion;
276  v2CamFrameMotion[0] = (v4Motion[0] - v4Cam[0] * v4Motion[2] * dOneOverCameraZ) * dOneOverCameraZ;
277  v2CamFrameMotion[1] = (v4Motion[1] - v4Cam[1] * v4Motion[2] * dOneOverCameraZ) * dOneOverCameraZ;
278  meas.m26A.T()[m] = meas.dSqrtInvNoise * m2CamDerivs * v2CamFrameMotion;
279  };
280  }
281 
282  // Calculate B: (the proj derivs WRT the point)
283  for(int m=0;m<3;m++)
284  {
285  const Vector<3> v3Motion = cam.se3CfW.get_rotation().get_matrix().T()[m];
286  Vector<2> v2CamFrameMotion;
287  v2CamFrameMotion[0] = (v3Motion[0] - v4Cam[0] * v3Motion[2] * dOneOverCameraZ) * dOneOverCameraZ;
288  v2CamFrameMotion[1] = (v3Motion[1] - v4Cam[1] * v3Motion[2] * dOneOverCameraZ) * dOneOverCameraZ;
289  meas.m23B.T()[m] = meas.dSqrtInvNoise * m2CamDerivs * v2CamFrameMotion;
290  };
291 
292  // Update the accumulators
293  if(!cam.bFixed)
294  {
295  // cam.m6U += meas.m26A.T() * meas.m26A; // SLOW SLOW this matrix is symmetric
297  cam.v6EpsilonA += meas.m26A.T() * meas.v2Epsilon;
298  // NOISE COVAR OMITTED because it's the 2-Identity
299  }
300 
301  // point.m3V += meas.m23B.T() * meas.m23B; // SLOW-ish this is symmetric too
302  BundleTriangle_UpdateM3V_LL(point.m3V, meas.m23B);
303  point.v3EpsilonB += meas.m23B.T() * meas.v2Epsilon;
304 
305  if(cam.bFixed)
306  meas.m63W = Zeros;
307  else
308  meas.m63W = meas.m26A.T() * meas.m23B;
309  }
310 
311  // OK, done (i) and most of (ii) except calcing Yij; this depends on Vi, which should
312  // be finished now. So we can find V*i (by adding lambda) and then invert.
313  // The next bits depend on mdLambda! So loop this next bit until error goes down.
314  double dNewError = dCurrentError + 9999;
315  while(dNewError > dCurrentError && !mbConverged && !mbHitMaxIterations && !*pbAbortSignal)
316  {
317  // Rest of part (ii) : find V*i inverse
318  for(vector<ExtendedMapPoint>::iterator itr = mvPoints.begin(); itr!=mvPoints.end(); itr++)
319  {
320  ExtendedMapPoint &point = *itr;
321  Matrix<3> m3VStar = point.m3V;
322  if(m3VStar[0][0] * m3VStar[1][1] * m3VStar[2][2] == 0)
323  point.m3VStarInv = Zeros;
324  else
325  {
326  // Fill in the upper-r triangle from the LL;
327  m3VStar[0][1] = m3VStar[1][0];
328  m3VStar[0][2] = m3VStar[2][0];
329  m3VStar[1][2] = m3VStar[2][1];
330 
331  for(int i=0; i<3; i++)
332  m3VStar[i][i] *= (1.0 + mdLambda);
333  Cholesky<3> chol(m3VStar);
334  point.m3VStarInv = chol.get_inverse();
335  };
336  }
337 
338  // Done part (ii), except calculating Yij;
339  // But we can do this inline when we calculate S in part (iii).
340 
341  // Part (iii): Construct the the big block-matrix S which will be inverted.
343  mS = Zeros;
344  Vector<> vE(mnCamsToUpdate * 6);
345  vE = Zeros;
346 
347  Matrix<6> m6; // Temp working space
348  Vector<6> v6; // Temp working space
349 
350  // Calculate on-diagonal blocks of S (i.e. only one camera at a time:)
351  for(unsigned int j=0; j<mvCameras.size(); j++)
352  {
353  Camera &cam_j = mvCameras[j];
354  if(cam_j.bFixed) continue;
355  int nCamJStartRow = cam_j.nStartRow;
356 
357  // First, do the diagonal elements.
358  //m6= cam_j.m6U; // can't do this anymore because cam_j.m6U is LL!!
359  for(int r=0; r<6; r++)
360  {
361  for(int c=0; c<r; c++)
362  m6[r][c] = m6[c][r] = cam_j.m6U[r][c];
363  m6[r][r] = cam_j.m6U[r][r];
364  };
365 
366  for(int nn = 0; nn< 6; nn++)
367  m6[nn][nn] *= (1.0 + mdLambda);
368 
369  v6 = cam_j.v6EpsilonA;
370 
371  vector<Meas*> &vMeasLUTj = mvMeasLUTs[j];
372  // Sum over measurements (points):
373  for(unsigned int i=0; i<mvPoints.size(); i++)
374  {
375  Meas* pMeas = vMeasLUTj[i];
376  if(pMeas == NULL || pMeas->bBad)
377  continue;
378  m6 -= pMeas->m63W * mvPoints[i].m3VStarInv * pMeas->m63W.T(); // SLOW SLOW should by 6x6sy
379  v6 -= pMeas->m63W * (mvPoints[i].m3VStarInv * mvPoints[i].v3EpsilonB);
380  }
381  mS.slice(nCamJStartRow, nCamJStartRow, 6, 6) = m6;
382  vE.slice(nCamJStartRow,6) = v6;
383  }
384 
385  // Now find off-diag elements of S. These are camera-point-camera combinations, of which there are lots.
386  // New code which doesn't waste as much time finding i-jk pairs; these are pre-stored in a per-i list.
387  for(unsigned int i=0; i<mvPoints.size(); i++)
388  {
389  ExtendedMapPoint &p = mvPoints[i];
390  int nCurrentJ = -1;
391  int nJRow = -1;
392  Meas* pMeas_ij;
393  Meas* pMeas_ik;
394  Matrix<6,3> m63_MIJW_times_m3VStarInv;
395 
396  for(vector<OffDiagScriptEntry>::iterator it=p.vOffDiagonalScript.begin();
397  it!=p.vOffDiagonalScript.end();
398  it++)
399  {
400  OffDiagScriptEntry &e = *it;
401  pMeas_ik = mvMeasLUTs[e.k][i];
402  if(pMeas_ik == NULL || pMeas_ik->bBad)
403  continue;
404  if(e.j != nCurrentJ)
405  {
406  pMeas_ij = mvMeasLUTs[e.j][i];
407  if(pMeas_ij == NULL || pMeas_ij->bBad)
408  continue;
409  nCurrentJ = e.j;
410  nJRow = mvCameras[e.j].nStartRow;
411  m63_MIJW_times_m3VStarInv = pMeas_ij->m63W * p.m3VStarInv;
412  }
413  int nKRow = mvCameras[pMeas_ik->c].nStartRow;
414 #ifndef WIN32
415  mS.slice(nJRow, nKRow, 6, 6) -= m63_MIJW_times_m3VStarInv * pMeas_ik->m63W.T();
416 #else
417  Matrix<6> m = mS.slice(nJRow, nKRow, 6, 6);
418  m -= m63_MIJW_times_m3VStarInv * pMeas_ik->m63W.T();
419  mS.slice(nJRow, nKRow, 6, 6) = m;
420 #endif
421  assert(nKRow < nJRow);
422  }
423  }
424 
425  // Did this purely LL triangle - now update the TR bit as well!
426  // (This is actually unneccessary since the lapack cholesky solver
427  // uses only one triangle, but I'm leaving it in here anyway.)
428  for(int i=0; i<mS.num_rows(); i++)
429  for(int j=0; j<i; j++)
430  mS[j][i] = mS[i][j];
431 
432  // Got fat matrix S and vector E from part(iii). Now Cholesky-decompose
433  // the matrix, and find the camera update vector.
434  Vector<> vCamerasUpdate(mS.num_rows());
435  vCamerasUpdate = Cholesky<>(mS).backsub(vE);
436 
437  // Part (iv): Compute the map updates
438  Vector<> vMapUpdates(mvPoints.size() * 3);
439  for(unsigned int i=0; i<mvPoints.size(); i++)
440  {
441  Vector<3> v3Sum;
442  v3Sum = Zeros;
443  for(unsigned int j=0; j<mvCameras.size(); j++)
444  {
445  Camera &cam = mvCameras[j];
446  if(cam.bFixed)
447  continue;
448  Meas *pMeas = mvMeasLUTs[j][i];
449  if(pMeas == NULL || pMeas->bBad)
450  continue;
451  v3Sum+=pMeas->m63W.T() * vCamerasUpdate.slice(cam.nStartRow,6);
452  }
453  Vector<3> v3 = mvPoints[i].v3EpsilonB - v3Sum;
454  vMapUpdates.slice(i * 3, 3) = mvPoints[i].m3VStarInv * v3;
455 // if(isnan(vMapUpdates.slice(i * 3, 3) * vMapUpdates.slice(i * 3, 3)))
456 // {
457 // cerr << "NANNERY! " << endl;
458 // cerr << mvPoints[i].m3VStarInv << endl;
459 // };
460  }
461 
462  // OK, got the two update vectors.
463  // First check for convergence..
464  // (this is a very poor convergence test)
465  double dSumSquaredUpdate = vCamerasUpdate * vCamerasUpdate + vMapUpdates * vMapUpdates;
466  LOGV(LOG_TAG, "Info: dSumSquaredUpdate: %g lastMdSigmaSquared: %g, difference: %g", dSumSquaredUpdate, *lastMdSigmaSquared, dSumSquaredUpdate - (*lastMdSigmaSquared));
467  *lastMdSigmaSquared = dSumSquaredUpdate;
468 
469  if(dSumSquaredUpdate < mgvdUpdateConvergenceLimit)
470  mbConverged = true;
471 
472  // Now re-project everything and measure the error;
473  // NB we don't keep these projections, SLOW, bit of a waste.
474 
475  // Temp versions of updated pose and pos:
476  for(unsigned int j=0; j<mvCameras.size(); j++)
477  {
478  if(mvCameras[j].bFixed)
479  mvCameras[j].se3CfWNew = mvCameras[j].se3CfW;
480  else
481  mvCameras[j].se3CfWNew = SE3<>::exp(vCamerasUpdate.slice(mvCameras[j].nStartRow, 6)) * mvCameras[j].se3CfW;
482  }
483  for(unsigned int i=0; i<mvPoints.size(); i++)
484  mvPoints[i].v3PosNew = mvPoints[i].v3Pos + vMapUpdates.slice(i*3, 3);
485  // Calculate new error by re-projecting, doing tukey, etc etc:
486  dNewError = FindNewError<MEstimator>();
487 
488  cout <<setprecision(1) << "L" << mdLambda << setprecision(3) << "\tOld " << dCurrentError << " New " << dNewError << " Diff " << dCurrentError - dNewError << "\t";
489 
490  // Was the step good? If not, modify lambda and try again!!
491  // (if it was good, will break from this loop.)
492  if(dNewError > dCurrentError)
493  {
494  cout << " TRY AGAIN " << endl;
495  LOGV(LOG_TAG, "Info: Try Again");
497  };
498 
499  mnCounter++;
501  mbHitMaxIterations = true;
502  } // End of while error too big loop
503 
504  if(dNewError < dCurrentError) // Was the last step a good one?
505  {
506  cout << " WINNER ------------ " << endl;
507  // Woo! got somewhere. Update lambda and make changes permanent.
509  for(unsigned int j=0; j<mvCameras.size(); j++)
510  mvCameras[j].se3CfW = mvCameras[j].se3CfWNew;
511  for(unsigned int i=0; i<mvPoints.size(); i++)
512  mvPoints[i].v3Pos = mvPoints[i].v3PosNew;
513  mnAccepted++;
514  }
515 
516  // Finally, ditch all the outliers.
517  vector<list<Meas>::iterator> vit;
518  for(list<Meas>::iterator itr = mMeasList.begin(); itr!=mMeasList.end(); itr++)
519  if(itr->bBad)
520  {
521  vit.push_back(itr);
522  mvOutlierMeasurementIdx.push_back(make_pair(itr->p, itr->c));
523  mvPoints[itr->p].nOutliers++;
524  mvMeasLUTs[itr->c][itr->p] = NULL;
525  };
526 
527  for(unsigned int i=0; i<vit.size(); i++)
528  mMeasList.erase(vit[i]);
529 
530  cout << "Nuked " << vit.size() << " measurements." << endl;
531  return true;
532 }
533 
534 // Find the new total error if cameras and points used their
535 // new coordinates
536 template<class MEstimator>
538 {
539  ofstream ofs;
540  double dNewError = 0;
541  vector<double> vdErrorSquared;
542  for(list<Meas>::iterator itr = mMeasList.begin(); itr!=mMeasList.end(); itr++)
543  {
544  Meas &meas = *itr;
545  // Project the point.
546  Vector<3> v3Cam = mvCameras[meas.c].se3CfWNew * mvPoints[meas.p].v3PosNew;
547  if(v3Cam[2] <= 0)
548  {
549  dNewError += 1.0;
550  cout << ".";
551  continue;
552  };
553  Vector<2> v2ImPlane = project(v3Cam);
554  Vector<2> v2Image = mCamera.Project(v2ImPlane);
555  Vector<2> v2Error = meas.dSqrtInvNoise * (meas.v2Found - v2Image);
556  double dErrorSquared = v2Error * v2Error;
557  dNewError += MEstimator::ObjectiveScore(dErrorSquared, mdSigmaSquared);
558  }
559  return dNewError;
560 }
561 
562 // Optimisation: make a bunch of tables, one per camera
563 // which point to measurements (if any) for each point
564 // This is faster than a std::map lookup.
566 {
567  mvMeasLUTs.clear();
568  for(unsigned int nCam = 0; nCam < mvCameras.size(); nCam++)
569  {
570  mvMeasLUTs.push_back(vector<Meas*>());
571  mvMeasLUTs.back().resize(mvPoints.size(), NULL);
572  };
573  for(list<Meas>::iterator it = mMeasList.begin(); it!=mMeasList.end(); it++)
574  mvMeasLUTs[it->c][it->p] = &(*it);
575 }
576 
577 // Optimisation: make a per-point list of all
578 // observation camera-camera pairs; this is then
579 // scanned to make the off-diagonal elements of matrix S
581 {
582  for(unsigned int i=0; i<mvPoints.size(); i++)
583  {
584  ExtendedMapPoint &p = mvPoints[i];
585  p.vOffDiagonalScript.clear();
586  for(set<int>::iterator it_j = p.sCameras.begin(); it_j!=p.sCameras.end(); it_j++)
587  {
588  int j = *it_j;
589  if(mvCameras[j].bFixed)
590  continue;
591  Meas *pMeas_j = mvMeasLUTs[j][i];
592  assert(pMeas_j != NULL);
593 
594  for(set<int>::iterator it_k = p.sCameras.begin(); it_k!=it_j; it_k++)
595  {
596  int k = *it_k;
597  if(mvCameras[k].bFixed)
598  continue;
599 
600  Meas *pMeas_k = mvMeasLUTs[k][i];
601  assert(pMeas_k != NULL);
602 
604  e.j = j;
605  e.k = k;
606  p.vOffDiagonalScript.push_back(e);
607  }
608  }
609  }
610 }
611 
613 {
614  mdLambdaFactor = 2.0;
615  mdLambda *= 0.3;
616 };
617 
619 {
621  mdLambdaFactor = mdLambdaFactor * 2;
622 };
623 
624 
626 {
627  return mvPoints.at(n).v3Pos;
628 }
629 
631 {
632  return mvCameras.at(n).se3CfW;
633 }
634 
636 {
637  set<int> sOutliers;
638  set<int>::iterator hint = sOutliers.begin();
639  for(unsigned int i=0; i<mvPoints.size(); i++)
640  {
641  ExtendedMapPoint &p = mvPoints[i];
642  if(p.nMeasurements > 0 && p.nMeasurements == p.nOutliers)
643  hint = sOutliers.insert(hint, i);
644  }
645  return sOutliers;
646 };
647 
648 
649 vector<pair<int, int> > Bundle::GetOutlierMeasurements()
650 {
652 }
653 
654 
655 
656 
657 
658 
659 
660 
661 
double mdLambda
Definition: Bundle.h:141
int mnCounter
Definition: Bundle.h:145
Matrix< 2, 3 > m23B
Definition: Bundle.h:93
void ModifyLambda_GoodStep()
Definition: Bundle.cpp:612
std::set< int > sCameras
Definition: Bundle.h:70
int c
Definition: Bundle.h:83
int AddPoint(Vector< 3 > v3Pos)
Definition: Bundle.cpp:65
#define LOGV(LOG_TAG,...)
Definition: globals.h:10
#define LOG_TAG
Definition: globals.h:9
int Compute(bool *pbAbortSignal)
Definition: Bundle.cpp:114
SE3 se3CfW
Definition: Bundle.h:43
SO3< Precision > & get_rotation()
Returns the rotation part of the transformation as a SO3.
Definition: se3.h:64
int mgvnBundleCout
Definition: Bundle.h:150
Vector< 2 > Project(const Vector< 2 > &camframe)
Definition: ATANCamera.cpp:109
Matrix< 3 > m3V
Definition: Bundle.h:64
Matrix< 6, 3 > m63W
Definition: Bundle.h:94
Vector< 2 > v2Epsilon
Definition: Bundle.h:91
double mgvdUpdateConvergenceLimit
Definition: Bundle.h:149
const std::string BundleMEstimator
Definition: globals.h:26
bool mbHitMaxIterations
Definition: Bundle.h:144
bool bFixed
Definition: Bundle.h:42
Definition: Bundle.h:76
void ProjectAndFindSquaredError(Meas &meas)
Definition: Bundle.cpp:166
int mnStartRow
Definition: Bundle.h:139
Vector<(Size==Dynamic?Dynamic:Size+1), Precision > unproject(const Vector< Size, Precision, Base > &v)
Definition: helpers.h:166
bool mbConverged
Definition: Bundle.h:143
Vector< 3 > v3Cam
Definition: Bundle.h:99
bool Do_LM_Step(bool *pbAbortSignal, double *lastMdSigmaSquared)
Definition: Bundle.cpp:187
double mdSigmaSquared
Definition: Bundle.h:140
Matrix< Size, Size, Precision > get_inverse()
Definition: Cholesky.h:196
int AddCamera(SE3<> se3CamFromWorld, bool bFixed)
Definition: Bundle.cpp:45
double mdLambdaFactor
Definition: Bundle.h:142
Matrix< 6 > m6U
Definition: Bundle.h:45
double dErrorSquared
Definition: Bundle.h:100
Vector< 2 > v2Found
Definition: Bundle.h:90
void GenerateOffDiagScripts()
Definition: Bundle.cpp:580
double FindNewError()
Definition: Bundle.cpp:537
std::list< Meas > mMeasList
Definition: Bundle.h:133
void AddMeas(int nCam, int nPoint, Vector< 2 > v2Pos, double dSigmaSquared)
Definition: Bundle.cpp:80
Definition: se3.h:50
bool * mpbAbortSignal
Definition: Bundle.h:152
Bundle(const ATANCamera &TCam)
Definition: Bundle.cpp:34
int p
Definition: Bundle.h:82
Matrix< R, C, P > exp(const Matrix< R, C, P, B > &m)
Definition: helpers.h:284
Matrix< 2, 6 > m26A
Definition: Bundle.h:92
std::vector< Camera > mvCameras
Definition: Bundle.h:132
int nMeasurements
Definition: Bundle.h:68
const double BundleMinTukeySigma
Definition: globals.h:27
bool bBad
Definition: Bundle.h:88
ATANCamera mCamera
Definition: Bundle.h:137
Vector< 6 > v6EpsilonA
Definition: Bundle.h:46
int mnAccepted
Definition: Bundle.h:146
Vector< 3 > v3Pos
Definition: Bundle.h:62
void ModifyLambda_BadStep()
Definition: Bundle.cpp:618
std::set< int > GetOutliers()
Definition: Bundle.cpp:635
const double BundleUpdateSquaredConvergenceLimit
Definition: globals.h:22
SE3 GetCamera(int n)
Definition: Bundle.cpp:630
std::vector< OffDiagScriptEntry > vOffDiagonalScript
Definition: Bundle.h:71
void ClearAccumulators()
Definition: Bundle.cpp:95
Matrix< 2 > m2CamDerivs
Definition: Bundle.h:101
void BundleTriangle_UpdateM3V_LL(Matrix< 3 > &m3V, Matrix< 2, 3 > &m23B)
Definition: Bundle.cpp:26
Vector< 3 > GetPoint(int n)
Definition: Bundle.cpp:625
int nStartRow
Definition: Bundle.h:47
Matrix< 3 > m3VStarInv
Definition: Bundle.h:66
void GenerateMeasLUTs()
Definition: Bundle.cpp:565
double dSqrtInvNoise
Definition: Bundle.h:96
int mgvnMaxIterations
Definition: Bundle.h:148
std::vector< ExtendedMapPoint > mvPoints
Definition: Bundle.h:131
const int BundleCout
Definition: globals.h:23
std::vector< std::pair< int, int > > mvOutlierMeasurementIdx
Definition: Bundle.h:134
int mnCamsToUpdate
Definition: Bundle.h:138
Matrix< 2, 2 > GetProjectionDerivs()
Definition: ATANCamera.cpp:172
std::vector< std::vector< Meas * > > mvMeasLUTs
Definition: Bundle.h:135
static Operator< Internal::Zero > Zeros
Definition: objects.h:727
Vector<(Size==Dynamic?Dynamic:Size-1), Precision > project(const Vector< Size, Precision, Base > &v)
Definition: helpers.h:157
bool isnan(const Vector< S, P, B > &v)
Definition: helpers.h:308
void BundleTriangle_UpdateM6U_LL(Matrix< 6 > &m6U, Matrix< 2, 6 > &m26A)
Definition: Bundle.cpp:20
#define cout
Definition: Bundle.cpp:16
Definition: Bundle.h:40
std::vector< std::pair< int, int > > GetOutlierMeasurements()
Definition: Bundle.cpp:649
const int BundleMaxIterations
Definition: globals.h:21
Vector< 3 > v3EpsilonB
Definition: Bundle.h:65