Program Listing for File TrackingThread.cpp

Return to documentation for file (lib/SlamSystem/TrackingThread.cpp)

#include <boost/thread/shared_lock_guard.hpp>

#include "TrackingThread.h"

#include "SlamSystem.h"

#include "DataStructures/KeyFrame.h"
#include "Tracking/SE3Tracker.h"
// #include "Tracking/Sim3Tracker.h"
// #include "DepthEstimation/DepthMap.h"
#include "Tracking/TrackingReference.h"
// #include "util/globalFuncs.h"
#include "GlobalMapping/KeyFrameGraph.h"
#include "GlobalMapping/TrackableKeyFrameSearch.h"
//#include "ros/ros.h"
// #include "GlobalMapping/g2oTypeSim3Sophus.h"
// #include "IOWrapper/ImageDisplay.h"
// #include "IOWrapper/Output3DWrapper.h"
// #include <g2o/core/robust_kernel_impl.h>
// #include "DataStructures/FrameMemory.h"
// #include "deque

#include "SlamSystem/MappingThread.h"

// for mkdir
#include <sys/stat.h>
#include <sys/types.h>

#include <g3log/g3log.hpp>

#ifdef ANDROID
#include <android/log.h>
#endif

#include "opencv2/opencv.hpp"

using namespace lsd_slam;

using active_object::Active;

TrackingThread::TrackingThread(SlamSystem &system, bool threaded)
    : _system(system), _perf(), _tracker(new SE3Tracker(Conf().slamImageSize)),
      //_trackingReference( new TrackingReference() ),
      _trackingIsGood(true), _newKeyFramePending(false),
      _latestGoodPoseCamToWorld(),
      _thread(threaded ? Active::createActive() : NULL) {
  // Do not use more than 4 levels for odometry tracking
  for (int level = 4; level < PYRAMID_LEVELS; ++level)
    _tracker->settings.maxItsPerLvl[level] = 0;

  lastTrackingClosenessScore = 0;
}

TrackingThread::~TrackingThread() { ; }

void TrackingThread::trackSetImpl(const std::shared_ptr<ImageSet> &set) {
  if (!_trackingIsGood) {
    // Prod mapping to check the relocalizer

    // _system._mapThread->relocalizer.updateCurrentFrame(set->refFrame());
    // _system._mapThread->pushDoIteration();

    return;
  }

  // DO TRACKING & Show tracking result.
  LOG_IF(DEBUG, Conf().print.threadingInfo)
      << "TRACKING frame " << set->refFrame()->id() << " onto ref. "
      << _currentKeyFrame->id();

  SE3 frameToReference_initialEstimate =
      se3FromSim3(_currentKeyFrame->pose()->getCamToWorld().inverse() *
                  _latestGoodPoseCamToWorld);

  Timer timer;

  LOG(DEBUG) << "Start tracking...";
  SE3 newRefToFrame_poseUpdate = _tracker->trackFrame(
      _currentKeyFrame, set->refFrame(), frameToReference_initialEstimate);

  LOG(DEBUG) << "Done tracking, took " << timer.stop() * 1000 << " ms";
  _perf.track.update(timer);

  tracking_lastResidual = _tracker->lastResidual;
  tracking_lastUsage = _tracker->pointUsage;

  if (manualTrackingLossIndicated || _tracker->diverged ||
      (_system.keyFrameGraph()->keyframesAll.size() >
           INITIALIZATION_PHASE_COUNT &&
       !_tracker->trackingWasGood)) {
    LOGF(WARNING,
         "TRACKING LOST for frame %d (%1.2f%% good Points, which is %1.2f%% of "
         "available points; %s tracking; tracker has %s)!\n",
         set->refFrame()->id(), 100 * _tracker->_pctGoodPerTotal,
         100 * _tracker->_pctGoodPerGoodBad,
         _tracker->trackingWasGood ? "GOOD" : "BAD",
         _tracker->diverged ? "DIVERGED" : "NOT DIVERGED");

    //_trackingReference->invalidate();
    setTrackingIsBad();

    //_system.mapThread->pushDoIteration();
    manualTrackingLossIndicated = false;
    return;
  }
  _latestGoodPoseCamToWorld = set->refFrame()->pose->getCamToWorld();

  LOG_IF(DEBUG, Conf().print.threadingInfo) << "Publishing tracked frame";
  _system.publishTrackedFrame(set->refFrame());
  _system.publishPose(set->refFrame()->getCamToWorld().cast<float>());

  // Keyframe selection
  LOG(INFO) << "Tracked " << set->id() << " against keyframe "
            << _currentKeyFrame->id();
  LOG_IF(INFO, Conf().print.threadingInfo)
      << _currentKeyFrame->numMappedOnThisTotal
      << " frames mapped on to keyframe " << _currentKeyFrame->id()
      << ", considering " << set->refFrame()->id() << " as new keyframe.";

  // Push to mapping before checking if its the new keyframe
  _system.mapThread()->doMapSet(_currentKeyFrame, set);

  if (!_newKeyFramePending &&
      _currentKeyFrame->numMappedOnThisTotal > MIN_NUM_MAPPED) {
    Sophus::Vector3d dist = newRefToFrame_poseUpdate.translation() *
                            _currentKeyFrame->frame()->meanIdepth;
    float minVal = fmin(0.2f + _system.keyFrameGraph()->size() * 0.8f /
                                   INITIALIZATION_PHASE_COUNT,
                        1.0f);

    if (_system.keyFrameGraph()->size() < INITIALIZATION_PHASE_COUNT)
      minVal *= 0.7;

    lastTrackingClosenessScore =
        _system.trackableKeyFrameSearch()->getRefFrameScore(
            dist.dot(dist), _tracker->pointUsage);

    if (lastTrackingClosenessScore > minVal) {
      LOG(INFO) << "Telling mapping thread to make " << set->refFrame()->id()
                << " the new keyframe.";

      _newKeyFramePending = true;
      _system.mapThread()->doCreateNewKeyFrame(_currentKeyFrame, set);

      LOGF_IF(INFO, Conf().print.keyframeSelectionInfo,
              "SELECT KEYFRAME %d on %d! dist %.3f + usage %.3f = %.3f > 1\n",
              set->refFrame()->id(), set->refFrame()->trackingParent()->id(),
              dist.dot(dist), _tracker->pointUsage,
              _system.trackableKeyFrameSearch()->getRefFrameScore(
                  dist.dot(dist), _tracker->pointUsage));
    } else {
      LOGF_IF(INFO, Conf().print.keyframeSelectionInfo,
              "SKIPPD KEYFRAME %d on %d! dist %.3f + usage %.3f = %.3f > 1\n",
              set->refFrame()->id(), set->refFrame()->trackingParent()->id(),
              dist.dot(dist), _tracker->pointUsage,
              _system.trackableKeyFrameSearch()->getRefFrameScore(
                  dist.dot(dist), _tracker->pointUsage));
    }
  }

  LOG_IF(DEBUG, Conf().print.threadingInfo) << "Exiting trackFrame";
}

