diff --git a/hello_wolf/hello_wolf.cpp b/hello_wolf/hello_wolf.cpp index ac33da83c3fece5dce946e9c808869edd511e6f4..a705a480cef464c49c0ec6b2f463ecf527c825ec 100644 --- a/hello_wolf/hello_wolf.cpp +++ b/hello_wolf/hello_wolf.cpp @@ -141,7 +141,7 @@ int main() TimeStamp t(0.0); // t : 0.0 Vector3d x(0,0,0); Matrix3d P = Matrix3d::Identity() * 0.1; - problem->setPrior(x, P, t, 0.5); // KF1 : (0,0,0) + problem->setPriorFactor(x, P, t, 0.5); // KF1 : (0,0,0) // SELF CALIBRATION =================================================== diff --git a/include/core/factor/factor_block_absolute.h b/include/core/factor/factor_block_absolute.h index 0743548b7b4aad0517ecdd2590955c4cdf7c023c..4ff0a96e89ee4bb9b6b5a77534e6656da24d7269 100644 --- a/include/core/factor/factor_block_absolute.h +++ b/include/core/factor/factor_block_absolute.h @@ -31,15 +31,43 @@ class FactorBlockAbsolute : public FactorAnalytic /** \brief Constructor * * \param _sb_ptr the constrained state block - * \param _start_idx (default=0) the index of the first state element that is constrained - * \param _start_idx (default=-1) the size of the state segment that is constrained, -1 = all the * */ FactorBlockAbsolute(StateBlockPtr _sb_ptr, - unsigned int _start_idx = 0, - int _size = -1, - ProcessorBasePtr _processor_ptr = nullptr, - bool _apply_loss_function = false, + ProcessorBasePtr _processor_ptr, + bool _apply_loss_function, + FactorStatus _status = FAC_ACTIVE) : + FactorAnalytic("FactorBlockAbsolute", + nullptr, + nullptr, + nullptr, + nullptr, + _processor_ptr, + _apply_loss_function, + _status, + _sb_ptr), + sb_size_(_sb_ptr->getSize()), + sb_constrained_start_(0), + sb_constrained_size_(sb_size_) + { + assert(sb_constrained_size_+sb_constrained_start_ <= sb_size_); + + // precompute Jacobian (Identity) + J_ = Eigen::MatrixXd::Identity(sb_constrained_size_, sb_size_); + } + + /** \brief Constructor for segment of state block + * + * \param _sb_ptr the constrained state block + * \param _start_idx the index of the first state element that is constrained + * \param _start_idx the size of the state segment that is constrained, -1 = all the + * + */ + FactorBlockAbsolute(StateBlockPtr _sb_ptr, + unsigned int _start_idx, + int _size, + ProcessorBasePtr _processor_ptr, + bool _apply_loss_function, FactorStatus _status = FAC_ACTIVE) : FactorAnalytic("FactorBlockAbsolute", nullptr, diff --git a/include/core/factor/factor_quaternion_absolute.h b/include/core/factor/factor_quaternion_absolute.h index 6533bd414d54a9eb45da8c92336ba3d1f0e07739..8b399f668a8a4763c35186a309b1cfbf76f2a86b 100644 --- a/include/core/factor/factor_quaternion_absolute.h +++ b/include/core/factor/factor_quaternion_absolute.h @@ -24,8 +24,8 @@ class FactorQuaternionAbsolute: public FactorAutodiff<FactorQuaternionAbsolute,3 public: FactorQuaternionAbsolute(StateBlockPtr _sb_ptr, - ProcessorBasePtr _processor_ptr = nullptr, - bool _apply_loss_function = false, + ProcessorBasePtr _processor_ptr, + bool _apply_loss_function, FactorStatus _status = FAC_ACTIVE) : FactorAutodiff<FactorQuaternionAbsolute,3,4>("QUATERNION ABS", nullptr, diff --git a/include/core/problem/problem.h b/include/core/problem/problem.h index f2b19ef05c22f7a4c6777f889031dbda45d80a5b..8e5d7736eb0bd79c2e77948ae1e73d8a193f4d7f 100644 --- a/include/core/problem/problem.h +++ b/include/core/problem/problem.h @@ -34,6 +34,15 @@ enum Notification REMOVE }; +struct PriorOptions +{ + std::string mode = ""; + Eigen::VectorXd state; + Eigen::MatrixXd cov; + double time_tolerance; +}; +WOLF_STRUCT_PTR_TYPEDEFS(PriorOptions); + /** \brief Wolf problem node element in the Wolf Tree */ class Problem : public std::enable_shared_from_this<Problem> @@ -54,8 +63,8 @@ class Problem : public std::enable_shared_from_this<Problem> mutable std::mutex mut_factor_notifications_; mutable std::mutex mut_state_block_notifications_; mutable std::mutex mut_covariances_; - bool prior_is_set_; std::string frame_structure_; + PriorOptionsPtr prior_options_; private: // CAUTION: THESE METHODS ARE PRIVATE, DO NOT MAKE THEM PUBLIC !! Problem(const std::string& _frame_structure); // USE create() below !! @@ -157,10 +166,24 @@ class Problem : public std::enable_shared_from_this<Problem> // Trajectory branch ---------------------------------- TrajectoryBasePtr getTrajectory() const; - virtual FrameBasePtr setPrior(const Eigen::VectorXd& _prior_state, // - const Eigen::MatrixXd& _prior_cov, // - const TimeStamp& _ts, - const double _time_tolerance); + + // Prior + bool isPriorSet() const; + void setPriorOptions(const std::string& _mode, + const double _time_tolerance = 0, + const Eigen::VectorXd& _state = Eigen::VectorXd(0), + const Eigen::MatrixXd& _cov = Eigen::MatrixXd(0,0)); + FrameBasePtr applyPriorOptions(const TimeStamp& _ts); + FrameBasePtr setPriorFactor(const Eigen::VectorXd &_state, + const Eigen::MatrixXd &_cov, + const TimeStamp &_ts, + const double &_time_tol); + FrameBasePtr setPriorFix(const Eigen::VectorXd &_state, + const TimeStamp &_ts, + const double &_time_tol); + FrameBasePtr setPriorInitialGuess(const Eigen::VectorXd &_state, + const TimeStamp &_ts, + const double &_time_tol); /** \brief Emplace frame from string frame_structure * \param _frame_structure String indicating the frame structure. @@ -269,8 +292,6 @@ class Problem : public std::enable_shared_from_this<Problem> void getState (const TimeStamp& _ts, Eigen::VectorXd& _state) const; // Zero state provider Eigen::VectorXd zeroState ( ) const; - bool priorIsSet() const; - void setPriorIsSet(bool _prior_is_set); // Perturb state void perturb(double amplitude = 0.01); @@ -361,14 +382,9 @@ class Problem : public std::enable_shared_from_this<Problem> namespace wolf { -inline bool Problem::priorIsSet() const -{ - return prior_is_set_; -} - -inline void Problem::setPriorIsSet(bool _prior_is_set) +inline bool Problem::isPriorSet() const { - prior_is_set_ = _prior_is_set; + return prior_options_ == nullptr; } inline IsMotionPtr Problem::getProcessorIsMotion() diff --git a/include/core/processor/processor_motion.h b/include/core/processor/processor_motion.h index 81a9184ad4798ccbaac1ebd61a194f6e287331b4..e20da100d5f3dbd7f78df097eaa2634bae51b3e7 100644 --- a/include/core/processor/processor_motion.h +++ b/include/core/processor/processor_motion.h @@ -134,6 +134,10 @@ class ProcessorMotion : public ProcessorBase, public IsMotion { public: typedef enum { + FIRST_TIME_WITHOUT_PACK, // NOT POSSIBLE + FIRST_TIME_WITH_PACK_BEFORE_INCOMING, + FIRST_TIME_WITH_PACK_ON_INCOMING, + FIRST_TIME_WITH_PACK_AFTER_INCOMING, // NOT POSSIBLE RUNNING_WITHOUT_PACK, RUNNING_WITH_PACK_BEFORE_ORIGIN, RUNNING_WITH_PACK_ON_ORIGIN, diff --git a/src/problem/problem.cpp b/src/problem/problem.cpp index 53acc960ecc87a61d28d7e1567af966d0579b375..189e0f99bc51a765893c8c52e55ec2ac0971ccf0 100644 --- a/src/problem/problem.cpp +++ b/src/problem/problem.cpp @@ -7,14 +7,20 @@ #include "core/processor/processor_motion.h" #include "core/processor/processor_tracker.h" #include "core/capture/capture_pose.h" +#include "core/capture/capture_void.h" #include "core/factor/factor_base.h" +#include "core/factor/factor_block_absolute.h" +#include "core/factor/factor_quaternion_absolute.h" #include "core/sensor/sensor_factory.h" #include "core/processor/processor_factory.h" #include "core/state_block/state_block.h" +#include "core/state_block/state_quaternion.h" +#include "core/state_block/state_angle.h" #include "core/utils/logging.h" #include "core/utils/params_server.h" #include "core/utils/loader.h" #include "core/utils/check_log.h" +#include "core/math/covariance.h" // IRI libs includes @@ -36,8 +42,8 @@ Problem::Problem(const std::string& _frame_structure, SizeEigen _dim) : trajectory_ptr_(std::make_shared<TrajectoryBase>(_frame_structure)), map_ptr_(std::make_shared<MapBase>()), processor_is_motion_list_(std::list<IsMotionPtr>()), - prior_is_set_(false), - frame_structure_(_frame_structure) + frame_structure_(_frame_structure), + prior_options_(std::make_shared<PriorOptions>()) { dim_ = _dim; if (_frame_structure == "PO" and _dim == 2) @@ -59,7 +65,6 @@ Problem::Problem(const std::string& _frame_structure, SizeEigen _dim) : } else std::runtime_error( "Problem::Problem(): Unknown frame structure. Add appropriate frame structure to the switch statement."); - } void Problem::setup() @@ -153,21 +158,28 @@ ProblemPtr Problem::autoSetup(ParamsServer &_server) } // Prior - Eigen::VectorXd prior_state = _server.getParam<Eigen::VectorXd>("problem/prior/state"); - Eigen::MatrixXd prior_cov = _server.getParam<Eigen::MatrixXd>("problem/prior/cov"); - double prior_time_tolerance = _server.getParam<double>("problem/prior/time_tolerance"); - double prior_ts = _server.getParam<double>("problem/prior/timestamp"); - - WOLF_TRACE("prior timestamp:\n" , prior_ts); - WOLF_TRACE("prior state:\n" , prior_state.transpose()); - WOLF_TRACE("prior covariance:\n" , prior_cov); - WOLF_TRACE("prior time tolerance:\n", prior_time_tolerance); - - problem->setPrior(prior_state, prior_cov, prior_ts, prior_time_tolerance); + std::string prior_mode = _server.getParam<std::string>("problem/prior/mode"); + if (prior_mode == "nothing") + { + problem->setPriorOptions(prior_mode); + } + else if (prior_mode == "factor") + { + problem->setPriorOptions(prior_mode, + _server.getParam<double>("problem/prior/time_tolerance"), + _server.getParam<Eigen::VectorXd>("problem/prior/state"), + _server.getParam<Eigen::MatrixXd>("problem/prior/cov")); + } + else + { + problem->setPriorOptions(prior_mode, + _server.getParam<double>("problem/prior/timestamp"), + _server.getParam<Eigen::VectorXd>("problem/prior/state")); + } // Done return problem; - } +} Problem::~Problem() { @@ -233,10 +245,6 @@ ProcessorBasePtr Problem::installProcessor(const std::string& _prc_type, // prc_ptr->configure(_corresponding_sensor_ptr); prc_ptr->link(_corresponding_sensor_ptr); - // setting the origin in all processor motion if origin already setted - if (prc_ptr->isMotion() && prior_is_set_) - (std::static_pointer_cast<ProcessorMotion>(prc_ptr))->setOrigin(getLastKeyFrame()); - return prc_ptr; } @@ -277,11 +285,6 @@ ProcessorBasePtr Problem::installProcessor(const std::string& _prc_type, // prc_ptr->configure(sen_ptr); prc_ptr->link(sen_ptr); - - // setting the origin in all processor motion if origin already setted - if (prc_ptr->isMotion() && prior_is_set_) - (std::static_pointer_cast<ProcessorMotion>(prc_ptr))->setOrigin(getLastKeyFrame()); - return prc_ptr; } @@ -868,51 +871,133 @@ FrameBasePtr Problem::closestKeyOrAuxFrameToTimeStamp(const TimeStamp& _ts) cons return trajectory_ptr_->closestKeyOrAuxFrameToTimeStamp(_ts); } -FrameBasePtr Problem::setPrior(const Eigen::VectorXd& _prior_state, const Eigen::MatrixXd& _prior_cov, const TimeStamp& _ts, const double _time_tolerance) +void Problem::setPriorOptions(const std::string& _mode, + const double _time_tolerance, + const Eigen::VectorXd& _state, + const Eigen::MatrixXd& _cov) { - if ( ! prior_is_set_ ) + assert(prior_options_ != nullptr && "prior options have already been applied"); + assert(prior_options_->mode == "" && "prior options have already been set"); + assert((_mode == "nothing" || _mode == "initial_guess" || _mode == "fix" || _mode == "factor") && "wrong _mode value, it should be: 'nothing', 'initial_guess', 'fix' or 'factor'"); + + // Store options (optionals depending on the mode) + WOLF_TRACE("prior mode: ", _mode); + prior_options_->mode = _mode; + + if (prior_options_->mode != "nothing") { - // Create origin frame - FrameBasePtr origin_keyframe = emplaceFrame(KEY, _prior_state, _ts); - - // create origin capture with the given state as data - // Capture fix only takes 3d position and Quaternion orientation - CapturePosePtr init_capture; - // if (this->getFrameStructure() == "POV" and this->getDim() == 3) - // init_capture = CaptureBase::emplace<CapturePose>(origin_keyframe, _ts, nullptr, _prior_state.head(7), _prior_cov.topLeftCorner(6,6)); - // else - // init_capture = CaptureBase::emplace<CapturePose>(origin_keyframe, _ts, nullptr, _prior_state, _prior_cov); - - if (this->getDim() == 3) - init_capture = CaptureBase::emplace<CapturePose>(origin_keyframe, _ts, nullptr, _prior_state.head(7), _prior_cov.topLeftCorner(6,6)); - else - init_capture = CaptureBase::emplace<CapturePose>(origin_keyframe, _ts, nullptr, _prior_state.head(3), _prior_cov.topLeftCorner(3,3)); + assert(_time_tolerance > 0 && "time tolerance should be bigger than 0"); + + WOLF_TRACE("prior state: ", _state.transpose()); + WOLF_TRACE("prior time tolerance: ", _time_tolerance); + prior_options_->state = _state; + prior_options_->time_tolerance = _time_tolerance; + + if (prior_options_->mode == "factor") + { + assert(isCovariance(_cov) && "cov is not a covariance matrix (symmetric and Pos Def)"); + WOLF_TRACE("prior covariance:\n" , _cov); + prior_options_->cov = _cov; + } + } +} + +FrameBasePtr Problem::applyPriorOptions(const TimeStamp& _ts) +{ + assert(!isPriorSet() && "applyPriorOptions can be called once!"); + FrameBasePtr prior_keyframe(nullptr); - // emplace feature and factor - init_capture->emplaceFeatureAndFactor(); + if (prior_options_->mode != "nothing") + { + prior_keyframe = emplaceFrame(this->getFrameStructure(), + this->getDim(), + KEY, + prior_options_->state, + _ts); + + if (prior_options_->mode == "fix") + prior_keyframe->fix(); + else if (prior_options_->mode == "factor") + { + // FIXME: change whenever state is changed to a map<string,vector> + // ASSUMPTION: Independent measurements (non-correlated block-diagonal covariance matrix) - WOLF_DEBUG("Set prior callback: KF", origin_keyframe->id(), " Callback emitted with ts = ", origin_keyframe->getTimeStamp()); + // Emplace a capture + auto prior_cap = CaptureBase::emplace<CaptureVoid>(prior_keyframe, _ts, nullptr); - // Notify all motion processors about the prior KF - for (auto sensor : hardware_ptr_->getSensorList()) - for (auto processor : sensor->getProcessorList()) - if (processor->isMotion()) - // Motion processors will set its origin at the KF - (std::static_pointer_cast<ProcessorMotion>(processor))->setOrigin(origin_keyframe); + // Emplace a feature and a factor for each state block + int state_idx = 0; + int cov_idx = 0; + for (auto sb : prior_keyframe->getStateBlockVec()) + { + assert(sb != nullptr); + assert(state_idx+sb->getSize() <= prior_options_->state.size() && "prior_options state wrong size (dimension too small)"); + assert(cov_idx+sb->getLocalSize() <= prior_options_->cov.rows() && "prior_options cov wrong size (dimension too small)"); - prior_is_set_ = true; + // state block segment + Eigen::VectorXd state_segment = prior_options_->state.segment(state_idx, sb->getSize()); + Eigen::MatrixXd cov_block = prior_options_->cov.block(cov_idx, cov_idx, sb->getLocalSize(), sb->getLocalSize()); - // Notify all other processors about the origin KF --> they will join it or not depending on their received data - for (auto sensor : hardware_ptr_->getSensorList()) - for (auto processor : sensor->getProcessorList()) - if ( !processor->isMotion() ) - processor->keyFrameCallback(origin_keyframe, _time_tolerance); + // feature + auto prior_fea = FeatureBase::emplace<FeatureBase>(prior_cap, "prior", state_segment, cov_block); + + // factor + if (sb->hasLocalParametrization()) + { + if (std::dynamic_pointer_cast<StateQuaternion>(sb) != nullptr) + auto prior_fac = FactorBase::emplace<FactorQuaternionAbsolute>(prior_fea, sb, nullptr, false); + else if (std::dynamic_pointer_cast<StateAngle>(sb) != nullptr) + auto prior_fac = FactorBase::emplace<FactorBlockAbsolute>(prior_fea, sb, nullptr, false); + else + throw std::runtime_error("not implemented...!"); + } + else + { + auto prior_fac = FactorBase::emplace<FactorBlockAbsolute>(prior_fea, sb, nullptr, false); + } + state_idx += sb->getSize(); + cov_idx += sb->getLocalSize(); + } + assert(state_idx == prior_options_->state.size() && "prior_options state wrong size (dimension too big)"); + assert(cov_idx == prior_options_->cov.rows() && "prior_options cov wrong size (dimension too big)"); + } + else + assert(prior_options_->mode == "initial_guess" && "wrong prior_options->mode"); - return origin_keyframe; + // notify all processors + keyFrameCallback(prior_keyframe, nullptr, prior_options_->time_tolerance); } - else - throw std::runtime_error("Origin already set!"); + // remove prior options + prior_options_ = nullptr; + + return prior_keyframe; +} + +FrameBasePtr Problem::setPriorFactor(const Eigen::VectorXd &_state, + const Eigen::MatrixXd &_cov, + const TimeStamp &_ts, + const double &_time_tol) +{ + setPriorOptions("factor", _time_tol, _state, _cov); + return applyPriorOptions(_ts); +} + + +FrameBasePtr Problem::setPriorFix(const Eigen::VectorXd &_state, + const TimeStamp &_ts, + const double &_time_tol) +{ + setPriorOptions("fix", _time_tol, _state); + return applyPriorOptions(_ts); +} + +FrameBasePtr Problem::setPriorInitialGuess(const Eigen::VectorXd &_state, + const TimeStamp &_ts, + const double &_time_tol) +{ + setPriorOptions("initial_guess", _time_tol, _state); + return applyPriorOptions(_ts); } void Problem::loadMap(const std::string& _filename_dot_yaml) diff --git a/src/processor/processor_base.cpp b/src/processor/processor_base.cpp index f61f861b021e51a08dd92db301aa1bd8de159272..8c3ba79053e98cc77e9c80c2cb6bebc64915cc91 100644 --- a/src/processor/processor_base.cpp +++ b/src/processor/processor_base.cpp @@ -53,6 +53,10 @@ void ProcessorBase::captureCallback(CaptureBasePtr _capture_ptr) assert(_capture_ptr != nullptr && "captureCallback with a nullptr capture"); WOLF_DEBUG("P", isMotion() ? "M " : "T ", getName(), ": Capture ", _capture_ptr->id(), " callback received with ts = ", _capture_ptr->getTimeStamp()); + // apply prior in problem if not done (very first capture) + if (getProblem() && !getProblem()->isPriorSet()) + getProblem()->applyPriorOptions(_capture_ptr->getTimeStamp()); + // asking if capture should be stored if (storeCapture(_capture_ptr)) buffer_capture_.add(_capture_ptr->getTimeStamp(), _capture_ptr); diff --git a/src/processor/processor_motion.cpp b/src/processor/processor_motion.cpp index aded1532cc17fc6a0f2e0d48edbbca857a1ab28b..5787c019254e612180a7ae3fca58cc5da1b6d2a8 100644 --- a/src/processor/processor_motion.cpp +++ b/src/processor/processor_motion.cpp @@ -93,6 +93,18 @@ void ProcessorMotion::processCapture(CaptureBasePtr _incoming_ptr) switch(processing_step_) { + case FIRST_TIME_WITHOUT_PACK : + // TODO: create keyframe with zero state? asking problem emplaceFrame? + break; + case FIRST_TIME_WITH_PACK_BEFORE_INCOMING : + // TODO: create keyframe asking problem emplaceFrame + break; + case FIRST_TIME_WITH_PACK_ON_INCOMING : + // TODO: joint to this KF + break; + case FIRST_TIME_WITH_PACK_AFTER_INCOMING : + // TODO: create keyframe asking problem emplaceFrame + break; case RUNNING_WITHOUT_PACK : case RUNNING_WITH_PACK_ON_ORIGIN : break; @@ -588,40 +600,69 @@ CaptureMotionPtr ProcessorMotion::findCaptureContainingTimeStamp(const TimeStamp PackKeyFramePtr ProcessorMotion::computeProcessingStep() { - if (!getProblem()->priorIsSet()) +// if (!getProblem()->priorIsSet()) +// { +// WOLF_WARN ("||*||"); +// WOLF_INFO (" ... It seems you missed something!"); +// WOLF_ERROR("ProcessorMotion received data before being initialized."); +// WOLF_INFO ("Did you forget to issue a Problem::setPrior()?"); +// throw std::runtime_error("ProcessorMotion received data before being initialized."); +// } + + // Origin not set + if (!origin_ptr_) { - WOLF_WARN ("||*||"); - WOLF_INFO (" ... It seems you missed something!"); - WOLF_ERROR("ProcessorMotion received data before being initialized."); - WOLF_INFO ("Did you forget to issue a Problem::setPrior()?"); - throw std::runtime_error("ProcessorMotion received data before being initialized."); - } + PackKeyFramePtr pack = buffer_pack_kf_.selectFirstPackBefore(incoming_ptr_, params_motion_->time_tolerance); - PackKeyFramePtr pack = buffer_pack_kf_.selectFirstPackBefore(last_ptr_, params_motion_->time_tolerance); + if (pack) + { + if (buffer_pack_kf_.checkTimeTolerance(pack->key_frame->getTimeStamp(), pack->time_tolerance, incoming_ptr_->getTimeStamp(), params_motion_->time_tolerance)) + processing_step_ = FIRST_TIME_WITH_PACK_ON_INCOMING; + else if (pack->key_frame->getTimeStamp() < incoming_ptr_->getTimeStamp()) + { + WOLF_INFO("First time with a KF too old. It seems the prior has been set before receiving the first capture of this processor.") + processing_step_ = FIRST_TIME_WITH_PACK_BEFORE_INCOMING; + } + else + { + WOLF_INFO("First time with a KF newer than the first capture. It only can happen if prior mode is 'nothing'") + processing_step_ = FIRST_TIME_WITH_PACK_AFTER_INCOMING; + } + } + else + { + WOLF_INFO("First time with a KF newer than the first capture. It only can happen if prior mode is 'nothing'") + processing_step_ = FIRST_TIME_WITHOUT_PACK; + } + } + else + { + PackKeyFramePtr pack = buffer_pack_kf_.selectFirstPackBefore(last_ptr_, params_motion_->time_tolerance); - // ignore "future" KF to avoid MotionBuffer::split() error - if (pack && pack->key_frame->getTimeStamp() > last_ptr_->getBuffer().get().back().ts_) - pack = nullptr; + // ignore "future" KF to avoid MotionBuffer::split() error + if (pack && pack->key_frame->getTimeStamp() > last_ptr_->getBuffer().get().back().ts_) + pack = nullptr; - if (pack) - { - if (buffer_pack_kf_.checkTimeTolerance(pack->key_frame->getTimeStamp(), pack->time_tolerance, origin_ptr_->getTimeStamp(), params_motion_->time_tolerance)) + if (pack) { - WOLF_WARN("||*||"); - WOLF_INFO(" ... It seems you missed something!"); - WOLF_ERROR("Pack's KF and origin's KF have matching time stamps (i.e. below time tolerances)"); - // throw std::runtime_error("Pack's KF and origin's KF have matching time stamps (i.e. below time tolerances)"); - processing_step_ = RUNNING_WITH_PACK_ON_ORIGIN; - } - else if (pack->key_frame->getTimeStamp() < origin_ptr_->getTimeStamp()) - processing_step_ = RUNNING_WITH_PACK_BEFORE_ORIGIN; + if (buffer_pack_kf_.checkTimeTolerance(pack->key_frame->getTimeStamp(), pack->time_tolerance, origin_ptr_->getTimeStamp(), params_motion_->time_tolerance)) + { + WOLF_WARN("||*||"); + WOLF_INFO(" ... It seems you missed something!"); + WOLF_ERROR("Pack's KF and origin's KF have matching time stamps (i.e. below time tolerances)"); + // throw std::runtime_error("Pack's KF and origin's KF have matching time stamps (i.e. below time tolerances)"); + processing_step_ = RUNNING_WITH_PACK_ON_ORIGIN; + } + else if (pack->key_frame->getTimeStamp() < origin_ptr_->getTimeStamp()) + processing_step_ = RUNNING_WITH_PACK_BEFORE_ORIGIN; - else - processing_step_ = RUNNING_WITH_PACK_AFTER_ORIGIN; + else + processing_step_ = RUNNING_WITH_PACK_AFTER_ORIGIN; + } + else + processing_step_ = RUNNING_WITHOUT_PACK; } - else - processing_step_ = RUNNING_WITHOUT_PACK; return pack; } diff --git a/src/processor/processor_tracker.cpp b/src/processor/processor_tracker.cpp index 56d5ae4ae45ed40962274292328076087da7fb9f..59671c2308468052d364f3e12bff8aa4b828c625 100644 --- a/src/processor/processor_tracker.cpp +++ b/src/processor/processor_tracker.cpp @@ -297,7 +297,6 @@ void ProcessorTracker::computeProcessingStep() WOLF_INFO("Pack's KF and last's KF have matching time stamps (i.e. below time tolerances)"); WOLF_INFO("Check the following for correctness:"); WOLF_INFO(" - You have all processors installed before starting receiving any data"); - WOLF_INFO(" - You issued a problem->setPrior() after all processors are installed ---> ", (getProblem()->priorIsSet() ? "OK" : "NOK")); WOLF_INFO(" - You have configured all your processors with compatible time tolerances"); WOLF_ERROR("Pack's KF and last's KF have matching time stamps (i.e. below time tolerances)."); } diff --git a/src/sensor/sensor_base.cpp b/src/sensor/sensor_base.cpp index 09afa700e79e66b058df609ea004334bd0830e4b..07cd3697f6a7b3e1ae085b3a51cc158298e982b6 100644 --- a/src/sensor/sensor_base.cpp +++ b/src/sensor/sensor_base.cpp @@ -184,9 +184,9 @@ void SensorBase::addPriorParameter(const std::string& _key, const Eigen::VectorX // create & add factor absolute if (is_quaternion) - FactorBase::emplace<FactorQuaternionAbsolute>(ftr_prior, _sb); + FactorBase::emplace<FactorQuaternionAbsolute>(ftr_prior, _sb, nullptr, false); else - FactorBase::emplace<FactorBlockAbsolute>(ftr_prior, _sb, _start_idx, _size); + FactorBase::emplace<FactorBlockAbsolute>(ftr_prior, _sb, _start_idx, _size, nullptr, false); // store feature in params_prior_map_ params_prior_map_[_key] = ftr_prior; diff --git a/test/gtest_factor_absolute.cpp b/test/gtest_factor_absolute.cpp index c0f75e3e8753a568fafb772805910642031494d4..14dea0d458afbb8fa6223f0bfc8d286bc2a473e6 100644 --- a/test/gtest_factor_absolute.cpp +++ b/test/gtest_factor_absolute.cpp @@ -49,7 +49,7 @@ auto cap0 = CaptureBase::emplace<CaptureMotion>(frm0, "IMU ABS", 0, nullptr, pos TEST(FactorBlockAbs, fac_block_abs_p) { auto fea0 = FeatureBase::emplace<FeatureBase>(cap0, "POSITION", pose10.head<3>(), data_cov.topLeftCorner<3,3>()); - FactorBase::emplace<FactorBlockAbsolute>(fea0, fea0->getFrame()->getP()); + FactorBase::emplace<FactorBlockAbsolute>(fea0, fea0->getFrame()->getP(), nullptr, false); ASSERT_TRUE(problem_ptr->check(0)); @@ -67,7 +67,7 @@ TEST(FactorBlockAbs, fac_block_abs_p) TEST(FactorBlockAbs, fac_block_abs_p_tail2) { auto fea0 = FeatureBase::emplace<FeatureBase>(cap0, "POSITION TAIL 2", pose10.segment<2>(1), data_cov.bottomRightCorner<2,2>()); - FactorBase::emplace<FactorBlockAbsolute>(fea0, fea0->getFrame()->getP(),1,2); + FactorBase::emplace<FactorBlockAbsolute>(fea0, fea0->getFrame()->getP(),1,2, nullptr, false); // Unfix frame 0, perturb frm0 frm0->unfix(); @@ -83,7 +83,7 @@ TEST(FactorBlockAbs, fac_block_abs_p_tail2) TEST(FactorBlockAbs, fac_block_abs_v) { auto fea0 = FeatureBase::emplace<FeatureBase>(cap0, "FeatureVelocity", pose10.tail<3>(), data_cov.bottomRightCorner<3,3>()); - FactorBase::emplace<FactorBlockAbsolute>(fea0, fea0->getFrame()->getV()); + FactorBase::emplace<FactorBlockAbsolute>(fea0, fea0->getFrame()->getV(), nullptr, false); ASSERT_TRUE(problem_ptr->check(0)); @@ -101,7 +101,7 @@ TEST(FactorBlockAbs, fac_block_abs_v) TEST(FactorQuatAbs, fac_block_abs_o) { auto fea0 = FeatureBase::emplace<FeatureBase>(cap0, "FeatureQuaternion", pose10.segment<4>(3), data_cov.block<3,3>(3,3)); - FactorBase::emplace<FactorQuaternionAbsolute>(fea0, fea0->getFrame()->getO()); + FactorBase::emplace<FactorQuaternionAbsolute>(fea0, fea0->getFrame()->getO(), nullptr, false); ASSERT_TRUE(problem_ptr->check(0)); diff --git a/test/gtest_factor_block_difference.cpp b/test/gtest_factor_block_difference.cpp index 1e06c7a80377b99197a721e85473319f9bf34862..cded07e0a3d882710f6b42e16a9460afb5e77611 100644 --- a/test/gtest_factor_block_difference.cpp +++ b/test/gtest_factor_block_difference.cpp @@ -50,11 +50,11 @@ class FixtureFactorBlockDifference : public testing::Test Vector10d x_origin = problem_->zeroState(); Eigen::Matrix9d cov_prior = 1e-3 * Eigen::Matrix9d::Identity(); - KF0_ = problem_->setPrior(x_origin, cov_prior, t0, 0.1); + KF0_ = problem_->setPriorFactor(x_origin, cov_prior, t0, 0.1); - CaptureBasePtr capV0 = CaptureBase::emplace<CaptureBase>(KF0_, "Vel0", t0); - FeatureBasePtr featV0 = FeatureBase::emplace<FeatureBase>(capV0, "Vel0", x_origin.tail(3), cov_prior.bottomRightCorner<3,3>()); - FactorBasePtr facV0 = FactorBase::emplace<FactorBlockAbsolute>(featV0, KF0_->getV()); + //CaptureBasePtr capV0 = CaptureBase::emplace<CaptureBase>(KF0_, "Vel0", t0); + //FeatureBasePtr featV0 = FeatureBase::emplace<FeatureBase>(capV0, "Vel0", x_origin.tail(3), cov_prior.bottomRightCorner<3,3>()); + //FactorBasePtr facV0 = FactorBase::emplace<FactorBlockAbsolute>(featV0, KF0_->getV(), nullptr, false); KF1_ = problem_->emplaceFrame(KEY, problem_->zeroState(), t1); diff --git a/test/gtest_factor_diff_drive.cpp b/test/gtest_factor_diff_drive.cpp index 67ef0974061dfa88339bbf3be362794ec6af060d..2f6ebb53e7f315ebd82db9f172f8b43d00d8470a 100644 --- a/test/gtest_factor_diff_drive.cpp +++ b/test/gtest_factor_diff_drive.cpp @@ -449,7 +449,7 @@ TEST(FactorDiffDrive, preintegrate_and_solve_sensor_intrinsics_gt) Vector3d x2(3.0, -3.0, 0.0); Matrix3d P0; P0.setIdentity(); - auto F0 = problem->setPrior(x0, P0, t, 0.1); + auto F0 = problem->setPriorFactor(x0, P0, t, 0.1); // right turn 90 deg in N steps --> ends up in (1.5, -1.5, -pi/2) int N = 6; @@ -581,7 +581,7 @@ TEST(FactorDiffDrive, preintegrate_and_solve_sensor_intrinsics) Vector3d x2(3.0, -3.0, 0.0); Matrix3d P0; P0.setIdentity(); - auto F0 = problem->setPrior(x0, P0, t, 0.1); + auto F0 = problem->setPriorFactor(x0, P0, t, 0.1); // right turn 90 deg in N steps --> ends up in (1.5, -1.5, -pi/2) int N = 6; diff --git a/test/gtest_odom_2d.cpp b/test/gtest_odom_2d.cpp index 1176783c855954afba8bf5e0a7566fb37ecbc8b5..0929163a71e7ea0e1a2d31ca1958b39e7a2cb902 100644 --- a/test/gtest_odom_2d.cpp +++ b/test/gtest_odom_2d.cpp @@ -128,7 +128,7 @@ TEST(Odom2d, FactorFix_and_FactorOdom2d) CeresManager ceres_manager(Pr); // KF0 and absolute prior - FrameBasePtr F0 = Pr->setPrior(x0, P0,t0, dt/2); + FrameBasePtr F0 = Pr->setPriorFactor(x0, P0,t0, dt/2); // KF1 and motion from KF0 t += dt; @@ -217,7 +217,7 @@ TEST(Odom2d, VoteForKfAndSolve) CeresManager ceres_manager(problem); // Origin Key Frame - FrameBasePtr origin_frame = problem->setPrior(x0, P0, t0, dt/2); + FrameBasePtr origin_frame = problem->setPriorFactor(x0, P0, t0, dt/2); ceres_manager.solve(SolverManager::ReportVerbosity::BRIEF); ceres_manager.computeCovariances(SolverManager::CovarianceBlocksToBeComputed::ALL_MARGINALS); @@ -352,7 +352,7 @@ TEST(Odom2d, KF_callback) CeresManager ceres_manager(problem); // Origin Key Frame - FrameBasePtr keyframe_0 = problem->setPrior(x0, x0_cov, t0, dt/2); + FrameBasePtr keyframe_0 = problem->setPriorFactor(x0, x0_cov, t0, dt/2); // Check covariance values Eigen::Vector3d integrated_pose = x0; diff --git a/test/gtest_problem.cpp b/test/gtest_problem.cpp index 6d262ba06b81438499b29ab3d45fd4bb101c89db..f9800e3f3ee2495ad445de725d284d4ef943ceed 100644 --- a/test/gtest_problem.cpp +++ b/test/gtest_problem.cpp @@ -141,7 +141,7 @@ TEST(Problem, SetOrigin_PO_2d) Eigen::VectorXd x0(3); x0 << 1,2,3; Eigen::MatrixXd P0(3,3); P0.setIdentity(); P0 *= 0.1; // P0 is 0.1*Id - P->setPrior(x0, P0, t0, 1.0); + P->setPriorFactor(x0, P0, t0, 1.0); // check that no sensor has been added ASSERT_EQ(P->getHardware()->getSensorList().size(), (SizeStd) 0); @@ -151,18 +151,29 @@ TEST(Problem, SetOrigin_PO_2d) // check that we have one frame, one capture, one feature, one factor TrajectoryBasePtr T = P->getTrajectory(); - ASSERT_EQ(T->getFrameList().size(), (SizeStd) 1); FrameBasePtr F = P->getLastFrame(); - ASSERT_EQ(F->getCaptureList().size(), (SizeStd) 1); CaptureBasePtr C = F->getCaptureList().front(); - ASSERT_EQ(C->getFeatureList().size(), (SizeStd) 1); FeatureBasePtr f = C->getFeatureList().front(); - ASSERT_EQ(f->getFactorList().size(), (SizeStd) 1); + FactorBasePtrList fac_list; + F->getFactorList(fac_list); - // check that the factor is absolute (no pointers to other F, f, or L) - FactorBasePtr c = f->getFactorList().front(); - ASSERT_FALSE(c->getFrameOther()); - ASSERT_FALSE(c->getLandmarkOther()); + // check that we have one frame (prior) + ASSERT_EQ(T->getFrameList().size(), (SizeStd) 1); + // check that we have one capture (prior) + ASSERT_EQ(F->getCaptureList().size(), (SizeStd) 1); + // check that we have two features (prior: one per state block) + ASSERT_EQ(C->getFeatureList().size(), (SizeStd) 2); + // check that we have one frame, one capture, one feature, one factor + ASSERT_EQ(fac_list.size(), (SizeStd) 2); + + // check that the factors are absolute (no pointers to other F, f, or L) + for (auto fac : fac_list) + { + ASSERT_FALSE(fac->getFrameOther()); + ASSERT_FALSE(fac->getLandmarkOther()); + ASSERT_FALSE(fac->getCaptureOther()); + ASSERT_FALSE(fac->getFeatureOther()); + } // check that the Feature measurement and covariance are the ones provided ASSERT_MATRIX_APPROX(x0, f->getMeasurement(), Constants::EPS_SMALL ); @@ -178,7 +189,7 @@ TEST(Problem, SetOrigin_PO_3d) Eigen::VectorXd x0(7); x0 << 1,2,3,4,5,6,7; Eigen::MatrixXd P0(6,6); P0.setIdentity(); P0 *= 0.1; // P0 is 0.1*Id - P->setPrior(x0, P0, t0, 1.0); + P->setPriorFactor(x0, P0, t0, 1.0); // check that no sensor has been added ASSERT_EQ(P->getHardware()->getSensorList().size(), (SizeStd) 0); diff --git a/test/gtest_processor_base.cpp b/test/gtest_processor_base.cpp index c4a1c4b0470c92bf09df1a950a1c19e57d35642d..96db133bba8e3efa62e6dd68fc0c1331d24623fd 100644 --- a/test/gtest_processor_base.cpp +++ b/test/gtest_processor_base.cpp @@ -104,7 +104,7 @@ TEST(ProcessorBase, KeyFrameCallback) TimeStamp t(0.0); Vector3d x(0,0,0); Matrix3d P = Matrix3d::Identity() * 0.1; - problem->setPrior(x, P, t, dt/2); // KF1 + problem->setPriorFactor(x, P, t, dt/2); // KF1 CaptureOdom2dPtr capt_odo = make_shared<CaptureOdom2d>(t, sens_odo, Vector2d(0.5,0)); @@ -117,15 +117,21 @@ TEST(ProcessorBase, KeyFrameCallback) // Move t = t+dt; WOLF_INFO("----------------------- ts: ", t , " --------------------------"); + std::cout << "1\n"; capt_odo->setTimeStamp(t); + std::cout << "2\n"; proc_odo->captureCallback(capt_odo); + std::cout << "3\n"; // Track capt_trk = make_shared<CaptureVoid>(t, sens_trk); + std::cout << "4\n"; proc_trk->captureCallback(capt_trk); + std::cout << "5\n"; - problem->print(4,1,1,0); + problem->print(4,1,1,0); + std::cout << "6\n"; // Only odom creating KFs ASSERT_TRUE( problem->getLastKeyFrame()->getType().compare("PO 2d")==0 ); diff --git a/test/gtest_processor_diff_drive.cpp b/test/gtest_processor_diff_drive.cpp index 612f66019cd62b892a300df15da4a809b0d51e9a..d68ace3de5e37428d21d829ef3632008983a436f 100644 --- a/test/gtest_processor_diff_drive.cpp +++ b/test/gtest_processor_diff_drive.cpp @@ -311,7 +311,7 @@ TEST_F(ProcessorDiffDriveTest, process) Vector3d x(0,0,0); Matrix3d P; P.setIdentity(); - auto F0 = problem->setPrior(x, P, t, 0.1); + auto F0 = problem->setPriorFactor(x, P, t, 0.1); // 1. left turn 90 deg in N steps of 90/N deg --> ends up in (1.5, 1.5, pi/2) int N = 9; @@ -341,7 +341,7 @@ TEST_F(ProcessorDiffDriveTest, linear) Vector3d x(0,0,0); Matrix3d P; P.setIdentity(); - auto F0 = problem->setPrior(x, P, t, 0.1); + auto F0 = problem->setPriorFactor(x, P, t, 0.1); // Straight one turn of the wheels, in one go data(0) = 100.0 ; // one turn of the wheels @@ -366,7 +366,7 @@ TEST_F(ProcessorDiffDriveTest, angular) Vector3d x(0,0,0); Matrix3d P; P.setIdentity(); - auto F0 = problem->setPrior(x, P, t, 0.1); + auto F0 = problem->setPriorFactor(x, P, t, 0.1); // Straight one turn of the wheels, in one go data(0) = -20.0 ; // one fifth of a turn of the left wheel, in reverse diff --git a/test/gtest_processor_loopclosure.cpp b/test/gtest_processor_loopclosure.cpp index d00fb93407ab75bb150a576bc434640f1c75fe12..5fb84268d1c376955e8cb2c7a6ed4edbb7536c11 100644 --- a/test/gtest_processor_loopclosure.cpp +++ b/test/gtest_processor_loopclosure.cpp @@ -79,7 +79,7 @@ TEST(ProcessorLoopClosure, installProcessor) TimeStamp t(0.0); Vector3d x(0,0,0); Matrix3d P = Matrix3d::Identity() * 0.1; - problem->setPrior(x, P, t, dt/2); // KF1 + problem->setPriorFactor(x, P, t, dt/2); // KF1 // new KF diff --git a/test/gtest_processor_motion.cpp b/test/gtest_processor_motion.cpp index 076118ba3d7836dbf61cdb2ed1d38d81d46b9084..6170c83c7efbc2f6bbe91b71b289874294ddce40 100644 --- a/test/gtest_processor_motion.cpp +++ b/test/gtest_processor_motion.cpp @@ -75,7 +75,7 @@ class ProcessorMotion_test : public testing::Test{ Vector3d x0; x0 << 0, 0, 0; Matrix3d P0; P0.setIdentity(); - problem->setPrior(x0, P0, 0.0, 0.01); + problem->setPriorFactor(x0, P0, 0.0, 0.01); } virtual void TearDown(){}