Program Listing for File Frame.h¶
↰ Return to documentation for file (lib/DataStructures/Frame.h)
#pragma once
#include "DataStructures/FrameMemory.h"
#include "DataStructures/FramePoseStruct.h"
#include "unordered_set"
#include "util/Configuration.h"
#include "util/SophusUtil.h"
#include "util/settings.h"
#include <boost/thread/recursive_mutex.hpp>
#include <boost/thread/shared_mutex.hpp>
#include <mutex>
#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;
cv::Mat getCvImage();
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;
}
} // namespace lsd_slam