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

📄 tracker.cc

📁 this is software for visual SLAM
💻 CC
📖 第 1 页 / 共 3 页
字号:
// Copyright 2008 Isis Innovation Limited#include "OpenGL.h"#include "Tracker.h"#include "MEstimator.h"#include "ShiTomasi.h"#include "SmallMatrixOpts.h"#include "PatchFinder.h"#include "TrackerData.h"#include <cvd/utility.h>#include <cvd/gl_helpers.h>#include <cvd/fast_corner.h>#include <cvd/vision.h>#include <TooN/wls_cholesky.h>#include <gvars3/instances.h>#include <gvars3/GStringUtil.h>#include <fstream>#include <fcntl.h>using namespace CVD;using namespace std;using namespace GVars3;// The constructor mostly sets up interal reference variables// to the other classes..Tracker::Tracker(ImageRef irVideoSize, const ATANCamera &c, Map &m, MapMaker &mm) :   mMap(m),  mMapMaker(mm),  mCamera(c),  mRelocaliser(mMap, mCamera),  mirSize(irVideoSize){  mCurrentKF.bFixed = false;  GUI.RegisterCommand("Reset", GUICommandCallBack, this);  GUI.RegisterCommand("KeyPress", GUICommandCallBack, this);  GUI.RegisterCommand("PokeTracker", GUICommandCallBack, this);  TrackerData::irImageSize = mirSize;    // Most of the initialisation is done in Reset()  Reset();}// Resets the tracker, wipes the map.// This is the main Reset-handler-entry-point of the program! Other classes' resets propagate from here.// It's always called in the Tracker's thread, often as a GUI command.void Tracker::Reset(){  mbDidCoarse = false;  mbUserPressedSpacebar = false;  mTrackingQuality = GOOD;  mnLostFrames = 0;  mdMSDScaledVelocityMagnitude = 0;  mCurrentKF.dSceneDepthMean = 1.0;  mCurrentKF.dSceneDepthSigma = 1.0;  mnInitialStage = TRAIL_TRACKING_NOT_STARTED;  mlTrails.clear();  mCamera.SetImageSize(mirSize);  mCurrentKF.mMeasurements.clear();  mnLastKeyFrameDropped = -20;  mnFrame=0;  Zero(mv6CameraVelocity);  mbJustRecoveredSoUseCoarse = false;    // Tell the MapMaker to reset itself..   // this may take some time, since the mapmaker thread may have to wait  // for an abort-check during calculation, so sleep while waiting.  // MapMaker will also clear the map.  mMapMaker.RequestReset();  while(!mMapMaker.ResetDone())#ifndef WIN32	  usleep(10);#else	  Sleep(1);#endif}// TrackFrame is called by System.cc with each incoming video frame.// It figures out what state the tracker is in, and calls appropriate internal tracking// functions. bDraw tells the tracker wether it should output any GL graphics// or not (it should not draw, for example, when AR stuff is being shown.)void Tracker::TrackFrame(Image<byte> &imFrame, bool bDraw){  mbDraw = bDraw;  mMessageForUser.str("");   // Wipe the user message clean    // Take the input video image, and convert it into the tracker's keyframe struct  mCurrentKF.mMeasurements.clear();  mCurrentKF.MakeKeyFrame_Lite(imFrame);  // From now on we only use the keyframe struct!    mnFrame++;    if(mbDraw)    {      glDrawPixels(mCurrentKF.aLevels[0].im);      if(GV2.GetInt("Tracker.DrawFASTCorners",0, SILENT))	{	  glColor3f(1,0,1);  glPointSize(1); glBegin(GL_POINTS);	  for(unsigned int i=0; i<mCurrentKF.aLevels[0].vCorners.size(); i++) 	    glVertex(mCurrentKF.aLevels[0].vCorners[i]);	  glEnd();	}    }    // Decide what to do - if there is a map, try to track the map ...  if(mMap.IsGood())    {      if(mnLostFrames < 3)  // .. but only if we're not lost!	{	  ApplyMotionModel();       // 	  TrackMap();               //  These three lines do the main tracking work.	  UpdateMotionModel();      // 	  	  AssessTrackingQuality();  //  Check if we're lost or if tracking is poor.	  	  { // Provide some feedback for the user:	    mMessageForUser << "Tracking Map, quality ";	    if(mTrackingQuality == GOOD)  mMessageForUser << "good.";	    if(mTrackingQuality == DODGY) mMessageForUser << "poor.";	    if(mTrackingQuality == BAD)   mMessageForUser << "bad.";	    mMessageForUser << " Found:";	    for(int i=0; i<LEVELS; i++) mMessageForUser << " " << manMeasFound[i] << "/" << manMeasAttempted[i];	    //	    mMessageForUser << " Found " << mnMeasFound << " of " << mnMeasAttempted <<". (";	    mMessageForUser << " Map: " << mMap.vpPoints.size() << "P, " << mMap.vpKeyFrames.size() << "KF";	  }	  	  // Heuristics to check if a key-frame should be added to the map:	  if(mTrackingQuality == GOOD &&	     mMapMaker.NeedNewKeyFrame(mCurrentKF) &&	     mnFrame - mnLastKeyFrameDropped > 20  &&	     mMapMaker.QueueSize() < 3)	    {	      mMessageForUser << " Adding key-frame.";	      AddNewKeyFrame();	    };	}      else  // what if there is a map, but tracking has been lost?	{	  mMessageForUser << "** Attempting recovery **.";	  if(AttemptRecovery())	    {	      TrackMap();	      AssessTrackingQuality();	    }	}      if(mbDraw)	RenderGrid();    }   else // If there is no map, try to make one.    TrackForInitialMap();     // GUI interface  while(!mvQueuedCommands.empty())    {      GUICommandHandler(mvQueuedCommands.begin()->sCommand, mvQueuedCommands.begin()->sParams);      mvQueuedCommands.erase(mvQueuedCommands.begin());    }};// Try to relocalise in case tracking was lost.// Returns success or failure as a bool.// Actually, the SBI relocaliser will almost always return true, even if// it has no idea where it is, so graphics will go a bit // crazy when lost. Could use a tighter SSD threshold and return more false,// but the way it is now gives a snappier response and I prefer it.bool Tracker::AttemptRecovery(){  bool bRelocGood = mRelocaliser.AttemptRecovery(mCurrentKF);  if(!bRelocGood)    return false;    SE3 se3Best = mRelocaliser.BestPose();  mse3CamFromWorld = mse3StartPos = se3Best;  Zero(mv6CameraVelocity);  mbJustRecoveredSoUseCoarse = true;  return true;}// Draw the reference grid to give the user an idea of wether tracking is OK or not.void Tracker::RenderGrid(){  // The colour of the ref grid shows if the coarse stage of tracking was used  // (it's turned off when the camera is sitting still to reduce jitter.)  if(mbDidCoarse)    glColor4f(.0, 0.5, .0, 0.6);  else    glColor4f(0,0,0,0.6);    // The grid is projected manually, i.e. GL receives projected 2D coords to draw.  int nHalfCells = 8;  int nTot = nHalfCells * 2 + 1;  Image<Vector<2> >  imVertices(ImageRef(nTot,nTot));  for(int i=0; i<nTot; i++)    for(int j=0; j<nTot; j++)      {	Vector<3> v3;	v3[0] = (i - nHalfCells) * 0.1;	v3[1] = (j - nHalfCells) * 0.1;	v3[2] = 0.0;	Vector<3> v3Cam = mse3CamFromWorld * v3;	if(v3Cam[2] < 0.001)	  v3Cam[2] = 0.001;	imVertices[i][j] = mCamera.Project(project(v3Cam));      }  glEnable(GL_LINE_SMOOTH);  glEnable(GL_BLEND);  glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);  glLineWidth(2);  for(int i=0; i<nTot; i++)    {      glBegin(GL_LINE_STRIP);      for(int j=0; j<nTot; j++)	glVertex(imVertices[i][j]);      glEnd();            glBegin(GL_LINE_STRIP);      for(int j=0; j<nTot; j++)	glVertex(imVertices[j][i]);      glEnd();    };    glLineWidth(1);  glColor3f(1,0,0);}// GUI interface. Stuff commands onto the back of a queue so the tracker handles// them in its own thread at the end of each frame. Note the charming lack of// any thread safety (no lock on mvQueuedCommands).void Tracker::GUICommandCallBack(void* ptr, string sCommand, string sParams){  Command c;  c.sCommand = sCommand;  c.sParams = sParams;  ((Tracker*) ptr)->mvQueuedCommands.push_back(c);}// This is called in the tracker's own thread.void Tracker::GUICommandHandler(string sCommand, string sParams)  // Called by the callback func..{  if(sCommand=="Reset")    {      Reset();      return;    }  // KeyPress commands are issued by GLWindow  if(sCommand=="KeyPress")    {      if(sParams == "Space")	{	  mbUserPressedSpacebar = true;	}      else if(sParams == "r")	{	  Reset();	}      else if(sParams == "q" || sParams == "Escape")	{	  GUI.ParseLine("quit");	}      return;    }  if((sCommand=="PokeTracker"))    {      mbUserPressedSpacebar = true;      return;    }        cout << "! Tracker::GUICommandHandler: unhandled command "<< sCommand << endl;  exit(1);}; // Routine for establishing the initial map. This requires two spacebar presses from the user// to define the first two key-frames. Salient points are tracked between the two keyframes// using cheap frame-to-frame tracking (which is very brittle - quick camera motion will// break it.) The salient points are stored in a list of `Trail' data structures.// What action TrackForInitialMap() takes depends on the mnInitialStage enum variable..void Tracker::TrackForInitialMap(){  // MiniPatch tracking threshhold.  static gvar3<int> gvnMaxSSD("Tracker.MiniPatchMaxSSD", 100000, SILENT);  MiniPatch::mnMaxSSD = *gvnMaxSSD;    // What stage of initial tracking are we at?  if(mnInitialStage == TRAIL_TRACKING_NOT_STARTED)     {      if(mbUserPressedSpacebar)  // First spacebar = this is the first keyframe	{	  mbUserPressedSpacebar = false;	  TrailTracking_Start();	  mnInitialStage = TRAIL_TRACKING_STARTED;	}      else	mMessageForUser << "Point camera at planar scene and press spacebar to start tracking for initial map." << endl;      return;    };    if(mnInitialStage == TRAIL_TRACKING_STARTED)    {      int nGoodTrails = TrailTracking_Advance();  // This call actually tracks the trails      if(nGoodTrails < 10) // if most trails have been wiped out, no point continuing.	{	  Reset();	  return;	}            // If the user pressed spacebar here, use trails to run stereo and make the intial map..      if(mbUserPressedSpacebar)	{	  mbUserPressedSpacebar = false;	  vector<pair<ImageRef, ImageRef> > vMatches;   // This is the format the mapmaker wants for the stereo pairs	  for(list<Trail>::iterator i = mlTrails.begin(); i!=mlTrails.end(); i++)	    vMatches.push_back(pair<ImageRef, ImageRef>(i->irInitialPos,							i->irCurrentPos));	  mMapMaker.InitFromStereo(mFirstKF, mCurrentKF, vMatches, mse3CamFromWorld);  // This will take some time!	  mnInitialStage = TRAIL_TRACKING_COMPLETE;	}      else	mMessageForUser << "Translate the camera slowly sideways, and press spacebar again to perform stereo init." << endl;    }}// The current frame is to be the first keyframe!void Tracker::TrailTracking_Start()

⌨️ 快捷键说明

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