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->refFrame() );

        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();
                //}
    }

}