From 836e61bed93f8344c8bab868baff2b7d87ff69f7 Mon Sep 17 00:00:00 2001 From: joan vallve <jvallve@iri.upc.edu> Date: Thu, 1 Feb 2024 17:58:17 +0100 Subject: [PATCH] developing processorLandmarkExternal --- CMakeLists.txt | 2 + .../core/feature/feature_landmark_external.h | 63 ++ .../processor/processor_landmark_external.h | 218 ++-- src/feature/feature_landmark_external.cpp | 62 + src/processor/processor_landmark_external.cpp | 434 ++++--- test/gtest_processor_landmark_external.cpp | 1008 ++++++++++++----- 6 files changed, 1279 insertions(+), 508 deletions(-) create mode 100644 include/core/feature/feature_landmark_external.h create mode 100644 src/feature/feature_landmark_external.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index 94873905c..8f7b6c613 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -152,6 +152,7 @@ SET(HDRS_FACTOR SET(HDRS_FEATURE include/${PROJECT_NAME}/feature/feature_base.h include/${PROJECT_NAME}/feature/feature_diff_drive.h + include/${PROJECT_NAME}/feature/feature_landmark_external.h include/${PROJECT_NAME}/feature/feature_match.h include/${PROJECT_NAME}/feature/feature_motion.h include/${PROJECT_NAME}/feature/feature_odom_2d.h @@ -273,6 +274,7 @@ SET(SRCS_FACTOR SET(SRCS_FEATURE src/feature/feature_base.cpp src/feature/feature_diff_drive.cpp + src/feature/feature_landmark_external.cpp src/feature/feature_motion.cpp src/feature/feature_odom_2d.cpp src/feature/feature_pose.cpp diff --git a/include/core/feature/feature_landmark_external.h b/include/core/feature/feature_landmark_external.h new file mode 100644 index 000000000..c7a907d1e --- /dev/null +++ b/include/core/feature/feature_landmark_external.h @@ -0,0 +1,63 @@ +//--------LICENSE_START-------- +// +// Copyright (C) 2020,2021,2022,2023,2024 Institut de Robòtica i Informà tica Industrial, CSIC-UPC. +// Authors: Joan Solà Ortega (jsola@iri.upc.edu) +// All rights reserved. +// +// This file is part of WOLF +// WOLF is free software: you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public License +// along with this program. If not, see <http://www.gnu.org/licenses/>. +// +//--------LICENSE_END-------- +#pragma once + +// Wolf includes +#include "core/feature/feature_base.h" + +// std includes + +namespace wolf +{ + +WOLF_PTR_TYPEDEFS(FeatureLandmarkExternal); + +// class FeatureLandmarkExternal +class FeatureLandmarkExternal : public FeatureBase +{ + protected: + int external_id_; ///< The id of the landmark assigned by an external classifier + int external_type_; ///< The type of the landmark assigned by an external classifier + + public: + /** \brief Constructor from capture pointer and measure + * + * \param _measurement the measurement + * \param _meas_covariance the noise of the measurement + * \param _external_id the id assigned by an external tracker (-1 for not tracked) + * \param _external_type the type index of the landmark detection (-1 for not classified) + * + */ + FeatureLandmarkExternal(const Eigen::VectorXd& _measurement, + const Eigen::MatrixXd& _meas_covariance, + const int& _external_id = -1, + const int& _external_type = -1); + + ~FeatureLandmarkExternal() override; + + int getExternalType() const; + void setExternalType(const int& _external_type); + int getExternalId() const; + void setExternalId(const int& _external_id); +}; + +} // namespace wolf diff --git a/include/core/processor/processor_landmark_external.h b/include/core/processor/processor_landmark_external.h index 692eadd1d..8fd3f5417 100644 --- a/include/core/processor/processor_landmark_external.h +++ b/include/core/processor/processor_landmark_external.h @@ -33,121 +33,131 @@ WOLF_STRUCT_PTR_TYPEDEFS(ParamsProcessorLandmarkExternal); struct ParamsProcessorLandmarkExternal : public ParamsProcessorTracker { - bool use_orientation; ///< use orientation measure or not when emplacing factors - double match_dist_th; ///< for considering tracked detection: distance threshold to previous detection - unsigned int new_features_for_keyframe; ///< for keyframe voting: amount of new features with respect to origin (sufficient condition if more than min_features_for_keyframe) - double filter_quality_th; ///< min quality to consider the detection - unsigned int filter_track_length_th; ///< length of the track necessary to consider the detection - double time_span; ///< for keyframe voting: time span since last frame (sufficient condition if more than min_features_for_keyframe) + bool use_orientation; ///< use orientation measure or not when emplacing factors + double match_dist_th; ///< for considering tracked detection: distance threshold to previous detection + unsigned int new_features_for_keyframe; ///< for keyframe voting: amount of new features with respect to origin + ///< (sufficient condition if more than min_features_for_keyframe) + double filter_quality_th; ///< min quality to consider the detection + unsigned int filter_track_length_th; ///< length of the track necessary to consider the detection + double time_span; ///< for keyframe voting: time span since last frame (sufficient condition if more than + ///< min_features_for_keyframe) + bool check_dist_when_ids_match; ///< check the match_dist_th also in detections with matching external ID + bool close_loops_when_ids_match; ///< emplace loop closure factors if external ID matches ParamsProcessorLandmarkExternal() = default; - ParamsProcessorLandmarkExternal(std::string _unique_name, - const wolf::ParamsServer & _server): - ParamsProcessorTracker(_unique_name, _server) + ParamsProcessorLandmarkExternal(std::string _unique_name, const wolf::ParamsServer& _server) + : ParamsProcessorTracker(_unique_name, _server) { - use_orientation = _server.getParam<bool> (prefix + _unique_name + "/use_orientation"); - filter_quality_th = _server.getParam<double> (prefix + _unique_name + "/filter/quality_th"); - filter_track_length_th = _server.getParam<unsigned int>(prefix + _unique_name + "/filter/track_length_th"); - match_dist_th = _server.getParam<double> (prefix + _unique_name + "/match_dist_th"); - time_span = _server.getParam<double> (prefix + _unique_name + "/keyframe_vote/time_span"); - new_features_for_keyframe = _server.getParam<unsigned int>(prefix + _unique_name + "/keyframe_vote/new_features_for_keyframe"); + use_orientation = _server.getParam<bool>(prefix + _unique_name + "/use_orientation"); + filter_quality_th = _server.getParam<double>(prefix + _unique_name + "/filter/quality_th"); + filter_track_length_th = _server.getParam<unsigned int>(prefix + _unique_name + "/filter/track_length_th"); + match_dist_th = _server.getParam<double>(prefix + _unique_name + "/match_dist_th"); + time_span = _server.getParam<double>(prefix + _unique_name + "/keyframe_vote/time_span"); + new_features_for_keyframe = + _server.getParam<unsigned int>(prefix + _unique_name + "/keyframe_vote/new_features_for_keyframe"); + check_dist_when_ids_match = _server.getParam<bool>(prefix + _unique_name + "/check_dist_when_ids_match"); + close_loops_when_ids_match = _server.getParam<bool>(prefix + _unique_name + "/close_loops_when_ids_match"); } }; WOLF_PTR_TYPEDEFS(ProcessorLandmarkExternal); -//Class +// Class class ProcessorLandmarkExternal : public ProcessorTracker { - public: - ProcessorLandmarkExternal(ParamsProcessorLandmarkExternalPtr _params_tracker_feature); - ~ProcessorLandmarkExternal() override; - - // Factory method for high level API - WOLF_PROCESSOR_CREATE(ProcessorLandmarkExternal, ParamsProcessorLandmarkExternal); - - void configure(SensorBasePtr _sensor) override { }; - - protected: - - ParamsProcessorLandmarkExternalPtr params_tfle_; - TrackMatrix track_matrix_; - std::set<SizeStd> lmks_ids_origin_; - - /** Pre-process incoming Capture - * - * This is called by process() just after assigning incoming_ptr_ to a valid Capture. - * - * Extract the detections and fill unmatched_detections_incoming_ (FeaturePtrList) - */ - void preProcess() override; - - - /** \brief Process known Features - * \return The number of successful matches. - * - * This function tracks features from last to incoming and starts new tracks for new (not tracked) features in incoming - */ - unsigned int processKnown() override; - - /**\brief Process new Features - * - */ - unsigned int processNew(const int& _max_features) override { return 0;}; - - /** \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! - */ - bool voteForKeyFrame() const override; - - /** \brief Emplaces a new factor for each known feature in Capture \b last - */ - void establishFactors() override; - - /** \brief Emplaces a new factor - * \param _feature feature pointer - * \param _landmark pointer to the landmark - */ - FactorBasePtr emplaceFactor(FeatureBasePtr _feature, LandmarkBasePtr _landmark); - - /** \brief Emplaces a landmark or modifies (if needed) a landmark - * \param _feature_ptr pointer to the Feature - */ - LandmarkBasePtr emplaceLandmark(FeatureBasePtr _feature_ptr); - - /** \brief Modifies (if needed) a landmark - * \param _landmark pointer to the landmark - * \param _feature pointer to the Feature. - */ - void modifyLandmark(LandmarkBasePtr _landmark, - FeatureBasePtr _feature); - - /** Post-process - * - * This is called by process() after finishing the processing algorithm. - * - * It does nothing for now - */ - void postProcess() override {}; - - void advanceDerived() override; - void resetDerived() override; - - double detectionDistance(FeatureBasePtr _ftr1, - FeatureBasePtr _ftr2, - const VectorComposite& _pose1, - const VectorComposite& _pose2, - const VectorComposite& _pose_sen) const; + public: + ProcessorLandmarkExternal(ParamsProcessorLandmarkExternalPtr _params_tracker_feature); + ~ProcessorLandmarkExternal() override; + + // Factory method for high level API + WOLF_PROCESSOR_CREATE(ProcessorLandmarkExternal, ParamsProcessorLandmarkExternal); + + void configure(SensorBasePtr _sensor) override{}; + + protected: + ParamsProcessorLandmarkExternalPtr params_tfle_; + TrackMatrix track_matrix_; + std::set<SizeStd> lmks_ids_origin_; + std::map<int, SizeStd> external_id_to_landmark_id_; + + /** Pre-process incoming Capture + * + * This is called by process() just after assigning incoming_ptr_ to a valid Capture. + * + * Extract the detections and fill unmatched_detections_incoming_ (FeaturePtrList) + */ + void preProcess() override; + + /** \brief Process known Features + * \return The number of successful matches. + * + * This function tracks features from last to incoming and starts new tracks for new (not tracked) features in + * incoming + */ + unsigned int processKnown() override; + + /**\brief Process new Features + * + */ + unsigned int processNew(const int& _max_features) override + { + return 0; + }; + + /** \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! + */ + bool voteForKeyFrame() const override; + + /** \brief Emplaces a new factor for each known feature in Capture \b last + */ + void establishFactors() override; + + /** \brief Emplaces a new factor + * \param _feature feature pointer + * \param _landmark pointer to the landmark + */ + FactorBasePtr emplaceFactor(FeatureBasePtr _feature, LandmarkBasePtr _landmark); + + /** \brief Emplaces a landmark or modifies (if needed) a landmark + * \param _feature_ptr pointer to the Feature + */ + LandmarkBasePtr emplaceLandmark(FeatureBasePtr _feature_ptr); + + /** \brief Modifies (if needed) a landmark + * \param _landmark pointer to the landmark + * \param _feature pointer to the Feature. + */ + void modifyLandmark(LandmarkBasePtr _landmark, FeatureBasePtr _feature); + + /** Post-process + * + * This is called by process() after finishing the processing algorithm. + * + * It does nothing for now + */ + void postProcess() override{}; + + void advanceDerived() override; + void resetDerived() override; + + double detectionDistance(FeatureBasePtr _ftr1, + FeatureBasePtr _ftr2, + const VectorComposite& _pose1, + const VectorComposite& _pose2, + const VectorComposite& _pose_sen) const; + + SizeStd getAvailableLandmarkId() const; }; -inline ProcessorLandmarkExternal::ProcessorLandmarkExternal(ParamsProcessorLandmarkExternalPtr _params_tfle) : - ProcessorTracker("ProcessorLandmarkExternal", "PO", 0, _params_tfle), - params_tfle_(_params_tfle), - lmks_ids_origin_() +inline ProcessorLandmarkExternal::ProcessorLandmarkExternal(ParamsProcessorLandmarkExternalPtr _params_tfle) + : ProcessorTracker("ProcessorLandmarkExternal", "PO", 0, _params_tfle), + params_tfle_(_params_tfle), + lmks_ids_origin_() { // } @@ -157,4 +167,4 @@ inline ProcessorLandmarkExternal::~ProcessorLandmarkExternal() // } -} // namespace wolf +} // namespace wolf diff --git a/src/feature/feature_landmark_external.cpp b/src/feature/feature_landmark_external.cpp new file mode 100644 index 000000000..686d1261d --- /dev/null +++ b/src/feature/feature_landmark_external.cpp @@ -0,0 +1,62 @@ +//--------LICENSE_START-------- +// +// Copyright (C) 2020,2021,2022,2023,2024 Institut de Robòtica i Informà tica Industrial, CSIC-UPC. +// Authors: Joan Solà Ortega (jsola@iri.upc.edu) +// All rights reserved. +// +// This file is part of WOLF +// WOLF is free software: you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public License +// along with this program. If not, see <http://www.gnu.org/licenses/>. +// +//--------LICENSE_END-------- +#include "core/feature/feature_landmark_external.h" + +namespace wolf +{ + +FeatureLandmarkExternal::FeatureLandmarkExternal(const Eigen::VectorXd& _measurement, + const Eigen::MatrixXd& _meas_covariance, + const int& _external_id, + const int& _external_type) + : FeatureBase("FeatureLandmarkExternal", _measurement, _meas_covariance), + external_id_(_external_id), + external_type_(_external_type) +{ +} + +FeatureLandmarkExternal::~FeatureLandmarkExternal() +{ + // +} + +int FeatureLandmarkExternal::getExternalType() const +{ + return external_type_; +} + +void FeatureLandmarkExternal::setExternalType(const int& _external_type) +{ + external_type_ = _external_type; +} + +int FeatureLandmarkExternal::getExternalId() const +{ + return external_id_; +} + +void FeatureLandmarkExternal::setExternalId(const int& _external_id) +{ + external_id_ = _external_id; +} + +} // namespace wolf diff --git a/src/processor/processor_landmark_external.cpp b/src/processor/processor_landmark_external.cpp index dc8f5b97f..d7bfd41ec 100644 --- a/src/processor/processor_landmark_external.cpp +++ b/src/processor/processor_landmark_external.cpp @@ -22,7 +22,7 @@ #include "core/processor/processor_landmark_external.h" #include "core/capture/capture_landmarks_external.h" -#include "core/feature/feature_base.h" +#include "core/feature/feature_landmark_external.h" #include "core/factor/factor_relative_pose_2d_with_extrinsics.h" #include "core/factor/factor_relative_position_2d_with_extrinsics.h" #include "core/factor/factor_relative_pose_3d_with_extrinsics.h" @@ -43,21 +43,22 @@ void ProcessorLandmarkExternal::preProcess() { new_features_incoming_.clear(); - auto dim = getProblem()->getDim(); + auto dim = getProblem()->getDim(); auto cap_landmarks = std::dynamic_pointer_cast<CaptureLandmarksExternal>(incoming_ptr_); if (not cap_landmarks) - throw std::runtime_error("ProcessorLandmarkExternal::preProcess incoming_ptr_ should be of type 'CaptureLandmarksExternal'"); + throw std::runtime_error( + "ProcessorLandmarkExternal::preProcess incoming_ptr_ should be of type 'CaptureLandmarksExternal'"); // Extract features from capture detections - auto landmark_detections = cap_landmarks->getDetections(); + auto landmark_detections = cap_landmarks->getDetections(); std::set<int> ids; for (auto detection : landmark_detections) { - WOLF_WARN_COND(ids.count(detection.id), "ProcessorLandmarkExternal::preProcess: detection with repeated id, discarding..."); + WOLF_WARN_COND(ids.count(detection.id), + "ProcessorLandmarkExternal::preProcess: detection with repeated id, discarding..."); // Filter by quality - if (detection.quality < params_tfle_->filter_quality_th or ids.count(detection.id)) - continue; + if (detection.quality < params_tfle_->filter_quality_th or ids.count(detection.id)) continue; // measure and covariance VectorXd meas; @@ -68,33 +69,29 @@ void ProcessorLandmarkExternal::preProcess() assert(detection.covariance.rows() >= dim and detection.covariance.rows() == detection.covariance.cols()); meas = detection.measure.head(dim); - cov = detection.covariance.topLeftCorner(dim,dim); + cov = detection.covariance.topLeftCorner(dim, dim); } else { assert(detection.measure.size() == (dim == 2 ? 3 : 7)); - assert(detection.covariance.rows() == (dim == 2 ? 3 : 6) and detection.covariance.rows() == detection.covariance.cols()); + assert(detection.covariance.rows() == (dim == 2 ? 3 : 6) and + detection.covariance.rows() == detection.covariance.cols()); meas = detection.measure; cov = detection.covariance; } // emplace feature - FeatureBasePtr ftr = FeatureBase::emplace<FeatureBase>(cap_landmarks, - "FeatureLandmarkExternal", - meas, - cov); - ftr->setLandmarkId(detection.id); - - if (detection.id != -1 and detection.id != 0) - ids.insert(detection.id); - - //unmatched_detections_incoming_.push_back(ftr); + FeatureBasePtr ftr = + FeatureBase::emplace<FeatureLandmarkExternal>(cap_landmarks, meas, cov, detection.id, detection.type); + if (detection.id >= 0) ids.insert(detection.id); // add new feature new_features_incoming_.push_back(ftr); } - WOLF_DEBUG("ProcessorLandmarkExternal::preprocess: found ", new_features_incoming_.size(), " new features"); + WOLF_DEBUG("ProcessorLandmarkExternal::preprocess: found ", + new_features_incoming_.size(), + " features in incoming capture"); } unsigned int ProcessorLandmarkExternal::processKnown() @@ -112,24 +109,141 @@ unsigned int ProcessorLandmarkExternal::processKnown() for (auto feat_last : known_features_last_) { + auto feat_lmk_last = std::static_pointer_cast<FeatureLandmarkExternal>(feat_last); + bool matched = false; + + // First we try to match by EXTERNAL_ID (if defined) + if (feat_lmk_last->getExternalId() != -1) + { + WOLF_DEBUG("Tracking feature last: ", feat_lmk_last); + auto feat_candidate_it = new_features_incoming_.begin(); + while (feat_candidate_it != new_features_incoming_.end()) + { + auto feat_lmk_candidate = std::static_pointer_cast<FeatureLandmarkExternal>(*feat_candidate_it); + if (feat_lmk_candidate->getExternalId() == feat_lmk_last->getExternalId()) + { + // Check distance (if enabled) + if (not params_tfle_->check_dist_when_ids_match or + detectionDistance(feat_lmk_last, feat_lmk_candidate, pose_in, pose_out, pose_sen) < + params_tfle_->match_dist_th) + { + WOLF_DEBUG("Feature last: ", + feat_lmk_last, + " matched with feature ", + feat_lmk_candidate, + " with landmark ID: ", + feat_lmk_candidate->landmarkId()); + matched = true; + + // set LANDMARK_ID if candidate has LANDMARK_ID + if (feat_lmk_candidate->landmarkId() != 0) + feat_lmk_last->setLandmarkId(feat_lmk_candidate->landmarkId()); + + // grow track + track_matrix_.add(feat_lmk_last, feat_lmk_candidate); + + // feature is known + known_features_incoming_.push_back(feat_lmk_candidate); + + // remove from unmatched + feat_candidate_it = new_features_incoming_.erase(feat_candidate_it); + break; + } + else + feat_candidate_it++; + } + } + if (matched) continue; + } + // Second we try to match by TYPE (if defined) + if (feat_lmk_last->getExternalType() != -1) + { + auto feat_candidate_it = new_features_incoming_.begin(); + while (feat_candidate_it != new_features_incoming_.end()) + { + auto feat_lmk_candidate = std::static_pointer_cast<FeatureLandmarkExternal>(*feat_candidate_it); + if (feat_lmk_candidate->getExternalType() == feat_lmk_last->getExternalType()) + { + // Check distance (if enabled) + if (detectionDistance(feat_lmk_last, feat_lmk_candidate, pose_in, pose_out, pose_sen) < + params_tfle_->match_dist_th) + { + WOLF_DEBUG("Feature last: ", + feat_lmk_last, + " matched with feature ", + feat_lmk_candidate, + " with landmark ID: ", + feat_lmk_candidate->landmarkId()); + matched = true; + + // set LANDMARK_ID if candidate has LANDMARK_ID + if (feat_lmk_candidate->landmarkId() != 0) + feat_lmk_last->setLandmarkId(feat_lmk_candidate->landmarkId()); + + // set EXTERNAL_ID if candidate has EXTERNAL_ID + if (feat_lmk_candidate->getExternalId() != -1) + feat_lmk_last->setExternalId(feat_lmk_candidate->getExternalId()); + + // grow track + track_matrix_.add(feat_lmk_last, feat_lmk_candidate); + + // feature is known + known_features_incoming_.push_back(feat_lmk_candidate); + + // remove from unmatched + feat_candidate_it = new_features_incoming_.erase(feat_candidate_it); + break; + } + else + feat_candidate_it++; + } + } + if (matched) continue; + } + // Finally, we try to match by distance auto feat_candidate_it = new_features_incoming_.begin(); while (feat_candidate_it != new_features_incoming_.end()) { - if ((*feat_candidate_it)->landmarkId() == feat_last->landmarkId() and - detectionDistance(feat_last, (*feat_candidate_it), pose_in, pose_out, pose_sen) < params_tfle_->match_dist_th) + auto feat_lmk_candidate = std::static_pointer_cast<FeatureLandmarkExternal>(*feat_candidate_it); + if (feat_lmk_candidate->getExternalType() == feat_lmk_last->getExternalType()) { - // grow track - track_matrix_.add(feat_last, *feat_candidate_it); - - // feature is known - known_features_incoming_.push_back((*feat_candidate_it)); - - // remove from unmatched - feat_candidate_it = new_features_incoming_.erase(feat_candidate_it); - break; + // Check distance (if enabled) + if (detectionDistance(feat_lmk_last, feat_lmk_candidate, pose_in, pose_out, pose_sen) < + params_tfle_->match_dist_th) + { + WOLF_DEBUG("Feature last: ", + feat_lmk_last, + " matched with feature ", + feat_lmk_candidate, + " with landmark ID: ", + feat_lmk_candidate->landmarkId()); + matched = true; + + // set LANDMARK_ID if candidate has LANDMARK_ID + if (feat_lmk_candidate->landmarkId() != 0) + feat_lmk_last->setLandmarkId(feat_lmk_candidate->landmarkId()); + + // set TYPE if candidate has TYPE + if (feat_lmk_candidate->getExternalType() != -1) + feat_lmk_last->setExternalType(feat_lmk_candidate->getExternalType()); + + // set EXTERNAL_ID if candidate has EXTERNAL_ID + if (feat_lmk_candidate->getExternalId() != -1) + feat_lmk_last->setExternalId(feat_lmk_candidate->getExternalId()); + + // grow track + track_matrix_.add(feat_lmk_last, feat_lmk_candidate); + + // feature is known + known_features_incoming_.push_back(feat_lmk_candidate); + + // remove from unmatched + feat_candidate_it = new_features_incoming_.erase(feat_candidate_it); + break; + } + else + feat_candidate_it++; } - else - feat_candidate_it++; } } WOLF_DEBUG("Tracked ", known_features_incoming_.size(), " features."); @@ -139,7 +253,19 @@ unsigned int ProcessorLandmarkExternal::processKnown() WOLF_DEBUG_COND(not new_features_incoming_.empty(), "Adding new features ", new_features_incoming_.size()); while (not new_features_incoming_.empty()) { - auto ftr = new_features_incoming_.front(); + auto ftr = std::static_pointer_cast<FeatureLandmarkExternal>(new_features_incoming_.front()); + + // loop closure + if (params_tfle_->close_loops_when_ids_match and ftr->getExternalId() != -1 and + external_id_to_landmark_id_.count(ftr->getExternalId()) != 0) + { + WOLF_DEBUG("Feature ", + ftr->id(), + " set to close loop with landmark ", + external_id_to_landmark_id_.at(ftr->getExternalId())); + + ftr->setLandmarkId(external_id_to_landmark_id_.at(ftr->getExternalId())); + } // new track track_matrix_.newTrack(ftr); @@ -152,20 +278,23 @@ unsigned int ProcessorLandmarkExternal::processKnown() } // check all features have been emplaced - assert(std::all_of(known_features_incoming_.begin(), known_features_incoming_.end(), [](FeatureBasePtr f){return f->getCapture() != nullptr;}) && + assert(std::all_of(known_features_incoming_.begin(), + known_features_incoming_.end(), + [](FeatureBasePtr f) { return f->getCapture() != nullptr; }) && "any not linked feature returned by trackFeatures()"); return known_features_incoming_.size(); } -double ProcessorLandmarkExternal::detectionDistance(FeatureBasePtr _ftr1, - FeatureBasePtr _ftr2, - const VectorComposite& _pose1, - const VectorComposite& _pose2, - const VectorComposite& _pose_sen) const +double ProcessorLandmarkExternal::detectionDistance(FeatureBasePtr _ftr1, + FeatureBasePtr _ftr2, + const VectorComposite& _pose1, + const VectorComposite& _pose2, + const VectorComposite& _pose_sen) const { // Any not available info of poses, assume identity - if (not _pose1.includesStructure("PO") or not _pose2.includesStructure("PO") or not _pose_sen.includesStructure("PO")) + if (not _pose1.includesStructure("PO") or not _pose2.includesStructure("PO") or + not _pose_sen.includesStructure("PO")) { if (getProblem()->getDim() == 2) return (_ftr1->getMeasurement().head<2>() - _ftr2->getMeasurement().head<2>()).norm(); @@ -178,9 +307,9 @@ double ProcessorLandmarkExternal::detectionDistance(FeatureBasePtr _ftr1, { auto pose_s1 = SE2::compose(_pose1, _pose_sen); auto pose_s2 = SE2::compose(_pose2, _pose_sen); - auto p1 = pose_s1.at('P') + Rotation2Dd(pose_s1.at('O')(0)) * _ftr1->getMeasurement().head<2>(); - auto p2 = pose_s2.at('P') + Rotation2Dd(pose_s2.at('O')(0)) * _ftr2->getMeasurement().head<2>(); - return (p1-p2).norm(); + auto p1 = pose_s1.at('P') + Rotation2Dd(pose_s1.at('O')(0)) * _ftr1->getMeasurement().head<2>(); + auto p2 = pose_s2.at('P') + Rotation2Dd(pose_s2.at('O')(0)) * _ftr2->getMeasurement().head<2>(); + return (p1 - p2).norm(); } else { @@ -188,7 +317,7 @@ double ProcessorLandmarkExternal::detectionDistance(FeatureBasePtr _ftr1, auto pose_s2 = SE3::compose(_pose2, _pose_sen); auto p1 = pose_s1.at('P') + Quaterniond(Vector4d(pose_s1.at('O'))) * _ftr1->getMeasurement().head<3>(); auto p2 = pose_s2.at('P') + Quaterniond(Vector4d(pose_s2.at('O'))) * _ftr2->getMeasurement().head<3>(); - return (p1-p2).norm(); + return (p1 - p2).norm(); } } } @@ -197,87 +326,119 @@ bool ProcessorLandmarkExternal::voteForKeyFrame() const { auto track_ids_last = track_matrix_.trackIds(last_ptr_); - WOLF_DEBUG("Active feature tracks: " , track_ids_last.size() ); - - // no tracks longer than filter_track_length_th - auto n_tracks = 0; + WOLF_DEBUG("Active feature tracks: ", track_ids_last.size()); + + // number of tracks longer than filter_track_length_th + auto n_tracks = 0; auto n_new_tracks = 0; for (auto track_id : track_ids_last) { if (track_matrix_.trackSize(track_id) >= params_tfle_->filter_track_length_th) { n_tracks++; - if (not lmks_ids_origin_.count(track_matrix_.feature(track_id, last_ptr_)->landmarkId())) - n_new_tracks++; + // if (not lmks_ids_origin_.count(track_matrix_.feature(track_id, last_ptr_)->landmarkId())) + // n_new_tracks++; + if (track_matrix_.feature(track_id, last_ptr_)->landmarkId() == 0) n_new_tracks++; } } - + // Necessary condition: active valid tracks bool vote_min_features = n_tracks >= params_tfle_->min_features_for_keyframe; - WOLF_DEBUG("vote_min_features: ", vote_min_features, - " - Active feature tracks longer than ", params_tfle_->filter_track_length_th, ": ", n_tracks, - " (should be equal or bigger than ", params_tfle_->min_features_for_keyframe, ")"); + WOLF_DEBUG("vote_min_features: ", + vote_min_features, + " - Active feature tracks longer than ", + params_tfle_->filter_track_length_th, + ": ", + n_tracks, + " (should be equal or bigger than ", + params_tfle_->min_features_for_keyframe, + ")"); bool vote_new_features(true), vote_time_span(true); if (vote_min_features and origin_ptr_) { // Sufficient condition: new valid tracks vote_new_features = n_new_tracks >= params_tfle_->new_features_for_keyframe; - WOLF_DEBUG("vote_new_features: " , vote_new_features, - " - n_new_tracks = ", n_new_tracks, - " (should be equal or bigger than ", params_tfle_->new_features_for_keyframe, ")"); + WOLF_DEBUG("vote_new_features: ", + vote_new_features, + " - n_new_tracks = ", + n_new_tracks, + " (should be equal or bigger than ", + params_tfle_->new_features_for_keyframe, + ")"); // Sufficient condition: time span vote_time_span = last_ptr_->getTimeStamp() - origin_ptr_->getTimeStamp() > params_tfle_->time_span; - WOLF_DEBUG("vote_time_span: " , vote_time_span, - " - time_span = ", last_ptr_->getTimeStamp() - origin_ptr_->getTimeStamp(), - " (should be bigger than ", params_tfle_->time_span, ")"); + WOLF_DEBUG("vote_time_span: ", + vote_time_span, + " - time_span = ", + last_ptr_->getTimeStamp() - origin_ptr_->getTimeStamp(), + " (should be bigger than ", + params_tfle_->time_span, + ")"); } bool vote = vote_min_features and (vote_new_features or vote_time_span); - WOLF_DEBUG( (vote ? "Vote ": "Do NOT vote ") , "for KF" ); + WOLF_DEBUG((vote ? "Vote " : "Do NOT vote "), "for KF"); return vote; } void ProcessorLandmarkExternal::establishFactors() { - if (origin_ptr_ == last_ptr_) - return; + WOLF_DEBUG("establishFactors"); + // if (origin_ptr_ == last_ptr_) return; // reset n_tracks_origin_ lmks_ids_origin_.clear(); - // will emplace a factor (and landmark if needed) for each known feature in last with long tracks (params_tfle_->filter_track_length_th) + // will emplace a factor (and landmark if needed) for each known feature in last with long tracks FactorBasePtrList fac_list; - auto track_ids_last = track_matrix_.trackIds(last_ptr_); + auto track_ids_last = track_matrix_.trackIds(last_ptr_); for (auto track_id : track_ids_last) { - // check track length - if (track_matrix_.trackSize(track_id) < params_tfle_->filter_track_length_th) - continue; + WOLF_DEBUG("Feature ", track_matrix_.feature(track_id, last_ptr_)->id()); + + // not enough long track + if (track_matrix_.trackSize(track_id) < params_tfle_->filter_track_length_th) continue; + + WOLF_DEBUG("Track long enough: ", track_matrix_.trackSize(track_id)); - auto feature = track_matrix_.feature(track_id, last_ptr_); + auto feature = std::static_pointer_cast<FeatureLandmarkExternal>(track_matrix_.feature(track_id, last_ptr_)); + + // Generate a new LANDMARK_ID if not set + WOLF_DEBUG_COND(feature->landmarkId() == 0, "Landmark id not set, getting available id..."); + if (feature->landmarkId() == 0) // id 0 will not be used + { + feature->setLandmarkId(getAvailableLandmarkId()); + } + WOLF_DEBUG("Landmark id: ", feature->landmarkId()); + + // store correspondence EXTERNAL_ID - LANDMARK_ID + if (feature->getExternalId() != -1) + external_id_to_landmark_id_[feature->getExternalId()] = feature->landmarkId(); // get landmark LandmarkBasePtr lmk = getProblem()->getMap()->getLandmark(feature->landmarkId()); - - // emplace landmark - if (not lmk) - lmk = emplaceLandmark(feature); - // modify landmark + // emplace landmark if doesn't exist + WOLF_DEBUG_COND(not lmk, "Landmark does not exist, emplacing..."); + if (not lmk) lmk = emplaceLandmark(feature); + + // modify landmark (add missing state blocks) modifyLandmark(lmk, feature); // emplace factor auto fac = emplaceFactor(feature, lmk); + // TODO: emplace factors for previous tracked features (in keyframes) + + // store tracked landmarks from origin (used by voteForKeyframe()) lmks_ids_origin_.insert(lmk->id()); - if (fac) - fac_list.push_back(fac); + if (fac) fac_list.push_back(fac); } WOLF_DEBUG("ProcessorLandmarkExternal::establishFactors: emplaced ", fac_list.size(), " factors!"); @@ -287,51 +448,38 @@ FactorBasePtr ProcessorLandmarkExternal::emplaceFactor(FeatureBasePtr _feature, { assert(_feature); assert(_landmark); - + // 2D - Relative Position if (getProblem()->getDim() == 2 and (_feature->getMeasurement().size() == 2 or not params_tfle_->use_orientation)) { - return FactorBase::emplace<FactorRelativePosition2dWithExtrinsics>(_feature, - _feature, - _landmark, - shared_from_this(), - params_tfle_->apply_loss_function); + return FactorBase::emplace<FactorRelativePosition2dWithExtrinsics>( + _feature, _feature, _landmark, shared_from_this(), params_tfle_->apply_loss_function); } // 2D - Relative Pose else if (getProblem()->getDim() == 2 and _feature->getMeasurement().size() == 3 and params_tfle_->use_orientation) { - return FactorBase::emplace<FactorRelativePose2dWithExtrinsics>(_feature, - _feature, - _landmark, - shared_from_this(), - params_tfle_->apply_loss_function); + return FactorBase::emplace<FactorRelativePose2dWithExtrinsics>( + _feature, _feature, _landmark, shared_from_this(), params_tfle_->apply_loss_function); } // 3D - Relative Position - else if (getProblem()->getDim() == 3 and (_feature->getMeasurement().size() == 3 or not params_tfle_->use_orientation)) + else if (getProblem()->getDim() == 3 and + (_feature->getMeasurement().size() == 3 or not params_tfle_->use_orientation)) { - return FactorBase::emplace<FactorRelativePosition3dWithExtrinsics>(_feature, - _feature, - _landmark, - shared_from_this(), - params_tfle_->apply_loss_function); + return FactorBase::emplace<FactorRelativePosition3dWithExtrinsics>( + _feature, _feature, _landmark, shared_from_this(), params_tfle_->apply_loss_function); } // 3D - Relative Pose else if (getProblem()->getDim() == 3 and _feature->getMeasurement().size() == 7 and params_tfle_->use_orientation) { - return FactorBase::emplace<FactorRelativePose3dWithExtrinsics>(_feature, - _feature, - _landmark, - shared_from_this(), - params_tfle_->apply_loss_function); + return FactorBase::emplace<FactorRelativePose3dWithExtrinsics>( + _feature, _feature, _landmark, shared_from_this(), params_tfle_->apply_loss_function); } - else + else throw std::runtime_error("ProcessorLandmarkExternal::emplaceFactor unknown case"); - // not reachable - return nullptr; - + return nullptr; // not going to happen } - + LandmarkBasePtr ProcessorLandmarkExternal::emplaceLandmark(FeatureBasePtr _feature) { assert(_feature); @@ -343,7 +491,8 @@ LandmarkBasePtr ProcessorLandmarkExternal::emplaceLandmark(FeatureBasePtr _featu assert(getProblem()->getMap()); if (getProblem()->getMap()->getLandmark(_feature->landmarkId()) != nullptr) - throw std::runtime_error("ProcessorLandmarkExternal::emplaceLandmark: attempting to create an existing landmark"); + throw std::runtime_error( + "ProcessorLandmarkExternal::emplaceLandmark: attempting to create an existing landmark"); LandmarkBasePtr lmk; @@ -352,15 +501,13 @@ LandmarkBasePtr ProcessorLandmarkExternal::emplaceLandmark(FeatureBasePtr _featu { Vector2d frm_p = _feature->getCapture()->getFrame()->getP()->getState(); Vector2d sen_p = _feature->getCapture()->getSensorP()->getState(); - double frm_o = _feature->getCapture()->getFrame()->getO()->getState()(0); - double sen_o = _feature->getCapture()->getSensorO()->getState()(0); - + double frm_o = _feature->getCapture()->getFrame()->getO()->getState()(0); + double sen_o = _feature->getCapture()->getSensorO()->getState()(0); + Vector2d lmk_p = frm_p + Rotation2Dd(frm_o) * (sen_p + Rotation2Dd(sen_o) * _feature->getMeasurement()); - lmk = LandmarkBase::emplace<LandmarkBase>(getProblem()->getMap(), - "LandmarkRelativePosition2d", - std::make_shared<StatePoint2d>(lmk_p), - nullptr); + lmk = LandmarkBase::emplace<LandmarkBase>( + getProblem()->getMap(), "LandmarkRelativePosition2d", std::make_shared<StatePoint2d>(lmk_p), nullptr); lmk->setId(_feature->landmarkId()); } // 2D - Relative Pose @@ -368,11 +515,12 @@ LandmarkBasePtr ProcessorLandmarkExternal::emplaceLandmark(FeatureBasePtr _featu { Vector2d frm_p = _feature->getCapture()->getFrame()->getP()->getState(); Vector2d sen_p = _feature->getCapture()->getSensorP()->getState(); - double frm_o = _feature->getCapture()->getFrame()->getO()->getState()(0); - double sen_o = _feature->getCapture()->getSensorO()->getState()(0); + double frm_o = _feature->getCapture()->getFrame()->getO()->getState()(0); + double sen_o = _feature->getCapture()->getSensorO()->getState()(0); - Vector2d lmk_p = frm_p + Rotation2Dd(frm_o) * (sen_p + Rotation2Dd(sen_o) * _feature->getMeasurement().head<2>()); - double lmk_o = frm_o + sen_o + _feature->getMeasurement()(2); + Vector2d lmk_p = + frm_p + Rotation2Dd(frm_o) * (sen_p + Rotation2Dd(sen_o) * _feature->getMeasurement().head<2>()); + double lmk_o = frm_o + sen_o + _feature->getMeasurement()(2); lmk = LandmarkBase::emplace<LandmarkBase>(getProblem()->getMap(), "LandmarkRelativePose2d", @@ -381,30 +529,29 @@ LandmarkBasePtr ProcessorLandmarkExternal::emplaceLandmark(FeatureBasePtr _featu lmk->setId(_feature->landmarkId()); } // 3D - Relative Position - else if (getProblem()->getDim() == 3 and (_feature->getMeasurement().size() == 3 or not params_tfle_->use_orientation)) + else if (getProblem()->getDim() == 3 and + (_feature->getMeasurement().size() == 3 or not params_tfle_->use_orientation)) { - Vector3d frm_p = _feature->getCapture()->getFrame()->getP()->getState(); - Vector3d sen_p = _feature->getCapture()->getSensorP()->getState(); + Vector3d frm_p = _feature->getCapture()->getFrame()->getP()->getState(); + Vector3d sen_p = _feature->getCapture()->getSensorP()->getState(); Quaterniond frm_o = Quaterniond(Vector4d(_feature->getCapture()->getFrame()->getO()->getState())); Quaterniond sen_o = Quaterniond(Vector4d(_feature->getCapture()->getSensorO()->getState())); Vector3d lmk_p = frm_p + frm_o * (sen_p + sen_o * _feature->getMeasurement()); - lmk = LandmarkBase::emplace<LandmarkBase>(getProblem()->getMap(), - "LandmarkRelativePosition3d", - std::make_shared<StatePoint3d>(lmk_p), - nullptr); + lmk = LandmarkBase::emplace<LandmarkBase>( + getProblem()->getMap(), "LandmarkRelativePosition3d", std::make_shared<StatePoint3d>(lmk_p), nullptr); lmk->setId(_feature->landmarkId()); } // 3D - Relative Pose else if (getProblem()->getDim() == 3 and _feature->getMeasurement().size() == 7 and params_tfle_->use_orientation) { - Vector3d frm_p = _feature->getCapture()->getFrame()->getP()->getState(); - Vector3d sen_p = _feature->getCapture()->getSensorP()->getState(); + Vector3d frm_p = _feature->getCapture()->getFrame()->getP()->getState(); + Vector3d sen_p = _feature->getCapture()->getSensorP()->getState(); Quaterniond frm_o = Quaterniond(Vector4d(_feature->getCapture()->getFrame()->getO()->getState())); Quaterniond sen_o = Quaterniond(Vector4d(_feature->getCapture()->getSensorO()->getState())); - Vector3d lmk_p = frm_p + frm_o * (sen_p + sen_o * _feature->getMeasurement().head<3>()); + Vector3d lmk_p = frm_p + frm_o * (sen_p + sen_o * _feature->getMeasurement().head<3>()); Quaterniond lmk_o = frm_o * sen_o * Quaterniond(_feature->getMeasurement().tail<4>()); lmk = LandmarkBase::emplace<LandmarkBase>(getProblem()->getMap(), @@ -413,14 +560,13 @@ LandmarkBasePtr ProcessorLandmarkExternal::emplaceLandmark(FeatureBasePtr _featu std::make_shared<StateQuaternion>(lmk_o)); lmk->setId(_feature->landmarkId()); } - else + else throw std::runtime_error("ProcessorLandmarkExternal::emplaceLandmark unknown case"); return lmk; } -void ProcessorLandmarkExternal::modifyLandmark(LandmarkBasePtr _landmark, - FeatureBasePtr _feature) +void ProcessorLandmarkExternal::modifyLandmark(LandmarkBasePtr _landmark, FeatureBasePtr _feature) { assert(_feature); assert(_feature->getCapture()); @@ -428,9 +574,8 @@ void ProcessorLandmarkExternal::modifyLandmark(LandmarkBasePtr _landmark, assert(_feature->getCapture()->getSensorP()); assert(_feature->getCapture()->getSensorO()); assert(getProblem()); - - if (not _landmark) - throw std::runtime_error("ProcessorLandmarkExternal::modifyLandmark: null landmark"); + + if (not _landmark) throw std::runtime_error("ProcessorLandmarkExternal::modifyLandmark: null landmark"); // 2D - Relative Position if (getProblem()->getDim() == 2 and (_feature->getMeasurement().size() == 2 or not params_tfle_->use_orientation)) @@ -453,7 +598,8 @@ void ProcessorLandmarkExternal::modifyLandmark(LandmarkBasePtr _landmark, } } // 3D - Relative Position - else if (getProblem()->getDim() == 3 and (_feature->getMeasurement().size() == 3 or not params_tfle_->use_orientation)) + else if (getProblem()->getDim() == 3 and + (_feature->getMeasurement().size() == 3 or not params_tfle_->use_orientation)) { // nothing to do (we assume P already in landmark) return; @@ -472,9 +618,20 @@ void ProcessorLandmarkExternal::modifyLandmark(LandmarkBasePtr _landmark, _landmark->addStateBlock('O', std::make_shared<StateQuaternion>(lmk_o), getProblem()); } } - else + else throw std::runtime_error("ProcessorLandmarkExternal::modifyLandmark unknown case"); -} +} + +SizeStd ProcessorLandmarkExternal::getAvailableLandmarkId() const +{ + auto lmk_list = getProblem()->getMap()->getLandmarkList(); + + SizeStd max_id = 0; + for (auto lmk : lmk_list) + if (lmk->id() > max_id) max_id = lmk->id(); + + return max_id + 1; +} void ProcessorLandmarkExternal::advanceDerived() { @@ -487,11 +644,12 @@ void ProcessorLandmarkExternal::resetDerived() known_features_last_ = std::move(known_features_incoming_); } -} // namespace wolf +} // namespace wolf // Register in the FactoryProcessor #include "core/processor/factory_processor.h" -namespace wolf { +namespace wolf +{ WOLF_REGISTER_PROCESSOR(ProcessorLandmarkExternal) WOLF_REGISTER_PROCESSOR_AUTO(ProcessorLandmarkExternal) -} // namespace wolf +} // namespace wolf diff --git a/test/gtest_processor_landmark_external.cpp b/test/gtest_processor_landmark_external.cpp index ca466ccc1..d6e50e760 100644 --- a/test/gtest_processor_landmark_external.cpp +++ b/test/gtest_processor_landmark_external.cpp @@ -44,58 +44,63 @@ using namespace Eigen; class ProcessorLandmarkExternalTest : public testing::Test { - protected: - int dim; - bool orientation; - TimeStamp t; - double dt; - - ProblemPtr problem; - SolverManagerPtr solver; - SensorBasePtr sensor, sensor_odom; - ProcessorLandmarkExternalPtr processor; - ProcessorMotionPtr processor_motion; - std::vector<LandmarkBasePtr> landmarks; - - // Groundtruth states - VectorComposite state_robot, state_sensor; - std::vector<VectorComposite> state_landmarks; - - virtual void SetUp() {}; - void initProblem(int _dim, - bool _orientation, - double _quality_th, - double _dist_th, - unsigned int _track_length_th, - double _time_span, - bool _add_landmarks); - void randomStep(); - CaptureLandmarksExternalPtr computeCaptureLandmarks() const; - void testConfiguration(int dim, - bool orientation, - double quality_th, - double dist_th, - int track_length, - double time_span, - bool add_landmarks); - void assertVectorComposite(const VectorComposite& v1, const VectorComposite& v2) const; + protected: + int dim; + bool orientation; + int mode; // 0: external ID, 1: external TYPE, 2: nothing, 3: all mixed + TimeStamp t; + double dt; + + ProblemPtr problem; + SolverManagerPtr solver; + SensorBasePtr sensor, sensor_odom; + ProcessorLandmarkExternalPtr processor; + ProcessorMotionPtr processor_motion; + std::vector<LandmarkBasePtr> landmarks; + + // Groundtruth states + VectorComposite state_robot, state_sensor; + std::vector<VectorComposite> state_landmarks; + + virtual void SetUp(){}; + void initProblem(int _dim, + bool _orientation, + int _mode, + double _quality_th, + double _dist_th, + unsigned int _track_length_th, + double _time_span, + bool _init_landmarks); + void randomStep(); + CaptureLandmarksExternalPtr computeCaptureLandmarks() const; + void testConfiguration(int _dim, + bool _orientation, + int _mode, + double _quality_th, + double _dist_th, + int _track_length, + double _time_span, + bool _init_landmarks); + void assertVectorComposite(const VectorComposite& v1, const VectorComposite& v2) const; }; -void ProcessorLandmarkExternalTest::initProblem(int _dim, - bool _orientation, - double _quality_th, - double _dist_th, +void ProcessorLandmarkExternalTest::initProblem(int _dim, + bool _orientation, + int _mode, + double _quality_th, + double _dist_th, unsigned int _track_length_th, - double _time_span, - bool _add_landmarks) + double _time_span, + bool _init_landmarks) { - dim = _dim; + dim = _dim; orientation = _orientation; - t = TimeStamp(0); - dt = 0.1; + mode = _mode; + t = TimeStamp(0); + dt = 0.1; problem = Problem::create("PO", dim); - solver = std::make_shared<SolverCeres>(problem); + solver = std::make_shared<SolverCeres>(problem); // Sensors if (dim == 2) @@ -106,58 +111,57 @@ void ProcessorLandmarkExternalTest::initProblem(int _dim, std::make_shared<StateAngle>(Vector1d::Random() * M_PI), nullptr, 2); - sensor_odom = SensorBase::emplace<SensorOdom2d>(problem->getHardware(), - Vector3d::Zero(), - ParamsSensorOdom2d()); - + sensor_odom = + SensorBase::emplace<SensorOdom2d>(problem->getHardware(), Vector3d::Zero(), ParamsSensorOdom2d()); } else { - sensor = SensorBase::emplace<SensorBase>(problem->getHardware(), + sensor = SensorBase::emplace<SensorBase>(problem->getHardware(), "SensorBase", std::make_shared<StatePoint3d>(Vector3d::Random()), std::make_shared<StateQuaternion>(Vector4d::Random().normalized()), nullptr, 3); - sensor_odom = SensorBase::emplace<SensorOdom3d>(problem->getHardware(), - (Vector7d() << 0,0,0,0,0,0,1).finished(), - ParamsSensorOdom3d()); + sensor_odom = SensorBase::emplace<SensorOdom3d>( + problem->getHardware(), (Vector7d() << 0, 0, 0, 0, 0, 0, 1).finished(), ParamsSensorOdom3d()); } // Processors ParamsProcessorLandmarkExternalPtr params = std::make_shared<ParamsProcessorLandmarkExternal>(); - params->time_tolerance = dt/2; - params->max_new_features = -1; - params->voting_active = true; - params->apply_loss_function = false; - params->use_orientation = orientation; - params->filter_quality_th = _quality_th; - params->match_dist_th = _dist_th; - params->min_features_for_keyframe = 1; - params->new_features_for_keyframe = 1000; - params->filter_track_length_th = _track_length_th; - params->time_span = _time_span; - processor = ProcessorBase::emplace<ProcessorLandmarkExternal>(sensor, params); + params->time_tolerance = dt / 2; + params->max_new_features = -1; + params->voting_active = true; + params->apply_loss_function = false; + params->use_orientation = orientation; + params->filter_quality_th = _quality_th; + params->match_dist_th = _dist_th; + params->check_dist_when_ids_match = false; + params->min_features_for_keyframe = 1; + params->new_features_for_keyframe = 1000; + params->filter_track_length_th = _track_length_th; + params->time_span = _time_span; + processor = ProcessorBase::emplace<ProcessorLandmarkExternal>(sensor, params); if (dim == 2) { - auto params_odom = std::make_shared<ParamsProcessorOdom2d>(); - params_odom->state_getter = true; + auto params_odom = std::make_shared<ParamsProcessorOdom2d>(); + params_odom->state_getter = true; params_odom->voting_active = false; - processor_motion = std::static_pointer_cast<ProcessorMotion>(ProcessorBase::emplace<ProcessorOdom2d>(sensor_odom, - params_odom)); + processor_motion = std::static_pointer_cast<ProcessorMotion>( + ProcessorBase::emplace<ProcessorOdom2d>(sensor_odom, params_odom)); } else { - auto params_odom = std::make_shared<ParamsProcessorOdom3d>(); - params_odom->state_getter = true; + auto params_odom = std::make_shared<ParamsProcessorOdom3d>(); + params_odom->state_getter = true; params_odom->voting_active = false; - processor_motion = std::static_pointer_cast<ProcessorMotion>(ProcessorBase::emplace<ProcessorOdom3d>(sensor_odom, - params_odom)); + processor_motion = std::static_pointer_cast<ProcessorMotion>( + ProcessorBase::emplace<ProcessorOdom3d>(sensor_odom, params_odom)); } // Emplace frame - auto F0 = problem->emplaceFrame(t, (dim == 2 ? VectorXd::Zero(3) : (VectorXd(7) << 0,0,0,0,0,0,1).finished())); + auto F0 = + problem->emplaceFrame(t, (dim == 2 ? VectorXd::Zero(3) : (VectorXd(7) << 0, 0, 0, 0, 0, 0, 1).finished())); F0->fix(); processor->keyFrameCallback(F0); processor_motion->setOrigin(F0); @@ -167,21 +171,19 @@ void ProcessorLandmarkExternalTest::initProblem(int _dim, { LandmarkBasePtr lmk; if (dim == 2) - lmk = LandmarkBase::emplace<LandmarkBase>(_add_landmarks ? problem->getMap() : nullptr, - "LandmarkExternal", - std::make_shared<StatePoint2d>(Vector2d::Random() * 10), - (orientation ? - std::make_shared<StateAngle>(Vector1d::Random() * M_PI) : - nullptr)); - - else - lmk = LandmarkBase::emplace<LandmarkBase>(_add_landmarks ? problem->getMap() : nullptr, - "LandmarkExternal", - std::make_shared<StatePoint3d>(Vector3d::Random() * 10), - (orientation ? - std::make_shared<StateQuaternion>(Vector4d::Random().normalized()) : - nullptr)); - lmk->setId(i); + lmk = LandmarkBase::emplace<LandmarkBase>( + _init_landmarks ? problem->getMap() : nullptr, + "LandmarkExternal", + std::make_shared<StatePoint2d>(Vector2d::Random() * 10), + (orientation ? std::make_shared<StateAngle>(Vector1d::Random() * M_PI) : nullptr)); + + else + lmk = LandmarkBase::emplace<LandmarkBase>( + _init_landmarks ? problem->getMap() : nullptr, + "LandmarkExternal", + std::make_shared<StatePoint3d>(Vector3d::Random() * 10), + (orientation ? std::make_shared<StateQuaternion>(Vector4d::Random().normalized()) : nullptr)); + lmk->setId(i + 1); landmarks.push_back(lmk); state_landmarks.push_back(lmk->getState()); } @@ -198,7 +200,7 @@ void ProcessorLandmarkExternalTest::randomStep() MatrixXd delta_cov; if (dim == 2) { - delta = Vector2d::Random() * 0.1; + delta = Vector2d::Random() * 0.1; delta_cov = Matrix2d::Identity() * 0.1; } else @@ -223,10 +225,13 @@ CaptureLandmarksExternalPtr ProcessorLandmarkExternalTest::computeCaptureLandmar for (auto i = 0; i < landmarks.size(); i++) { // compute detection - VectorXd meas(orientation?(dim==2?3:7):(dim==2?2:3)); + VectorXd meas(orientation ? (dim == 2 ? 3 : 7) : (dim == 2 ? 2 : 3)); if (dim == 2) { - meas.head(2) = Rotation2Dd(-state_sensor.at('O')(0))*(Rotation2Dd(-state_robot.at('O')(0))*(state_landmarks.at(i).at('P') - state_robot.at('P')) - state_sensor.at('P')); + meas.head(2) = + Rotation2Dd(-state_sensor.at('O')(0)) * + (Rotation2Dd(-state_robot.at('O')(0)) * (state_landmarks.at(i).at('P') - state_robot.at('P')) - + state_sensor.at('P')); if (orientation) meas(2) = state_landmarks.at(i).at('O')(0) - state_robot.at('O')(0) - state_sensor.at('O')(0); } @@ -235,38 +240,51 @@ CaptureLandmarksExternalPtr ProcessorLandmarkExternalTest::computeCaptureLandmar auto q_sensor = Quaterniond(Vector4d(state_sensor.at('O'))); auto q_robot = Quaterniond(Vector4d(state_robot.at('O'))); - meas.head(3) = q_sensor.conjugate() * (q_robot.conjugate() * (state_landmarks.at(i).at('P') - state_robot.at('P')) - state_sensor.at('P')); + meas.head(3) = + q_sensor.conjugate() * + (q_robot.conjugate() * (state_landmarks.at(i).at('P') - state_robot.at('P')) - state_sensor.at('P')); if (orientation) - meas.tail(4) = (q_sensor.conjugate() * q_robot.conjugate() * Quaterniond(Vector4d(state_landmarks.at(i).at('O')))).coeffs(); + meas.tail(4) = + (q_sensor.conjugate() * q_robot.conjugate() * Quaterniond(Vector4d(state_landmarks.at(i).at('O')))) + .coeffs(); } // cov MatrixXd cov = MatrixXd::Identity(meas.size(), meas.size()); - if (orientation and dim != 2) - cov = MatrixXd::Identity(6, 6); + if (orientation and dim != 2) cov = MatrixXd::Identity(6, 6); // quality - double quality = (double) i / (double) (landmarks.size()-1); // increasing from 0 to 1 + double quality = (double)i / (double)(landmarks.size() - 1); // increasing from 0 to 1 // add detection - cap->addDetection(landmarks.at(i)->id(), meas, cov, quality ); + // with ID + if (mode == 0 or (mode == 3 and i % 3 == 0)) cap->addDetection(landmarks.at(i)->id(), -1, meas, cov, quality); + // with TYPE + else if (mode == 1 or (mode == 3 and i % 3 == 1)) + cap->addDetection(-1, landmarks.at(i)->id(), meas, cov, quality); + // with nothing + else if (mode == 2 or (mode == 3 and i % 3 == 2)) + cap->addDetection(-1, -1, meas, cov, quality); } return cap; } -void ProcessorLandmarkExternalTest::testConfiguration(int dim, - bool orientation, - double quality_th, - double dist_th, - int track_length, - double time_span, - bool add_landmarks) +void ProcessorLandmarkExternalTest::testConfiguration(int _dim, + bool _orientation, + int _mode, + double _quality_th, + double _dist_th, + int _track_length, + double _time_span, + bool _init_landmarks) { - initProblem(dim, orientation, quality_th, dist_th, track_length, time_span, add_landmarks); + initProblem(_dim, _orientation, _mode, _quality_th, _dist_th, _track_length, _time_span, _init_landmarks); + + auto n_keyframes = problem->getTrajectory()->size(); ASSERT_TRUE(problem->check()); - for (auto i = 0; i<10; i++) + for (auto i = 0; i < 10; i++) { WOLF_INFO("\n================= STEP ", i, " t = ", t, " ================="); @@ -277,73 +295,90 @@ void ProcessorLandmarkExternalTest::testConfiguration(int dim, // process detections cap->process(); ASSERT_TRUE(problem->check()); - problem->print(4,1,1,1); + problem->print(4, 1, 1, 1); // CHECKS FactorBasePtrList fac_list; problem->getTrajectory()->getFactorList(fac_list); // should emplace KF in last? - bool any_active_track = quality_th <=1 and i >= track_length-1; - bool should_emplace_KF = t-dt > time_span and any_active_track; - WOLF_INFO("should emplace KF: ", should_emplace_KF, " t-dt = ", t-dt, " time_span = ", time_span, " track_length-1 = ", track_length-1); - + bool any_active_track = _quality_th <= 1 and i >= _track_length - 1; + bool should_emplace_KF = (t - dt > _time_span and any_active_track); + bool should_emplace_factors = i == 1 or should_emplace_KF; + WOLF_INFO("should emplace KF: ", + should_emplace_KF, + "should emplace factors: ", + should_emplace_factors, + " i = ", + i, + " t-dt = ", + t - dt, + " time_span = ", + _time_span, + " track_length-1 = ", + _track_length - 1); + + // Check voted&emplaced a keyframe if (should_emplace_KF) - { - // voted for keyframe - ASSERT_TRUE(problem->getTrajectory()->size() > 1); - - // emplaced factors + { + ASSERT_EQ(problem->getTrajectory()->size(), n_keyframes + 1); + n_keyframes++; + } + else + { + ASSERT_EQ(problem->getTrajectory()->size(), n_keyframes); + } + + // Check emplaced factors and landmarks + if (should_emplace_factors) + { ASSERT_FALSE(fac_list.empty()); - + // factors' type for (auto fac : fac_list) { if (fac->getProcessor() == processor) { - ASSERT_EQ(fac->getType(), std::string("FactorRelative") + - (orientation ? "Pose" : "Position") + - (dim == 2 ? "2d" : "3d") + - "WithExtrinsics"); + ASSERT_EQ(fac->getType(), + std::string("FactorRelative") + (orientation ? "Pose" : "Position") + + (dim == 2 ? "2d" : "3d") + "WithExtrinsics"); } } // landmarks created by processor - if (not add_landmarks) + if (not _init_landmarks) { auto landmarks_map = problem->getMap()->getLandmarkList(); - // amount of landmarks due to quality filtering of detections - auto n_landmarks = (quality_th <= 0 ? 3 : (quality_th <= 0.5 ? 2 : (quality_th <= 1 ? 1 : 0))); + // amount of landmarks according to quality filtering of detections + auto n_landmarks = (_quality_th <= 0 ? 3 : (_quality_th <= 0.5 ? 2 : (_quality_th <= 1 ? 1 : 0))); ASSERT_EQ(landmarks_map.size(), n_landmarks); // check state correctly initialized for (auto lmk_map : landmarks_map) { ASSERT_TRUE(lmk_map->id() < landmarks.size()); - ASSERT_EQ(lmk_map->id(), landmarks.at(lmk_map->id())->id()); + ASSERT_EQ(lmk_map->id(), landmarks.at(lmk_map->id() - 1)->id()); assertVectorComposite(lmk_map->getState(), state_landmarks.at(lmk_map->id())); } } } else { - // didn't vote for keyframe - ASSERT_FALSE(problem->getTrajectory()->size() > 1); // no factors emplaced ASSERT_TRUE(fac_list.empty()); + // no landmarks created yet (if not added by the test) - ASSERT_EQ(problem->getMap()->getLandmarkList().empty(), not add_landmarks); + ASSERT_EQ(problem->getMap()->getLandmarkList().empty(), not _init_landmarks); } // step with random movement - t+=dt; + t += dt; randomStep(); // solve - if (should_emplace_KF) + if (should_emplace_factors) { // perturb landmarks - for (auto lmk : problem->getMap()->getLandmarkList()) - lmk->perturb(); + for (auto lmk : problem->getMap()->getLandmarkList()) lmk->perturb(); // fix frame and extrinsics sensor->fix(); @@ -353,9 +388,7 @@ void ProcessorLandmarkExternalTest::testConfiguration(int dim, auto report = solver->solve(SolverManager::ReportVerbosity::FULL); WOLF_INFO(report); - // check values - //assertVectorComposite(sensor->getState("PO"), state_sensor); - //assertVectorComposite(problem->getState("PO"), state_robot); + // check values for (auto lmk_map : problem->getMap()->getLandmarkList()) { assertVectorComposite(lmk_map->getState(), state_landmarks.at(lmk_map->id())); @@ -386,141 +419,584 @@ void ProcessorLandmarkExternalTest::assertVectorComposite(const VectorComposite& } // / TESTS ////////////////////////////////////////// -TEST_F(ProcessorLandmarkExternalTest, P_2d_existing_lmks) -{ - testConfiguration(2, //int dim - false, //bool orientation - 0, //double quality_th - 1e6, //double dist_th - 6, //int track_length - 4.5*dt, //double time_span - true); //bool add_landmarks -} - -TEST_F(ProcessorLandmarkExternalTest, P_2d_no_lmks) -{ - testConfiguration(2, //int dim - false, //bool orientation - 0, //double quality_th - 1e6, //double dist_th - 2, //int track_length - 4.5*dt, //double time_span - false); //bool add_landmarks -} - -TEST_F(ProcessorLandmarkExternalTest, P_2d_no_lmks_quality) -{ - testConfiguration(2, //int dim - false, //bool orientation - 0.3, //double quality_th - 1e6, //double dist_th - 6, //int track_length - 4.5*dt, //double time_span - false); //bool add_landmarks -} - -TEST_F(ProcessorLandmarkExternalTest, PO_2d_existing_lmks) -{ - testConfiguration(2, //int dim - true, //bool orientation - 0, //double quality_th - 1e6, //double dist_th - 3, //int track_length - 4.5*dt, //double time_span - true); //bool add_landmarks -} - -TEST_F(ProcessorLandmarkExternalTest, PO_2d_no_lmks) -{ - testConfiguration(2, //int dim - true, //bool orientation - 0, //double quality_th - 1e6, //double dist_th - 1, //int track_length - 4.5*dt, //double time_span - false); //bool add_landmarks -} - -TEST_F(ProcessorLandmarkExternalTest, PO_2d_no_lmks_quality) -{ - testConfiguration(2, //int dim - true, //bool orientation - 0.3, //double quality_th - 1e6, //double dist_th - 0, //int track_length - 4.5*dt, //double time_span - false); //bool add_landmarks -} - -TEST_F(ProcessorLandmarkExternalTest, P_3d_existing_lmks) +TEST_F(ProcessorLandmarkExternalTest, P_2d_existing_lmks_id) { - testConfiguration(3, //int dim - false, //bool orientation - 0, //double quality_th - 1e6, //double dist_th - 7, //int track_length - 4.5*dt, //double time_span - true); //bool add_landmarks + testConfiguration(2, // int dim + false, // bool orientation + 0, // int mode + 0, // double quality_th + 1e6, // double dist_th + 6, // int track_length + 4.5 * dt, // double time_span + true); // bool init_landmarks } -TEST_F(ProcessorLandmarkExternalTest, P_3d_no_lmks) +// TEST_F(ProcessorLandmarkExternalTest, P_2d_existing_lmks_type) +// { +// testConfiguration(2, // int dim +// false, // bool orientation +// 1, // int mode +// 0, // double quality_th +// 1e6, // double dist_th +// 6, // int track_length +// 4.5 * dt, // double time_span +// true); // bool init_landmarks +// } + +// TEST_F(ProcessorLandmarkExternalTest, P_2d_existing_lmks_nothing) +// { +// testConfiguration(2, // int dim +// false, // bool orientation +// 2, // int mode +// 0, // double quality_th +// 1e6, // double dist_th +// 6, // int track_length +// 4.5 * dt, // double time_span +// true); // bool init_landmarks +// } + +// TEST_F(ProcessorLandmarkExternalTest, P_2d_existing_lmks_mixed) +// { +// testConfiguration(2, // int dim +// false, // bool orientation +// 3, // int mode +// 0, // double quality_th +// 1e6, // double dist_th +// 6, // int track_length +// 4.5 * dt, // double time_span +// true); // bool init_landmarks +// } + +TEST_F(ProcessorLandmarkExternalTest, P_2d_no_lmks_id) { - testConfiguration(3, //int dim - false, //bool orientation - 0, //double quality_th - 1e6, //double dist_th - 53, //int track_length - 4.5*dt, //double time_span - false); //bool add_landmarks + testConfiguration(2, // int dim + false, // bool orientation + 0, // int mode + 0, // double quality_th + 1e6, // double dist_th + 2, // int track_length + 4.5 * dt, // double time_span + false); // bool init_landmarks } -TEST_F(ProcessorLandmarkExternalTest, P_3d_no_lmks_quality) -{ - testConfiguration(3, //int dim - false, //bool orientation - 0.3, //double quality_th - 1e6, //double dist_th - 2, //int track_length - 4.5*dt, //double time_span - false); //bool add_landmarks -} - -TEST_F(ProcessorLandmarkExternalTest, PO_3d_existing_lmks) -{ - testConfiguration(3, //int dim - true, //bool orientation - 0, //double quality_th - 1e6, //double dist_th - 1, //int track_length - 4.5*dt, //double time_span - true); //bool add_landmarks -} - -TEST_F(ProcessorLandmarkExternalTest, PO_3d_no_lmks) -{ - testConfiguration(3, //int dim - true, //bool orientation - 0, //double quality_th - 1e6, //double dist_th - 4, //int track_length - 4.5*dt, //double time_span - false); //bool add_landmarks -} - -TEST_F(ProcessorLandmarkExternalTest, PO_3d_no_lmks_quality) -{ - testConfiguration(3, //int dim - true, //bool orientation - 0.2, //double quality_th - 1e6, //double dist_th - 5, //int track_length - 4.5*dt, //double time_span - false); //bool add_landmarks -} - - -int main(int argc, char **argv) +// TEST_F(ProcessorLandmarkExternalTest, P_2d_no_lmks_type) +// { +// testConfiguration(2, // int dim +// false, // bool orientation +// 1, // int mode +// 0, // double quality_th +// 1e6, // double dist_th +// 2, // int track_length +// 4.5 * dt, // double time_span +// false); // bool init_landmarks +// } + +// TEST_F(ProcessorLandmarkExternalTest, P_2d_no_lmks_nothing) +// { +// testConfiguration(2, // int dim +// false, // bool orientation +// 2, // int mode +// 0, // double quality_th +// 1e6, // double dist_th +// 2, // int track_length +// 4.5 * dt, // double time_span +// false); // bool init_landmarks +// } + +// TEST_F(ProcessorLandmarkExternalTest, P_2d_no_lmks_mixed) +// { +// testConfiguration(2, // int dim +// false, // bool orientation +// 3, // int mode +// 0, // double quality_th +// 1e6, // double dist_th +// 2, // int track_length +// 4.5 * dt, // double time_span +// false); // bool init_landmarks +// } + +// TEST_F(ProcessorLandmarkExternalTest, P_2d_no_lmks_quality_id) +// { +// testConfiguration(2, // int dim +// false, // bool orientation +// 0, // int mode +// 0.3, // double quality_th +// 1e6, // double dist_th +// 6, // int track_length +// 4.5 * dt, // double time_span +// false); // bool init_landmarks +// } + +// TEST_F(ProcessorLandmarkExternalTest, P_2d_no_lmks_quality_type) +// { +// testConfiguration(2, // int dim +// false, // bool orientation +// 1, // int mode +// 0.3, // double quality_th +// 1e6, // double dist_th +// 6, // int track_length +// 4.5 * dt, // double time_span +// false); // bool init_landmarks +// } + +// TEST_F(ProcessorLandmarkExternalTest, P_2d_no_lmks_quality_nothing) +// { +// testConfiguration(2, // int dim +// false, // bool orientation +// 2, // int mode +// 0.3, // double quality_th +// 1e6, // double dist_th +// 6, // int track_length +// 4.5 * dt, // double time_span +// false); // bool init_landmarks +// } + +// TEST_F(ProcessorLandmarkExternalTest, P_2d_no_lmks_quality_mixed) +// { +// testConfiguration(2, // int dim +// false, // bool orientation +// 3, // int mode +// 0.3, // double quality_th +// 1e6, // double dist_th +// 6, // int track_length +// 4.5 * dt, // double time_span +// false); // bool init_landmarks +// } + +// TEST_F(ProcessorLandmarkExternalTest, PO_2d_existing_lmks_id) +// { +// testConfiguration(2, // int dim +// true, // bool orientation +// 0, // int mode +// 0, // double quality_th +// 1e6, // double dist_th +// 3, // int track_length +// 4.5 * dt, // double time_span +// true); // bool init_landmarks +// } + +// TEST_F(ProcessorLandmarkExternalTest, PO_2d_existing_lmks_type) +// { +// testConfiguration(2, // int dim +// true, // bool orientation +// 1, // int mode +// 0, // double quality_th +// 1e6, // double dist_th +// 3, // int track_length +// 4.5 * dt, // double time_span +// true); // bool init_landmarks +// } + +// TEST_F(ProcessorLandmarkExternalTest, PO_2d_existing_lmks_nothing) +// { +// testConfiguration(2, // int dim +// true, // bool orientation +// 2, // int mode +// 0, // double quality_th +// 1e6, // double dist_th +// 3, // int track_length +// 4.5 * dt, // double time_span +// true); // bool init_landmarks +// } + +// TEST_F(ProcessorLandmarkExternalTest, PO_2d_existing_lmks_mixed) +// { +// testConfiguration(2, // int dim +// true, // bool orientation +// 3, // int mode +// 0, // double quality_th +// 1e6, // double dist_th +// 3, // int track_length +// 4.5 * dt, // double time_span +// true); // bool init_landmarks +// } + +// TEST_F(ProcessorLandmarkExternalTest, PO_2d_no_lmks_id) +// { +// testConfiguration(2, // int dim +// true, // bool orientation +// 0, // int mode +// 0, // double quality_th +// 1e6, // double dist_th +// 1, // int track_length +// 4.5 * dt, // double time_span +// false); // bool init_landmarks +// } + +// TEST_F(ProcessorLandmarkExternalTest, PO_2d_no_lmks_type) +// { +// testConfiguration(2, // int dim +// true, // bool orientation +// 1, // int mode +// 0, // double quality_th +// 1e6, // double dist_th +// 1, // int track_length +// 4.5 * dt, // double time_span +// false); // bool init_landmarks +// } + +// TEST_F(ProcessorLandmarkExternalTest, PO_2d_no_lmks_nothing) +// { +// testConfiguration(2, // int dim +// true, // bool orientation +// 2, // int mode +// 0, // double quality_th +// 1e6, // double dist_th +// 1, // int track_length +// 4.5 * dt, // double time_span +// false); // bool init_landmarks +// } + +// TEST_F(ProcessorLandmarkExternalTest, PO_2d_no_lmks_mixed) +// { +// testConfiguration(2, // int dim +// true, // bool orientation +// 3, // int mode +// 0, // double quality_th +// 1e6, // double dist_th +// 1, // int track_length +// 4.5 * dt, // double time_span +// false); // bool init_landmarks +// } + +// TEST_F(ProcessorLandmarkExternalTest, PO_2d_no_lmks_quality_id) +// { +// testConfiguration(2, // int dim +// true, // bool orientation +// 0, // int mode +// 0.3, // double quality_th +// 1e6, // double dist_th +// 0, // int track_length +// 4.5 * dt, // double time_span +// false); // bool init_landmarks +// } + +// TEST_F(ProcessorLandmarkExternalTest, PO_2d_no_lmks_quality_type) +// { +// testConfiguration(2, // int dim +// true, // bool orientation +// 1, // int mode +// 0.3, // double quality_th +// 1e6, // double dist_th +// 0, // int track_length +// 4.5 * dt, // double time_span +// false); // bool init_landmarks +// } + +// TEST_F(ProcessorLandmarkExternalTest, PO_2d_no_lmks_quality_nothing) +// { +// testConfiguration(2, // int dim +// true, // bool orientation +// 2, // int mode +// 0.3, // double quality_th +// 1e6, // double dist_th +// 0, // int track_length +// 4.5 * dt, // double time_span +// false); // bool init_landmarks +// } + +// TEST_F(ProcessorLandmarkExternalTest, PO_2d_no_lmks_quality_mixed) +// { +// testConfiguration(2, // int dim +// true, // bool orientation +// 3, // int mode +// 0.3, // double quality_th +// 1e6, // double dist_th +// 0, // int track_length +// 4.5 * dt, // double time_span +// false); // bool init_landmarks +// } + +// TEST_F(ProcessorLandmarkExternalTest, P_3d_existing_lmks_id) +// { +// testConfiguration(3, // int dim +// false, // bool orientation +// 0, // int mode +// 0, // double quality_th +// 1e6, // double dist_th +// 7, // int track_length +// 4.5 * dt, // double time_span +// true); // bool init_landmarks +// } + +// TEST_F(ProcessorLandmarkExternalTest, P_3d_existing_lmks_type) +// { +// testConfiguration(3, // int dim +// false, // bool orientation +// 1, // int mode +// 0, // double quality_th +// 1e6, // double dist_th +// 7, // int track_length +// 4.5 * dt, // double time_span +// true); // bool init_landmarks +// } + +// TEST_F(ProcessorLandmarkExternalTest, P_3d_existing_lmks_nothing) +// { +// testConfiguration(3, // int dim +// false, // bool orientation +// 2, // int mode +// 0, // double quality_th +// 1e6, // double dist_th +// 7, // int track_length +// 4.5 * dt, // double time_span +// true); // bool init_landmarks +// } + +// TEST_F(ProcessorLandmarkExternalTest, P_3d_existing_lmks_mixed) +// { +// testConfiguration(3, // int dim +// false, // bool orientation +// 3, // int mode +// 0, // double quality_th +// 1e6, // double dist_th +// 7, // int track_length +// 4.5 * dt, // double time_span +// true); // bool init_landmarks +// } + +// TEST_F(ProcessorLandmarkExternalTest, P_3d_no_lmks_id) +// { +// testConfiguration(3, // int dim +// false, // bool orientation +// 0, // int mode +// 0, // double quality_th +// 1e6, // double dist_th +// 53, // int track_length +// 4.5 * dt, // double time_span +// false); // bool init_landmarks +// } + +// TEST_F(ProcessorLandmarkExternalTest, P_3d_no_lmks_type) +// { +// testConfiguration(3, // int dim +// false, // bool orientation +// 1, // int mode +// 0, // double quality_th +// 1e6, // double dist_th +// 53, // int track_length +// 4.5 * dt, // double time_span +// false); // bool init_landmarks +// } + +// TEST_F(ProcessorLandmarkExternalTest, P_3d_no_lmks_nothing) +// { +// testConfiguration(3, // int dim +// false, // bool orientation +// 2, // int mode +// 0, // double quality_th +// 1e6, // double dist_th +// 53, // int track_length +// 4.5 * dt, // double time_span +// false); // bool init_landmarks +// } + +// TEST_F(ProcessorLandmarkExternalTest, P_3d_no_lmks_mixed) +// { +// testConfiguration(3, // int dim +// false, // bool orientation +// 3, // int mode +// 0, // double quality_th +// 1e6, // double dist_th +// 53, // int track_length +// 4.5 * dt, // double time_span +// false); // bool init_landmarks +// } + +// TEST_F(ProcessorLandmarkExternalTest, P_3d_no_lmks_quality_id) +// { +// testConfiguration(3, // int dim +// false, // bool orientation +// 0, // int mode +// 0.3, // double quality_th +// 1e6, // double dist_th +// 2, // int track_length +// 4.5 * dt, // double time_span +// false); // bool init_landmarks +// } + +// TEST_F(ProcessorLandmarkExternalTest, P_3d_no_lmks_quality_type) +// { +// testConfiguration(3, // int dim +// false, // bool orientation +// 1, // int mode +// 0.3, // double quality_th +// 1e6, // double dist_th +// 2, // int track_length +// 4.5 * dt, // double time_span +// false); // bool init_landmarks +// } + +// TEST_F(ProcessorLandmarkExternalTest, P_3d_no_lmks_quality_nothing) +// { +// testConfiguration(3, // int dim +// false, // bool orientation +// 2, // int mode +// 0.3, // double quality_th +// 1e6, // double dist_th +// 2, // int track_length +// 4.5 * dt, // double time_span +// false); // bool init_landmarks +// } + +// TEST_F(ProcessorLandmarkExternalTest, P_3d_no_lmks_quality_mixed) +// { +// testConfiguration(3, // int dim +// false, // bool orientation +// 3, // int mode +// 0.3, // double quality_th +// 1e6, // double dist_th +// 2, // int track_length +// 4.5 * dt, // double time_span +// false); // bool init_landmarks +// } + +// TEST_F(ProcessorLandmarkExternalTest, PO_3d_existing_lmks_id) +// { +// testConfiguration(3, // int dim +// true, // bool orientation +// 0, // int mode +// 0, // double quality_th +// 1e6, // double dist_th +// 1, // int track_length +// 4.5 * dt, // double time_span +// true); // bool init_landmarks +// } + +// TEST_F(ProcessorLandmarkExternalTest, PO_3d_existing_lmks_type) +// { +// testConfiguration(3, // int dim +// true, // bool orientation +// 1, // int mode +// 0, // double quality_th +// 1e6, // double dist_th +// 1, // int track_length +// 4.5 * dt, // double time_span +// true); // bool init_landmarks +// } + +// TEST_F(ProcessorLandmarkExternalTest, PO_3d_existing_lmks_nothing) +// { +// testConfiguration(3, // int dim +// true, // bool orientation +// 2, // int mode +// 0, // double quality_th +// 1e6, // double dist_th +// 1, // int track_length +// 4.5 * dt, // double time_span +// true); // bool init_landmarks +// } + +// TEST_F(ProcessorLandmarkExternalTest, PO_3d_existing_lmks_mixed) +// { +// testConfiguration(3, // int dim +// true, // bool orientation +// 3, // int mode +// 0, // double quality_th +// 1e6, // double dist_th +// 1, // int track_length +// 4.5 * dt, // double time_span +// true); // bool init_landmarks +// } + +// TEST_F(ProcessorLandmarkExternalTest, PO_3d_no_lmks_id) +// { +// testConfiguration(3, // int dim +// true, // bool orientation +// 0, // int mode +// 0, // double quality_th +// 1e6, // double dist_th +// 4, // int track_length +// 4.5 * dt, // double time_span +// false); // bool init_landmarks +// } + +// TEST_F(ProcessorLandmarkExternalTest, PO_3d_no_lmks_type) +// { +// testConfiguration(3, // int dim +// true, // bool orientation +// 1, // int mode +// 0, // double quality_th +// 1e6, // double dist_th +// 4, // int track_length +// 4.5 * dt, // double time_span +// false); // bool init_landmarks +// } + +// TEST_F(ProcessorLandmarkExternalTest, PO_3d_no_lmks_nothing) +// { +// testConfiguration(3, // int dim +// true, // bool orientation +// 2, // int mode +// 0, // double quality_th +// 1e6, // double dist_th +// 4, // int track_length +// 4.5 * dt, // double time_span +// false); // bool init_landmarks +// } + +// TEST_F(ProcessorLandmarkExternalTest, PO_3d_no_lmks_mixed) +// { +// testConfiguration(3, // int dim +// true, // bool orientation +// 3, // int mode +// 0, // double quality_th +// 1e6, // double dist_th +// 4, // int track_length +// 4.5 * dt, // double time_span +// false); // bool init_landmarks +// } + +// TEST_F(ProcessorLandmarkExternalTest, PO_3d_no_lmks_quality_id) +// { +// testConfiguration(3, // int dim +// true, // bool orientation +// 0, // int mode +// 0.2, // double quality_th +// 1e6, // double dist_th +// 5, // int track_length +// 4.5 * dt, // double time_span +// false); // bool init_landmarks +// } + +// TEST_F(ProcessorLandmarkExternalTest, PO_3d_no_lmks_quality_type) +// { +// testConfiguration(3, // int dim +// true, // bool orientation +// 1, // int mode +// 0.2, // double quality_th +// 1e6, // double dist_th +// 5, // int track_length +// 4.5 * dt, // double time_span +// false); // bool init_landmarks +// } + +// TEST_F(ProcessorLandmarkExternalTest, PO_3d_no_lmks_quality_nothing) +// { +// testConfiguration(3, // int dim +// true, // bool orientation +// 2, // int mode +// 0.2, // double quality_th +// 1e6, // double dist_th +// 5, // int track_length +// 4.5 * dt, // double time_span +// false); // bool init_landmarks +// } + +// TEST_F(ProcessorLandmarkExternalTest, PO_3d_no_lmks_quality_mixed) +// { +// testConfiguration(3, // int dim +// true, // bool orientation +// 3, // int mode +// 0.2, // double quality_th +// 1e6, // double dist_th +// 5, // int track_length +// 4.5 * dt, // double time_span +// false); // bool init_landmarks +// } + +int main(int argc, char** argv) { - testing::InitGoogleTest(&argc, argv); - return RUN_ALL_TESTS(); + testing::InitGoogleTest(&argc, argv); + return RUN_ALL_TESTS(); } -- GitLab