void TrackingThread::useNewKeyFrameImpl(const std::shared_ptr<KeyFrame> &kf) {
  LOG(DEBUG) << "Using " << kf->id() << " as new keyframe";
  _newKeyFramePending = false;
  _currentKeyFrame = kf;
}

// n.b. this function will be called from the mapping thread.  Ensure
// locking is in place.

// TODO I don't think this is ever entered?
// Need to add pushUnmappedTrackedFrame for image set
void TrackingThread::takeRelocalizeResult(const RelocalizerResult &result) {
  LOG(WARNING) << "Entering takeRelocalizeResult";
  // Frame* keyframe;
  // int succFrameID;
  // SE3 succFrameToKF_init;
  // std::shared_ptr<Frame> succFrame;
  //
  // relocalizer.stop();
  // relocalizer.getResult(keyframe, succFrame, succFrameID,
  // succFrameToKF_init); assert(keyframe != 0);

  // KeyFrame::SharedPtr keyframe( _currentKeyFrame );
  // _trackingReference->importFrame( keyframe );
  // _trackingReferenceFrameSharedPT = keyframe;

  _tracker->trackFrame(_currentKeyFrame, result.successfulFrame,
                       result.successfulFrameToKeyframe);

  if (!_tracker->trackingWasGood ||
      _tracker->lastGoodCount() / (_tracker->lastGoodCount()) <
          1 - 0.75f * (1 - MIN_GOODPERGOODBAD_PIXEL)) {
    LOG_IF(DEBUG, Conf().print.relocalizationInfo)
        << "RELOCALIZATION FAILED BADLY! discarding result.";
    //_trackingReference->invalidate();
  } else {
    //_system.keyFrameGraph()->addFrame(result.successfulFrame );

    // TODO commenting this out in the assumption I don't need it... need to
    // revist _system.mapThread->pushUnmappedTrackedFrame( result.successfulFrame
    //);

    //{
    //       std::lock_guard<std::mutex> lock( currentKeyFrameMutex );
    // createNewKeyFrame = false;
    setTrackingIsGood();
    //}
  }
}