Program Listing for File Frame.h¶
↰ Return to documentation for file (lib/DataStructures/Frame.h)
#pragma once
#include <mutex>
#include "util/SophusUtil.h"
#include "util/settings.h"
#include <boost/thread/recursive_mutex.hpp>
#include <boost/thread/shared_mutex.hpp>
#include "DataStructures/FramePoseStruct.h"
#include "DataStructures/FrameMemory.h"
#include "unordered_set"
#include "util/settings.h"
#include "util/Configuration.h"
#include "FrameData.h"
namespace lsd_slam
{
using libvideoio::Camera;
using libvideoio::ImageSize;
class KeyFrame;
class DepthMapPixelHypothesis;
class DepthMap;
template< int __LEVELS > class _TrackingRef;
typedef _TrackingRef<PYRAMID_LEVELS> TrackingReference;
class Frame
{
private:
// Again, having wierd FrameData alignment issues where it's of different
// lengths in different subunits unless it's at the top...
FrameData<PYRAMID_LEVELS> data;
public:
EIGEN_MAKE_ALIGNED_OPERATOR_NEW
friend class FrameMemory;
typedef std::shared_ptr<Frame> SharedPtr;
// Explicitly delete default and copy constructors
Frame() = delete;
Frame( const Frame & ) = delete;
Frame(int id, const Camera &cam, const ImageSize &sz, double timestamp, const unsigned char* image );
Frame(int id, const Camera &cam, const ImageSize &sz, double timestamp, const float* image );
~Frame();
void setDepth(const std::shared_ptr<DepthMap> &depthMap ); //PixelHypothesis* newDepth);
void calculateMeanInformation();
void setDepthFromGroundTruth(const float* depth, float cov_scale = 1.0f);
void prepareForStereoWith( const Frame::SharedPtr &other, Sim3 thisToOther, const int level);
// Accessors
inline int id() const { return _id; }
#define DATA_LEVEL_READER( _rtype, _name ) \
inline _rtype _name( int level = 0 ) const \
{ return data._name[level]; }
#define DATA_LEVEL_CAMERA_READER( _rtype, _name ) \
inline _rtype _name( int level = 0 ) const \
{ return data.camera[level]._name; }
inline const ImageSize &imgSize( int i=0 ) const { return data.imgSize[i]; }
inline int width( int i=0 ) const { return data.imgSize[i].width; }
inline int height( int i=0 ) const { return data.imgSize[i].height; }
inline int area( int i=0 ) const { return data.imgSize[i].area(); }
DATA_LEVEL_READER( const Camera &, camera )
DATA_LEVEL_CAMERA_READER( const Eigen::Matrix3f&, K )
DATA_LEVEL_CAMERA_READER( const Eigen::Matrix3f&, Kinv )
DATA_LEVEL_CAMERA_READER( float, fx )
DATA_LEVEL_CAMERA_READER( float, fy )
DATA_LEVEL_CAMERA_READER( float, cx )
DATA_LEVEL_CAMERA_READER( float, cy )
DATA_LEVEL_CAMERA_READER( float, fxi )
DATA_LEVEL_CAMERA_READER( float, fyi )
DATA_LEVEL_CAMERA_READER( float, cxi )
DATA_LEVEL_CAMERA_READER( float, cyi )
inline double timestamp() const { return _timestamp; }
inline float* image(int level = 0);
inline const Eigen::Vector4f* gradients(int level = 0);
inline const float* maxGradients(int level = 0);
inline bool hasIDepthBeenSet() const;
inline const float* idepth(int level = 0);
inline const float* idepthVar(int level = 0);
inline const unsigned char* validity_reAct();
inline const float* idepth_reAct();
inline const float* idepthVar_reAct();
inline bool* refPixelWasGood();
inline bool* refPixelWasGoodNoCreate();
inline void clear_refPixelWasGood();
enum DataFlags
{
IMAGE = 1<<0,
GRADIENTS = 1<<1,
MAX_GRADIENTS = 1<<2,
IDEPTH = 1<<3,
IDEPTH_VAR = 1<<4,
REF_ID = 1<<5,
ALL = IMAGE | GRADIENTS | MAX_GRADIENTS | IDEPTH | IDEPTH_VAR | REF_ID
};
// For SLAM-like features, KeyFrames can own their own TrackingReference
// this is copied into the keyframe when the keyframe is finalized
// This used for loop closure and re-localization
// void setPermaRef( const std::unique_ptr<TrackingReference> &reference);
// void takeReActivationData(DepthMapPixelHypothesis* depthMap);
// shared_lock this as long as any minimizable arrays are being used.
// the minimizer will only minimize frames after getting
// an exclusive lock on this.
inline boost::shared_lock<boost::shared_mutex> getActiveLock()
{
return FrameMemory::getInstance().activateFrame(this);
}
std::mutex frameMutex;
/*
* ==================================================================================
* Here are ALL central pose and scale informations.
* generally, everything is stored relative to the frame
*/
FramePoseStruct::SharedPtr pose;
Sim3 getCamToWorld() { return pose->getCamToWorld(); }
// parent, the frame originally tracked on. never changes.
void setTrackingParent( const std::shared_ptr<KeyFrame> &newParent ) { _trackingParent = newParent; }
bool hasTrackingParent() const { return (bool)_trackingParent; }
const std::shared_ptr<KeyFrame> &trackingParent() const { return _trackingParent; }
bool isTrackingParent( const std::shared_ptr<Frame> &other ) const;
bool isTrackingParent( const std::shared_ptr<KeyFrame> &other ) const;
bool isTrackingParent( int id ) const;
Sim3 lastConstraintTrackedCamToWorld;
// flag set when depth is updated.
//bool depthHasBeenUpdatedFlag;
// Tracking Reference for quick test. Always available, never taken out of memory.
// this is used for re-localization and re-Keyframe positioning.
// boost::mutex permaRef_mutex;
// Eigen::Vector3f* permaRef_posData; // (x,y,z)
// Eigen::Vector2f* permaRef_colorAndVarData; // (I, Var)
// int permaRefNumPts;
// A bunch of state which is created by prepareForStereoWith()
int referenceID;
int referenceLevel;
float distSquared;
Eigen::Matrix3f K_otherToThis_R;
Eigen::Vector3f K_otherToThis_t;
Eigen::Vector3f otherToThis_t;
Eigen::Vector3f K_thisToOther_t;
Eigen::Matrix3f thisToOther_R;
Eigen::Vector3f otherToThis_R_row0;
Eigen::Vector3f otherToThis_R_row1;
Eigen::Vector3f otherToThis_R_row2;
Eigen::Vector3f thisToOther_t;
// statistics
float initialTrackedResidual;
float meanIdepth;
int numPoints;
int idxInKeyframes;
float edgeErrorSum, edgesNum;
int numMappablePixels;
float meanInformation;
private:
std::shared_ptr<KeyFrame> _trackingParent;
int _id;
double _timestamp;
void require(int dataFlags, int level = 0);
void release(int dataFlags, bool pyramidsOnly, bool invalidateOnly);
// void initialize(double timestamp);
void setDepth_Allocate();
void buildImage(int level);
void releaseImage(int level);
void buildGradients(int level);
void releaseGradients(int level);
void buildMaxGradients(int level);
void releaseMaxGradients(int level);
void buildIDepthAndIDepthVar(int level);
void releaseIDepth(int level);
void releaseIDepthVar(int level);
// used internally. locked while something is being built, such that no
// two threads build anything simultaneously. not locked on require() if nothing is changed.
boost::mutex buildMutex;
boost::shared_mutex activeMutex;
bool isActive;
bool minimizeInMemory();
};
inline float* Frame::image(int level)
{
if (! data.imageValid[level])
require(IMAGE, level);
return data.image[level];
}
inline const Eigen::Vector4f* Frame::gradients(int level)
{
if (! data.gradientsValid[level])
require(GRADIENTS, level);
return data.gradients[level];
}
inline const float* Frame::maxGradients(int level)
{
if (! data.maxGradientsValid[level])
require(MAX_GRADIENTS, level);
return data.maxGradients[level];
}
inline bool Frame::hasIDepthBeenSet() const
{
return data.hasIDepthBeenSet;
}
inline const float* Frame::idepth(int level)
{
if (! hasIDepthBeenSet())
{
LOG(WARNING) << "Frame " <<id() << "; idepth(): idepth has not been set yet!";
return nullptr;
}
if (! data.idepthValid[level])
require(IDEPTH, level);
return data.idepth[level];
}
inline const unsigned char* Frame::validity_reAct()
{
if( !data.reActivationDataValid)
return 0;
return data.validity_reAct;
}
inline const float* Frame::idepth_reAct()
{
if( !data.reActivationDataValid)
return 0;
return data.idepth_reAct;
}
inline const float* Frame::idepthVar_reAct()
{
if( !data.reActivationDataValid)
return 0;
return data.idepthVar_reAct;
}
inline const float* Frame::idepthVar(int level)
{
if (! hasIDepthBeenSet())
{
LOG(WARNING) << "Frame " << id() << "; idepthVar(): idepth has not been set yet!";
return nullptr;
}
if (! data.idepthVarValid[level]) require(IDEPTH_VAR, level);
return data.idepthVar[level];
}
inline bool* Frame::refPixelWasGood()
{
if( data.refPixelWasGood == 0)
{
boost::unique_lock<boost::mutex> lock2(buildMutex);
if(data.refPixelWasGood == 0)
{
const int width = data.imgSize[SE3TRACKING_MIN_LEVEL].width;
const int height = data.imgSize[SE3TRACKING_MIN_LEVEL].height;
data.refPixelWasGood = (bool*)FrameMemory::getInstance().getBuffer(sizeof(bool) * width * height);
memset(data.refPixelWasGood, 0xFFFFFFFF, sizeof(bool) * (width * height));
}
}
return data.refPixelWasGood;
}
inline bool* Frame::refPixelWasGoodNoCreate()
{
return data.refPixelWasGood;
}
inline void Frame::clear_refPixelWasGood()
{
FrameMemory::getInstance().returnBuffer(reinterpret_cast<float*>(data.refPixelWasGood));
data.refPixelWasGood=0;
}
}