diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index cc1d33c48b722bf2d0ad94be5e05effe2e744319..733ae9a3c56060fb942eb9c06377a4f00d9f2fcb 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -196,6 +196,7 @@ SET(HDRS_BASE pinholeTools.h problem.h processor_base.h + processor_capture_holder.h processor_factory.h processor_motion.h processor_tracker.h @@ -290,6 +291,7 @@ SET(SRCS_BASE node_base.cpp problem.cpp processor_base.cpp + processor_capture_holder.cpp processor_motion.cpp processor_tracker.cpp processor_tracker_feature.cpp diff --git a/src/capture_buffer.h b/src/capture_buffer.h new file mode 100644 index 0000000000000000000000000000000000000000..26537d058486a44e71543311414f62214d8834ea --- /dev/null +++ b/src/capture_buffer.h @@ -0,0 +1,173 @@ +/** + * \file capture_buffer.h + * + * Created on: Jul 12, 2017 + * \author: Jeremie Deray + */ + +#ifndef _WOLF_CAPTURE_BUFFER_H_ +#define _WOLF_CAPTURE_BUFFER_H_ + +#include "wolf.h" +#include "time_stamp.h" + +#include <list> +#include <algorithm> + +namespace wolf { + +//using namespace Eigen; + +enum class CaptureBufferPolicy : std::size_t +{ + TIME = 0, + NUM_CAPTURES, + ALL +}; + +/** \brief class for capture buffers. + * + * It consists of a buffer of pre-integrated motions (aka. delta-integrals) that is being filled + * by the motion processors (deriving from ProcessorMotion). + * Each delta-integral is accompanied by a time stamp, a Jacobian and a covariances matrix. + * + * This buffer contains the time stamp and delta-integrals: + * - since the last key-Frame + * - until the frame of this capture. + * + * The buffer can be queried for motion-integrals and delta-integrals corresponding to a provided time stamp, + * with the following rules: + * - If the query time stamp is later than the last one in the buffer, + * the last motion-integral or delta-integral is returned. + * - If the query time stamp is earlier than the beginning of the buffer, + * the earliest Motion or Delta is returned. + * - If the query time stamp matches one time stamp in the buffer exactly, + * the returned motion-integral or delta-integral is the one of the queried time stamp. + * - If the query time stamp does not match any time stamp in the buffer, + * the returned motion-integral or delta-integral is the one immediately before the query time stamp. + */ + +//template <CaptureBufferPolicy policy> +class CaptureBuffer +{ +public: + + CaptureBuffer(const Scalar _buffer_dt, const int _max_capture = -1); + ~CaptureBuffer() = default; + + void push_back(const CaptureBasePtr& capture); + +// std::list<CaptureBasePtr>& get(); +// const std::list<CaptureBasePtr>& get() const; + + const CaptureBasePtr& getCapture(const TimeStamp& _ts) const; + void getCapture(const TimeStamp& _ts, CaptureBasePtr& _motion) const; + + void remove(const CaptureBasePtr& capture); + + void clear(); +// void print(); + + const TimeStamp& earliest() const; + const TimeStamp& latest() const; + +//private: + + int max_capture_; + Scalar buffer_dt_; + + std::list<CaptureBasePtr> container_; +}; + + +CaptureBuffer::CaptureBuffer(const Scalar _buffer_dt, const int _max_capture) : + max_capture_(_max_capture), buffer_dt_(_buffer_dt) +{ + // +} + +void CaptureBuffer::push_back(const CaptureBasePtr& capture) +{ + container_.push_back(capture); + + WOLF_DEBUG("Buffer dt : ", container_.back()->getTimeStamp() - + container_.front()->getTimeStamp(), " vs ", buffer_dt_); + + while (container_.back()->getTimeStamp() - + container_.front()->getTimeStamp() > buffer_dt_) + { + container_.pop_front(); + } +} + +const CaptureBasePtr& CaptureBuffer::getCapture(const TimeStamp& _ts) const +{ + //assert((container_.front().ts_ <= _ts) && "Query time stamp out of buffer bounds"); + auto previous = std::find_if(container_.rbegin(), container_.rend(), + [&](const CaptureBasePtr& c) + { + return c->getTimeStamp() <= _ts; + }); + + if (previous == container_.rend()) + // The time stamp is older than the buffer's oldest data. + // We could do something here, and throw an error or something, but by now we'll return the first valid data + previous--; + + return *previous; +} + +void CaptureBuffer::getCapture(const TimeStamp& _ts, CaptureBasePtr& _capture) const +{ +// //assert((container_.front().ts_ <= _ts) && "Query time stamp out of buffer bounds"); +// auto previous = std::find_if(container_.rbegin(), container_.rend(), +// [&](const Motion& m) +// { +// return c->getTimeStamp() <= _ts; +// }); + +// if (previous == container_.rend()) +// // The time stamp is older than the buffer's oldest data. +// // We could do something here, but by now we'll return the last valid data +// previous--; + +// _capture = *previous; + + _capture = getCapture(_ts); +} + +//inline std::list<CaptureBasePtr>& CaptureBuffer::get() +//{ +// return container_; +//} + +//inline const std::list<CaptureBasePtr>& CaptureBuffer::get() const +//{ +// return container_; +//} + +inline void CaptureBuffer::remove(const CaptureBasePtr& capture) +{ + container_.remove(capture); +} + +inline void CaptureBuffer::clear() +{ + return container_.clear(); +} + +inline const TimeStamp& CaptureBuffer::earliest() const +{ + return (!container_.empty())? container_.front()->getTimeStamp() : + InvalidStamp; +} + +inline const TimeStamp& CaptureBuffer::latest() const +{ + return (!container_.empty())? container_.back()->getTimeStamp() : + InvalidStamp; +} + +} // namespace wolf + +#endif /* _WOLF_CAPTURE_BUFFER_H_ */ diff --git a/src/processor_capture_holder.cpp b/src/processor_capture_holder.cpp new file mode 100644 index 0000000000000000000000000000000000000000..299b14cf81c33a688ad764414517966668995d61 --- /dev/null +++ b/src/processor_capture_holder.cpp @@ -0,0 +1,151 @@ +/** + * \file processor_capture_holder.h + * + * Created on: Jul 12, 2017 + * \author: Jeremie Deray + */ + +//Wolf includes +#include "processor_capture_holder.h" + +namespace wolf { + +ProcessorCaptureHolder::ProcessorCaptureHolder(const Scalar& _buffer_size) : + ProcessorBase("CAPTURE HOLDER", _buffer_size/2.), + buffer_(_buffer_size) +{ + // +} + +void ProcessorCaptureHolder::process(CaptureBasePtr _capture_ptr) +{ + buffer_.push_back(_capture_ptr); +} + +bool ProcessorCaptureHolder::keyFrameCallback(FrameBasePtr _keyframe_ptr, + const Scalar& _time_tolerance) +{ + assert(_keyframe_ptr->getTrajectoryPtr() != nullptr + && "ProcessorMotion::keyFrameCallback: key frame must be in the trajectory."); + + // get keyframe's time stamp + const TimeStamp new_ts = _keyframe_ptr->getTimeStamp(); + + // find capture whose buffer is affected by the new keyframe + CaptureBasePtr existing_capture = findCaptureContainingTimeStamp(new_ts); + + if (existing_capture == nullptr) + { + WOLF_WARN("Could not find a capture at ts : ", new_ts.get()); + return false; + } + + WOLF_DEBUG("ProcessorCaptureHolder::keyFrameCallback", _time_tolerance); + WOLF_DEBUG("Capture of type : ", existing_capture->getType()); + WOLF_DEBUG("CaptureBuffer size : ", buffer_.container_.size()); + + // add motion capture to keyframe + if (std::abs(new_ts - existing_capture->getTimeStamp()) < _time_tolerance) + { + auto frame_ptr = existing_capture->getFramePtr(); + + if (frame_ptr != _keyframe_ptr) + { + _keyframe_ptr->addCapture(existing_capture); + + //WOLF_INFO("Adding capture laser !"); + + //frame_ptr->remove(); + } + //else + //WOLF_INFO("Capture laser already exists !"); + + // Remove as we don't want duplicates + buffer_.remove(existing_capture); + + return true; + } + else + { + WOLF_DEBUG("Capture doesn't fit dt : ", + std::abs(new_ts - existing_capture->getTimeStamp()), + " vs ", _time_tolerance); + + return false; + } +} + +CaptureBasePtr ProcessorCaptureHolder::findCaptureContainingTimeStamp(const TimeStamp& _ts) const +{ + WOLF_DEBUG("ProcessorCaptureHolder::findCaptureContainingTimeStamp: ts = ", + _ts.getSeconds(), ".", _ts.getNanoSeconds()); + +// auto capture_ptr = last_ptr_; +// while (capture_ptr != nullptr) +// { +// // capture containing motion previous than the ts found: +// if (buffer_.get().front()->getTimeStamp() < _ts) +// return capture_ptr; +// else +// { +// // go to the previous motion capture +// if (capture_ptr == last_ptr_) +// capture_ptr = std::static_pointer_cast<CaptureMotion>(origin_ptr_); +// else if (capture_ptr->getOriginFramePtr() == nullptr) +// return nullptr; +// else +// { +// CaptureBasePtr capture_base_ptr = capture_ptr->getOriginFramePtr()->getCaptureOf(getSensorPtr()); +// if (capture_base_ptr == nullptr) +// return nullptr; +// else +// capture_ptr = std::static_pointer_cast<CaptureMotion>(capture_base_ptr); +// } +// } +// } + +// return capture_ptr;. + +// auto capt = buffer_.getCapture(_ts); + + /// @todo +// WOLF_WARN("ProcessorCaptureHolder::findCaptureContainingTimeStamp " +// "looking for stamp ", +// _ts.get() - ((long)_ts.get()), +// " in (", +// buffer_.earliest().get() - ((long)buffer_.earliest().get()), ",", +// buffer_.latest().get() - ((long)buffer_.latest().get()), ").\n", +// "Found capture with stamp ", +// capt->getTimeStamp().get() - ((long)capt->getTimeStamp().get())); + +// return capt; + + + return buffer_.getCapture(_ts); +} + +ProcessorBasePtr ProcessorCaptureHolder::create(const std::string& _unique_name, + const ProcessorParamsBasePtr _params, + const SensorBasePtr) +{ + ProcessorParamsCaptureHolderPtr params; + + params = std::static_pointer_cast<ProcessorParamsCaptureHolder>(_params); + + // if cast failed use default value + if (params == nullptr) + params = std::make_shared<ProcessorParamsCaptureHolder>(); + + ProcessorCaptureHolderPtr prc_ptr = std::make_shared<ProcessorCaptureHolder>(params->buffer_size_); + prc_ptr->setName(_unique_name); + + return prc_ptr; +} + +} // namespace wolf + +// Register in the ProcessorFactory +#include "processor_factory.h" +namespace wolf { +WOLF_REGISTER_PROCESSOR("CAPTURE HOLDER", ProcessorCaptureHolder) +} // namespace wolf diff --git a/src/processor_capture_holder.h b/src/processor_capture_holder.h new file mode 100644 index 0000000000000000000000000000000000000000..dd3b6bd71c146be7d8652fce423751e4658ae973 --- /dev/null +++ b/src/processor_capture_holder.h @@ -0,0 +1,72 @@ +/** + * \file processor_capture_holder.h + * + * Created on: Jul 12, 2017 + * \author: Jeremie Deray + */ + +#ifndef _WOLF_PROCESSOR_CAPTURE_HOLDER_H_ +#define _WOLF_PROCESSOR_CAPTURE_HOLDER_H_ + +//Wolf includes +#include "processor_base.h" +#include "capture_base.h" +#include "capture_buffer.h" + +namespace wolf { + +WOLF_PTR_TYPEDEFS(ProcessorCaptureHolder); +WOLF_STRUCT_PTR_TYPEDEFS(ProcessorParamsCaptureHolder); + +/** + * \brief ProcessorParamsCaptureHolder + */ +struct ProcessorParamsCaptureHolder : public ProcessorParamsBase +{ + Scalar buffer_size_ = 30; +}; + +/** + * \brief ProcessorCaptureHolder + */ +class ProcessorCaptureHolder : public ProcessorBase +{ +public: + + ProcessorCaptureHolder(const Scalar& _buffer_size = 1); + virtual ~ProcessorCaptureHolder() = default; + + virtual void process(CaptureBasePtr _capture_ptr) override; + + /** \brief Vote for KeyFrame generation + * + * If a KeyFrame criterion is validated, this function returns true, + * meaning that it wants to create a KeyFrame at the \b last Capture. + * + * WARNING! This function only votes! It does not create KeyFrames! + */ + virtual bool voteForKeyFrame() override { return false; } + + virtual bool keyFrameCallback(FrameBasePtr _keyframe_ptr, + const Scalar& _time_tolerance) override; + + /** + * \brief Finds the capture that contains the closest previous motion of _ts + * \return a pointer to the capture (if it exists) or a nullptr (otherwise) + */ + CaptureBasePtr findCaptureContainingTimeStamp(const TimeStamp& _ts) const; + +protected: + + CaptureBuffer buffer_; + +public: + + static ProcessorBasePtr create(const std::string& _unique_name, + const ProcessorParamsBasePtr _params, + const SensorBasePtr sensor_ptr = nullptr); +}; + +} // namespace wolf + +#endif // _WOLF_PROCESSOR_CAPTURE_HOLDER_H_