⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 bundle.cc

📁 this is software for visual SLAM
💻 CC
📖 第 1 页 / 共 2 页
字号:
// Copyright 2008 Isis Innovation Limited#include "Bundle.h"#include "LapackCholesky.h"#include "MEstimator.h"#include <TooN/helpers.h>#include <TooN/Cholesky.h>#include <fstream>#include <gvars3/instances.h>using namespace GVars3;using namespace std;#ifdef WIN32inline bool isnan(double d) {return !(d==d);}#endif#define cout if(*mgvnBundleCout) cout// Some inlines which replace standard matrix multiplications // with LL-triangle-only versions.inline void BundleTriangle_UpdateM6U_LL(Matrix<6> &m6U, Matrix<2,6> &m26A){  for(int r=0; r<6; r++)    for(int c=0; c<=r; c++)      m6U(r,c)+= m26A.T()(r,0)*m26A(0,c) + m26A.T()(r,1)*m26A(1,c);}inline void BundleTriangle_UpdateM3V_LL(Matrix<3> &m3V, Matrix<2,3> &m23B){  for(int r=0; r<3; r++)     for(int c=0; c<=r; c++)       m3V(r,c)+= m23B.T()(r,0)*m23B(0,c) + m23B.T()(r,1)*m23B(1,c); }// Constructor copies MapMaker's camera parametersBundle::Bundle(const ATANCamera &TCam)  : mCamera(TCam){  mnCamsToUpdate = 0;  mnStartRow = 0;  GV3::Register(mgvnMaxIterations, "Bundle.MaxIterations", 20,  SILENT);  GV3::Register(mgvdUpdateConvergenceLimit, "Bundle.UpdateSquaredConvergenceLimit", 1e-06, SILENT);  GV3::Register(mgvnBundleCout, "Bundle.Cout", 0, SILENT);};// Add a camera to the system, return value is the bundle adjuster's ID for the cameraint Bundle::AddCamera(SE3 se3CamFromWorld, bool bFixed){  int n = mvCameras.size();  Camera c;  c.bFixed = bFixed;  c.se3CfW = se3CamFromWorld;  Zero(c.m6U);  Zero(c.v6EpsilonA);  if(!bFixed)    {      c.nStartRow = mnStartRow;      mnStartRow += 6;      mnCamsToUpdate++;    }  else    c.nStartRow = -999999999;   mvCameras.push_back(c);     return n;}// Add a map point to the system, return value is the bundle adjuster's ID for the pointint Bundle::AddPoint(Vector<3> v3Pos){  int n = mvPoints.size();  Point p;  if(isnan(v3Pos * v3Pos))    {      cerr << " You sucker, tried to give me a nan " << v3Pos << endl;      Zero(v3Pos);    }  p.v3Pos = v3Pos;  Zero(p.m3V);  Zero(p.v3EpsilonB);  mvPoints.push_back(p);  return n;}// Add a measurement of one point with one cameravoid Bundle::AddMeas(int nCam, int nPoint, Vector<2> v2Pos, double dSigmaSquared){  assert(nCam < (int) mvCameras.size());  assert(nPoint < (int) mvPoints.size());  mvPoints[nPoint].nMeasurements++;  mvPoints[nPoint].sCameras.insert(nCam);  Meas m;  m.p = nPoint;  m.c = nCam;  m.v2Found = v2Pos;  m.dSqrtInvNoise = sqrt(1.0 / dSigmaSquared);  mMeasList.push_back(m);}// Perform bundle adjustment. The parameter points to a signal bool // which mapmaker will set to high if another keyframe is incoming// and bundle adjustment needs to be aborted.// Returns number of accepted iterations if all good, negative // value for big error.int Bundle::Compute(bool *pbAbortSignal){  mpbAbortSignal = pbAbortSignal;  // Some speedup data structures  GenerateMeasLUTs();  GenerateOffDiagScripts();  // Initially behave like gauss-newton  mdLambda = 0.0001;  mdLambdaFactor = 2.0;  mbConverged = false;  mbHitMaxIterations = false;  mnCounter = 0;  mnAccepted = 0;    // What MEstimator are we using today?  static gvar3<string> gvsMEstimator("BundleMEstimator", "Tukey", SILENT);    while(!mbConverged  && !mbHitMaxIterations && !*pbAbortSignal)    {      bool bNoError;      if(*gvsMEstimator == "Cauchy")	bNoError = Do_LM_Step<Cauchy>(pbAbortSignal);        else if(*gvsMEstimator == "Tukey")	bNoError = Do_LM_Step<Tukey>(pbAbortSignal);      else if(*gvsMEstimator == "Huber")	bNoError = Do_LM_Step<Huber>(pbAbortSignal);      else	{	  cout << "Invalid BundleMEstimator selected !! " << endl;	  cout << "Defaulting to Tukey." << endl;	  *gvsMEstimator = "Tukey";	  bNoError = Do_LM_Step<Tukey>(pbAbortSignal);	};            if(!bNoError)	return -1;    }    if(mbHitMaxIterations)    cout << "  Hit max iterations." << endl;  cout << "Final Sigma Squared: " << mdSigmaSquared << " (= " << sqrt(mdSigmaSquared) / 4.685 << " pixels.)" << endl;  return mnAccepted;};// Reproject a single measurement, find errorinline void Bundle::ProjectAndFindSquaredError(Meas &meas){  Camera &cam = mvCameras[meas.c];  Point &point = mvPoints[meas.p];    // Project the point.  meas.v3Cam = cam.se3CfW * point.v3Pos;  if(meas.v3Cam[2] <= 0)    {      meas.bBad = true;      return;    }  meas.bBad = false;  Vector<2> v2ImPlane = project(meas.v3Cam);  Vector<2> v2Image   = mCamera.Project(v2ImPlane);  meas.m2CamDerivs = mCamera.GetProjectionDerivs();  meas.v2Epsilon = meas.dSqrtInvNoise * (meas.v2Found - v2Image);  meas.dErrorSquared = meas.v2Epsilon * meas.v2Epsilon;}template<class MEstimator>bool Bundle::Do_LM_Step(bool *pbAbortSignal){  //  Do a LM step according to Hartley and Zisserman Algo A6.4 in MVG 2nd Edition  //  Actual work starts a bit further down - first we have to work out the   //  projections and errors for each point, so we can do tukey reweighting  vector<double> vdErrorSquared;  for(list<Meas>::iterator itr = mMeasList.begin(); itr!=mMeasList.end(); itr++)    {      Meas &meas = *itr;      ProjectAndFindSquaredError(meas);      if(!meas.bBad)	vdErrorSquared.push_back(meas.dErrorSquared);    };    // Projected all points and got vector of errors; find the median,   // And work out robust estimate of sigma, then scale this for the tukey  // estimator  mdSigmaSquared = MEstimator::FindSigmaSquared(vdErrorSquared);    //  OK - good to go! weights can now be calced on second run through the loop.  //  Back to Hartley and Zisserman....  //  `` (i) Compute the derivative matrices Aij = [dxij/daj]  //      and Bij = [dxij/dbi] and the error vectors eij''  //  //  Here we do this by looping over all measurements  //   //  While we're here, might as well update the accumulators U, ea, B, eb  //  from part (ii) as well, and let's calculate Wij while we're here as well.    double dCurrentError = 0.0;  for(list<Meas>::iterator itr = mMeasList.begin(); itr!=mMeasList.end(); itr++)    {      Meas &meas = *itr;      Camera &cam = mvCameras[meas.c];      Point &point = mvPoints[meas.p];            // Project the point.      // We've done this before - results are still cached in meas.      if(meas.bBad)	{	  dCurrentError += 1.0;	  continue;	};            // What to do with the weights? The easiest option is to independently weight      // The two jacobians, A and B, with sqrt of the tukey weight w;      // And also weight the error vector v2Epsilon.      // That makes everything else automatic.      // Calc the square root of the tukey weight:      double dWeight= MEstimator::SquareRootWeight(meas.dErrorSquared, mdSigmaSquared);      // Re-weight error:      meas.v2Epsilon = dWeight * meas.v2Epsilon;            if(dWeight == 0)	{	  meas.bBad = true;  	  dCurrentError += 1.0;	  continue;	}            dCurrentError += MEstimator::ObjectiveScore(meas.dErrorSquared, mdSigmaSquared);            // To re-weight the jacobians, I'll just re-weight the camera param matrix      // This is only used for the jacs and will save a few fmuls      Matrix<2> m2CamDerivs = dWeight * meas.m2CamDerivs;            const double dOneOverCameraZ = 1.0 / meas.v3Cam[2];      const Vector<4> v4Cam = unproject(meas.v3Cam);            // Calculate A: (the proj derivs WRT the camera)      if(cam.bFixed)	Zero(meas.m26A);      else 	{	  for(int m=0;m<6;m++)	    {	      const Vector<4> v4Motion = SE3::generator_field(m, v4Cam); 	      Vector<2> v2CamFrameMotion; 	      v2CamFrameMotion[0] = (v4Motion[0] - v4Cam[0] * v4Motion[2] * dOneOverCameraZ) * dOneOverCameraZ; 	      v2CamFrameMotion[1] = (v4Motion[1] - v4Cam[1] * v4Motion[2] * dOneOverCameraZ) * dOneOverCameraZ; 	      meas.m26A.T()[m] = meas.dSqrtInvNoise * m2CamDerivs * v2CamFrameMotion;	    };	}            // Calculate B: (the proj derivs WRT the point)      for(int m=0;m<3;m++)	{	  const Vector<3> v3Motion = cam.se3CfW.get_rotation().get_matrix().T()[m];	  Vector<2> v2CamFrameMotion;	  v2CamFrameMotion[0] = (v3Motion[0] - v4Cam[0] * v3Motion[2] * dOneOverCameraZ) * dOneOverCameraZ;	  v2CamFrameMotion[1] = (v3Motion[1] - v4Cam[1] * v3Motion[2] * dOneOverCameraZ) * dOneOverCameraZ;	  meas.m23B.T()[m] = meas.dSqrtInvNoise * m2CamDerivs * v2CamFrameMotion;	};            // Update the accumulators      if(!cam.bFixed)	{	  //	  cam.m6U += meas.m26A.T() * meas.m26A; 	  // SLOW SLOW this matrix is symmetric	  BundleTriangle_UpdateM6U_LL(cam.m6U, meas.m26A);	  cam.v6EpsilonA += meas.m26A.T() * meas.v2Epsilon;	  // NOISE COVAR OMITTED because it's the 2-Identity	}            //            point.m3V += meas.m23B.T() * meas.m23B;             // SLOW-ish this is symmetric too      BundleTriangle_UpdateM3V_LL(point.m3V, meas.m23B);      point.v3EpsilonB += meas.m23B.T() * meas.v2Epsilon;            if(cam.bFixed)	Zero(meas.m63W);      else	meas.m63W = meas.m26A.T() * meas.m23B;    }    // OK, done (i) and most of (ii) except calcing Yij; this depends on Vi, which should   // be finished now. So we can find V*i (by adding lambda) and then invert.  // The next bits depend on mdLambda! So loop this next bit until error goes down.  double dNewError = dCurrentError + 9999;  while(dNewError > dCurrentError && !mbConverged && !mbHitMaxIterations && !*pbAbortSignal)    {      // Rest of part (ii) : find V*i inverse      for(vector<Point>::iterator itr = mvPoints.begin(); itr!=mvPoints.end(); itr++)	{	  Point &point = *itr;	  Matrix<3> m3VStar = point.m3V;	  if(m3VStar[0][0] * m3VStar[1][1] * m3VStar[2][2] == 0)	    Zero(point.m3VStarInv);	  else	    {	      // Fill in the upper-r triangle from the LL;	      m3VStar[0][1] = m3VStar[1][0];	      m3VStar[0][2] = m3VStar[2][0];	      m3VStar[1][2] = m3VStar[2][1];	       	      for(int i=0; i<3; i++)		m3VStar[i][i] *= (1.0 + mdLambda);	      Cholesky<3> chol(m3VStar);	      point.m3VStarInv = chol.get_inverse();	    };	}      // Done part (ii), except calculating Yij;      // But we can do this inline when we calculate S in part (iii).            // Part (iii): Construct the the big block-matrix S which will be inverted.      Matrix<> mS(mnCamsToUpdate * 6, mnCamsToUpdate * 6);      Zero(mS);      Vector<> vE(mnCamsToUpdate * 6);      Zero(vE);

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -