Program Listing for File Relocalizer.cpp

Return to documentation for file (lib/Tracking/Relocalizer.cpp)

#include "Relocalizer.h"
#include "DataStructures/Frame.h"
#include "DataStructures/KeyFrame.h"
#include "Tracking/SE3Tracker.h"
#include "IOWrapper/ImageDisplay.h"

namespace lsd_slam
{


Relocalizer::Relocalizer()
    : isRunning( false ),
      KFForReloc(),
      nextRelocIDX( 0 ),
      maxRelocIDX( 0 ),
      continueRunning( false ),
        hasResult( false ),
        resultKF( nullptr ),
        resultFrameID( 0 ),
        resultFrameToKeyframe( SE3() ),
        _printRelocalizationInfo( false )
{
    for(int i=0;i<RELOCALIZE_THREADS;i++)
        running[i] = false;

}


Relocalizer::~Relocalizer()
{
    stop();
}


void Relocalizer::stop()
{
    continueRunning = false;
    exMutex.lock();
    newCurrentFrameSignal.notify_all();
    exMutex.unlock();
    for(int i=0;i<RELOCALIZE_THREADS;i++)
    {
        relocThreads[i].join();
        running[i] = false;
    }
    isRunning = false;


    KFForReloc.clear();
    CurrentRelocFrame.reset();
}


void Relocalizer::updateCurrentFrame(std::shared_ptr<Frame> currentFrame)
{
    std::lock_guard<std::mutex> lock(exMutex);

    if(hasResult) return;

    this->CurrentRelocFrame = currentFrame;
//  int doneLast = KFForReloc.size() - (maxRelocIDX-nextRelocIDX);
    maxRelocIDX = nextRelocIDX + KFForReloc.size();
    newCurrentFrameSignal.notify_all();

//  f("tried last on %d. set new current frame %d. trying %d to %d!\n",
//          doneLast,
//          currentFrame->id(), nextRelocIDX, maxRelocIDX);

    // Opening the window from deep within the stack was causing issues on OSX.
    // It was a good diagnostic but probably not the best UI choice anyway...
    // if (displayDepthMap)
    //  Util::displayImage( "DebugWindow DEPTH", cv::Mat(currentFrame->height(), currentFrame->width(), CV_32F, currentFrame->image())*(1/255.0f), false );
    //
    // int pressedKey = Util::waitKey(1);
    // handleKey(pressedKey);
}

void Relocalizer::start(std::vector<KeyFrame::SharedPtr> &allKeyframesList)
{
    // make KFForReloc List
    KFForReloc.clear();
    for(unsigned int k=0;k < allKeyframesList.size(); k++)
    {
        // insert
        const int ridx = rand()%(KFForReloc.size());
        auto itr = KFForReloc.begin();
        for( int i = 0; i < ridx; ++i ) { ++itr; }
        KFForReloc.insert(itr, allKeyframesList[k]);
    }
    nextRelocIDX=0;
    maxRelocIDX=KFForReloc.size();

    hasResult = false;
    continueRunning = true;
    isRunning = true;

    // start threads
    for(int i=0;i<RELOCALIZE_THREADS;i++)
    {
        relocThreads[i] = boost::thread(&Relocalizer::threadLoop, this, i);
        running[i] = true;
    }
}

bool Relocalizer::waitResult(int milliseconds)
{
    std::lock_guard<std::mutex> lock(exMutex);
    if(hasResult) return true;

    // !!TODO.  Change to C++11 condition variable
    //resultReadySignal.timed_wait(lock, boost::posix_time::milliseconds(milliseconds));
    return hasResult;
}

RelocalizerResult Relocalizer::getResult( void ) //Frame* &out_keyframe, std::shared_ptr<Frame> &frame, int &out_successfulFrameID, SE3 &out_frameToKeyframe)
{
    std::lock_guard<std::mutex> lock(exMutex);
    if(hasResult)
    {
        return RelocalizerResult( resultKF, resultRelocFrame, resultFrameID, resultFrameToKeyframe );
    }
    else
    {
        return RelocalizerResult();
    }
}


void Relocalizer::threadLoop(int idx)
{
    if(!multiThreading && idx != 0) return;

    SE3Tracker* tracker = new SE3Tracker(Conf().slamImageSize );

//  std::lock_guard<std::mutex> lock(exMutex);
    exMutex.lock();
    while(continueRunning)
    {
        // if got something: do it (unlock in the meantime)
        if(nextRelocIDX < maxRelocIDX && CurrentRelocFrame)
        {
            KeyFrame::SharedPtr todo( KFForReloc[nextRelocIDX%KFForReloc.size()] );
            nextRelocIDX++;
            if(todo->neighbors.size() <= 2) continue;

            std::shared_ptr<Frame> myRelocFrame = CurrentRelocFrame;

            exMutex.unlock();

            // initial Alignment
            SE3 todoToFrame = tracker->trackFrameOnPermaref(todo, myRelocFrame, SE3());

            // try neighbours
            float todoGoodVal = tracker->pointUsage * tracker->lastGoodCount() / (tracker->lastGoodCount()+tracker->lastBadCount());
            if(todoGoodVal > relocalizationTH)
            {
                int numGoodNeighbours = 0;
                int numBadNeighbours = 0;

                float bestNeightbourGoodVal = todoGoodVal;
                float bestNeighbourUsage = tracker->pointUsage;
                KeyFrame::SharedPtr bestKF(todo);
                SE3 bestKFToFrame = todoToFrame;
                for(auto nkf : todo->neighbors)
                {
                    SE3 nkfToFrame_init = se3FromSim3((nkf->frame()->getCamToWorld().inverse() * todo->frame()->getCamToWorld() * sim3FromSE3(todoToFrame.inverse(), 1))).inverse();
                    SE3 nkfToFrame = tracker->trackFrameOnPermaref(nkf, myRelocFrame, nkfToFrame_init);

                    float goodVal = tracker->pointUsage * tracker->lastGoodCount() / (tracker->lastGoodCount()+tracker->lastBadCount());
                    if(goodVal > relocalizationTH*0.8 && (nkfToFrame * nkfToFrame_init.inverse()).log().norm() < 0.1)
                        numGoodNeighbours++;
                    else
                        numBadNeighbours++;

                    if(goodVal > bestNeightbourGoodVal)
                    {
                        bestNeightbourGoodVal = goodVal;
                        bestKF = nkf;
                        bestKFToFrame = nkfToFrame;
                        bestNeighbourUsage = tracker->pointUsage;
                    }
                }

                if(numGoodNeighbours > numBadNeighbours || numGoodNeighbours >= 5)
                {
                    if(_printRelocalizationInfo)
                        printf("RELOCALIZED! frame %d on %d (bestNeighbour %d): good %2.1f%%, usage %2.1f%%, GoodNeighbours %d / %d\n",
                                myRelocFrame->id(), todo->id(), bestKF->id(),
                                100*bestNeightbourGoodVal, 100*bestNeighbourUsage,
                                numGoodNeighbours, numGoodNeighbours+numBadNeighbours);

                    // set everything to stop!
                    continueRunning = false;
                    exMutex.lock();
                    resultRelocFrame = myRelocFrame;
                    resultFrameID = myRelocFrame->id();
                    resultKF = bestKF;
                    resultFrameToKeyframe = bestKFToFrame.inverse();
                    resultReadySignal.notify_all();
                    hasResult = true;
                    exMutex.unlock();
                }
                else
                {
                    if(_printRelocalizationInfo)
                        printf("FAILED RELOCALIZE! frame %d on %d (bestNeighbour %d): good %2.1f%%, usage %2.1f%%, GoodNeighbours %d / %d\n",
                                myRelocFrame->id(), todo->id(), bestKF->id(),
                                100*bestNeightbourGoodVal, 100*bestNeighbourUsage,
                                numGoodNeighbours, numGoodNeighbours+numBadNeighbours);
                }
            }

            exMutex.lock();
        }
        else
        {
            // !!TODO.  Make this wok in C++11
            //newCurrentFrameSignal.wait(lock);
        }
    }
    exMutex.unlock();

    delete tracker;
}

}