diff --git a/CMakeLists.txt b/CMakeLists.txt index cab800a231b74a05eb9c466e0ec5d508ca561918..98de6dbd9bfb7521238c7c784b077456b35b5629 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -285,7 +285,11 @@ SET(HDRS_SOLVER include/core/solver/solver_manager.h include/core/solver/solver_factory.h ) - +SET(HDRS_TREE_MANAGER + include/core/tree_manager/factory_tree_manager.h + include/core/tree_manager/tree_manager_base.h + include/core/tree_manager/tree_manager_sliding_window.h + ) SET(HDRS_YAML include/core/yaml/parser_yaml.h include/core/yaml/yaml_conversion.h @@ -371,6 +375,9 @@ SET(SRCS_SENSOR SET(SRCS_SOLVER src/solver/solver_manager.cpp ) +SET(SRCS_TREE_MANAGER + src/tree_manager/tree_manager_sliding_window.cpp + ) SET(SRCS_YAML src/yaml/parser_yaml.cpp src/yaml/processor_odom_3d_yaml.cpp @@ -431,6 +438,7 @@ ADD_LIBRARY(${PROJECT_NAME} ${SRCS_SOLVER} ${SRCS_STATE_BLOCK} ${SRCS_TRAJECTORY} + ${SRCS_TREE_MANAGER} ${SRCS_UTILS} ${SRCS_WRAPPER} ${SRCS_YAML} @@ -471,44 +479,46 @@ INSTALL(TARGETS ${PROJECT_NAME} EXPORT ${PROJECT_NAME}Targets install(EXPORT ${PROJECT_NAME}Targets DESTINATION lib/cmake/${PROJECT_NAME}) #install headers -INSTALL(FILES ${HDRS_MATH} - DESTINATION include/iri-algorithms/wolf/plugin_core/core/math) -INSTALL(FILES ${HDRS_UTILS} - DESTINATION include/iri-algorithms/wolf/plugin_core/core/utils) -INSTALL(FILES ${HDRS_PROBLEM} - DESTINATION include/iri-algorithms/wolf/plugin_core/core/problem) -INSTALL(FILES ${HDRS_HARDWARE} - DESTINATION include/iri-algorithms/wolf/plugin_core/core/hardware) -INSTALL(FILES ${HDRS_TRAJECTORY} - DESTINATION include/iri-algorithms/wolf/plugin_core/core/trajectory) -INSTALL(FILES ${HDRS_MAP} - DESTINATION include/iri-algorithms/wolf/plugin_core/core/map) -INSTALL(FILES ${HDRS_FRAME} - DESTINATION include/iri-algorithms/wolf/plugin_core/core/frame) -INSTALL(FILES ${HDRS_STATE_BLOCK} - DESTINATION include/iri-algorithms/wolf/plugin_core/core/state_block) -INSTALL(FILES ${HDRS_COMMON} - DESTINATION include/iri-algorithms/wolf/plugin_core/core/common) INSTALL(FILES ${HDRS_CAPTURE} DESTINATION include/iri-algorithms/wolf/plugin_core/core/capture) +INSTALL(FILES ${HDRS_COMMON} + DESTINATION include/iri-algorithms/wolf/plugin_core/core/common) INSTALL(FILES ${HDRS_FACTOR} DESTINATION include/iri-algorithms/wolf/plugin_core/core/factor) INSTALL(FILES ${HDRS_FEATURE} DESTINATION include/iri-algorithms/wolf/plugin_core/core/feature) -INSTALL(FILES ${HDRS_SENSOR} - DESTINATION include/iri-algorithms/wolf/plugin_core/core/sensor) -INSTALL(FILES ${HDRS_PROCESSOR} - DESTINATION include/iri-algorithms/wolf/plugin_core/core/processor) +INSTALL(FILES ${HDRS_FRAME} + DESTINATION include/iri-algorithms/wolf/plugin_core/core/frame) +INSTALL(FILES ${HDRS_HARDWARE} + DESTINATION include/iri-algorithms/wolf/plugin_core/core/hardware) INSTALL(FILES ${HDRS_LANDMARK} DESTINATION include/iri-algorithms/wolf/plugin_core/core/landmark) -INSTALL(FILES ${HDRS_WRAPPER} - DESTINATION include/iri-algorithms/wolf/plugin_core/core/ceres_wrapper) -INSTALL(FILES ${HDRS_SOLVER_SUITESPARSE} - DESTINATION include/iri-algorithms/wolf/plugin_core/core/solver_suitesparse) -INSTALL(FILES ${HDRS_SOLVER} - DESTINATION include/iri-algorithms/wolf/plugin_core/core/solver) +INSTALL(FILES ${HDRS_MAP} + DESTINATION include/iri-algorithms/wolf/plugin_core/core/map) +INSTALL(FILES ${HDRS_MATH} + DESTINATION include/iri-algorithms/wolf/plugin_core/core/math) +INSTALL(FILES ${HDRS_PROBLEM} + DESTINATION include/iri-algorithms/wolf/plugin_core/core/problem) +INSTALL(FILES ${HDRS_PROCESSOR} + DESTINATION include/iri-algorithms/wolf/plugin_core/core/processor) +INSTALL(FILES ${HDRS_SENSOR} + DESTINATION include/iri-algorithms/wolf/plugin_core/core/sensor) INSTALL(FILES ${HDRS_SERIALIZATION} DESTINATION include/iri-algorithms/wolf/plugin_core/core/serialization) +INSTALL(FILES ${HDRS_SOLVER} + DESTINATION include/iri-algorithms/wolf/plugin_core/core/solver) +INSTALL(FILES ${HDRS_SOLVER_SUITESPARSE} + DESTINATION include/iri-algorithms/wolf/plugin_core/core/solver_suitesparse) +INSTALL(FILES ${HDRS_STATE_BLOCK} + DESTINATION include/iri-algorithms/wolf/plugin_core/core/state_block) +INSTALL(FILES ${HDRS_TRAJECTORY} + DESTINATION include/iri-algorithms/wolf/plugin_core/core/trajectory) +INSTALL(FILES ${HDRS_TREE_MANAGER} + DESTINATION include/iri-algorithms/wolf/plugin_core/core/tree_manager) +INSTALL(FILES ${HDRS_UTILS} + DESTINATION include/iri-algorithms/wolf/plugin_core/core/utils) +INSTALL(FILES ${HDRS_WRAPPER} + DESTINATION include/iri-algorithms/wolf/plugin_core/core/ceres_wrapper) INSTALL(FILES ${HDRS_YAML} DESTINATION include/iri-algorithms/wolf/plugin_core/core/yaml) diff --git a/include/core/common/wolf.h b/include/core/common/wolf.h index 64a4741c518ecd0f75bf029aa4e3267b1e3f8c4e..b11165468e47ef55e7c65ce046571d7e68ebd945 100644 --- a/include/core/common/wolf.h +++ b/include/core/common/wolf.h @@ -212,6 +212,10 @@ WOLF_PTR_TYPEDEFS(NodeBase); // Problem WOLF_PTR_TYPEDEFS(Problem); +// Tree Manager +WOLF_PTR_TYPEDEFS(TreeManagerBase); +WOLF_STRUCT_PTR_TYPEDEFS(ParamsTreeManagerBase); + // Hardware WOLF_PTR_TYPEDEFS(HardwareBase); diff --git a/include/core/problem/problem.h b/include/core/problem/problem.h index f2b19ef05c22f7a4c6777f889031dbda45d80a5b..edda0b3b59fa839cdb6c5156abf61e1f2c338174 100644 --- a/include/core/problem/problem.h +++ b/include/core/problem/problem.h @@ -43,6 +43,7 @@ class Problem : public std::enable_shared_from_this<Problem> friend ProcessorMotion; protected: + TreeManagerBasePtr tree_manager_; HardwareBasePtr hardware_ptr_; TrajectoryBasePtr trajectory_ptr_; MapBasePtr map_ptr_; @@ -73,6 +74,10 @@ class Problem : public std::enable_shared_from_this<Problem> SizeEigen getDim() const; std::string getFrameStructure() const; + // Tree manager -------------------------------------- + void setTreeManager(TreeManagerBasePtr _gm); + TreeManagerBasePtr getTreeManager() const; + // Hardware branch ------------------------------------ HardwareBasePtr getHardware() const; @@ -361,6 +366,11 @@ class Problem : public std::enable_shared_from_this<Problem> namespace wolf { +inline TreeManagerBasePtr Problem::getTreeManager() const +{ + return tree_manager_; +} + inline bool Problem::priorIsSet() const { return prior_is_set_; diff --git a/include/core/tree_manager/factory_tree_manager.h b/include/core/tree_manager/factory_tree_manager.h new file mode 100644 index 0000000000000000000000000000000000000000..7b421461c4c636a5a87ccc35b87fc83213d5b4d0 --- /dev/null +++ b/include/core/tree_manager/factory_tree_manager.h @@ -0,0 +1,61 @@ +#ifndef FACTORY_TREE_MANAGER_H_ +#define FACTORY_TREE_MANAGER_H_ + +namespace wolf +{ +class TreeManagerBase; +struct ParamsTreeManagerBase; +} + +// wolf +#include "core/common/factory.h" + +// std + +namespace wolf +{ +/** \brief TreeManager factory class + * TODO + */ + +// ParamsTreeManager factory +struct ParamsTreeManagerBase; +typedef Factory<ParamsTreeManagerBase, + const std::string&> FactoryParamsTreeManager; +template<> +inline std::string FactoryParamsTreeManager::getClass() +{ + return "FactoryParamsTreeManager"; +} + +// TreeManager factory +typedef Factory<TreeManagerBase, + const std::string&, + const ParamsTreeManagerBasePtr> FactoryTreeManager; +template<> +inline std::string FactoryTreeManager::getClass() +{ + return "FactoryTreeManager"; +} + +#define WOLF_REGISTER_TREE_MANAGER(TreeManagerType, TreeManagerName) \ + namespace{ const bool WOLF_UNUSED TreeManagerName##Registered = \ + wolf::FactoryTreeManager::get().registerCreator(TreeManagerType, TreeManagerName::create); } \ + +typedef Factory<TreeManagerBase, + const std::string&, + const ParamsServer&> AutoConfFactoryTreeManager; +template<> +inline std::string AutoConfFactoryTreeManager::getClass() +{ + return "AutoConfFactoryTreeManager"; +} + + +#define WOLF_REGISTER_TREE_MANAGER_AUTO(TreeManagerType, TreeManagerName) \ + namespace{ const bool WOLF_UNUSED TreeManagerName##AutoConfRegistered = \ + wolf::AutoConfFactoryTreeManager::get().registerCreator(TreeManagerType, TreeManagerName::create); } \ + +} /* namespace wolf */ + +#endif /* FACTORY_TREE_MANAGER_H_ */ diff --git a/include/core/tree_manager/tree_manager_base.h b/include/core/tree_manager/tree_manager_base.h new file mode 100644 index 0000000000000000000000000000000000000000..53ef9825ab029933b8c58e497e792d4f101c0406 --- /dev/null +++ b/include/core/tree_manager/tree_manager_base.h @@ -0,0 +1,82 @@ +#ifndef INCLUDE_TREE_MANAGER_BASE_H_ +#define INCLUDE_TREE_MANAGER_BASE_H_ + +// Wolf includes +#include "core/common/wolf.h" +#include "core/common/node_base.h" +#include "core/common/params_base.h" +#include "core/problem/problem.h" + +namespace wolf +{ +/* + * Macro for defining Autoconf tree manager creator for WOLF's high level API. + * + * Place a call to this macro inside your class declaration (in the tree_manager_class.h file), + * preferably just after the constructors. + * + * In order to use this macro, the derived processor class, ProcessorClass, + * must have a constructor available with the API: + * + * TreeManagerClass(const ParamsTreeManagerPtr _params); + */ +#define WOLF_TREE_MANAGER_CREATE(TreeManagerClass, ParamsTreeManagerClass) \ +static TreeManagerBasePtr create(const std::string& _unique_name, \ + const ParamsServer& _server) \ +{ \ + auto params = std::make_shared<ParamsTreeManagerClass>(_unique_name, _server); \ + \ + auto tree_manager = std::make_shared<TreeManagerClass>(params); \ + \ + tree_manager ->setName(_unique_name); \ + \ + return tree_manager; \ +} \ +static TreeManagerBasePtr create(const std::string& _unique_name, \ + const ParamsTreeManagerBasePtr _params) \ +{ \ + auto params = std::static_pointer_cast<ParamsTreeManagerClass>(_params); \ + \ + auto tree_manager = std::make_shared<TreeManagerClass>(params); \ + \ + tree_manager ->setName(_unique_name); \ + \ + return tree_manager; \ +} \ + +struct ParamsTreeManagerBase : public ParamsBase +{ + std::string prefix = "problem/tree_manager"; + ParamsTreeManagerBase() = default; + ParamsTreeManagerBase(std::string _unique_name, const ParamsServer& _server): + ParamsBase(_unique_name, _server) + { + } + + virtual ~ParamsTreeManagerBase() = default; + + std::string print() const + { + return ParamsBase::print() + "\n"; + } +}; + +class TreeManagerBase : public NodeBase +{ + public: + TreeManagerBase(const std::string& _type, ParamsTreeManagerBasePtr _params) : + NodeBase("TREE_MANAGER", _type), + params_(_params) + {} + + virtual ~TreeManagerBase(){} + + virtual void keyFrameCallback(FrameBasePtr _key_frame) = 0; + + protected: + ParamsTreeManagerBasePtr params_; +}; + +} /* namespace wolf */ + +#endif /* INCLUDE_TREE_MANAGER_BASE_H_ */ diff --git a/include/core/tree_manager/tree_manager_sliding_window.h b/include/core/tree_manager/tree_manager_sliding_window.h new file mode 100644 index 0000000000000000000000000000000000000000..8b2deec3b4fe8de046e1dd6c65c646be1a773727 --- /dev/null +++ b/include/core/tree_manager/tree_manager_sliding_window.h @@ -0,0 +1,54 @@ +#ifndef INCLUDE_TREE_MANAGER_SLIDING_WINDOW_H_ +#define INCLUDE_TREE_MANAGER_SLIDING_WINDOW_H_ + +#include "../tree_manager/tree_manager_base.h" + +namespace wolf +{ + +WOLF_STRUCT_PTR_TYPEDEFS(ParamsTreeManagerSlidingWindow) +WOLF_PTR_TYPEDEFS(TreeManagerSlidingWindow) + +struct ParamsTreeManagerSlidingWindow : public ParamsTreeManagerBase +{ + ParamsTreeManagerSlidingWindow() = default; + ParamsTreeManagerSlidingWindow(std::string _unique_name, const wolf::ParamsServer & _server) : + ParamsTreeManagerBase(_unique_name, _server) + { + n_key_frames = _server.getParam<unsigned int>(prefix + "/n_key_frames"); + fix_first_key_frame = _server.getParam<bool> (prefix + "/fix_first_key_frame"); + viral_remove_empty_parent = _server.getParam<bool> (prefix + "/viral_remove_empty_parent"); + } + std::string print() const + { + return "\n" + ParamsTreeManagerBase::print() + "\n" + + "n_key_frames: " + std::to_string(n_key_frames) + "\n" + + "fix_first_key_frame: " + std::to_string(fix_first_key_frame) + "\n" + + "viral_remove_empty_parent: " + std::to_string(viral_remove_empty_parent) + "\n"; + } + + unsigned int n_key_frames; + bool fix_first_key_frame; + bool viral_remove_empty_parent; +}; + +class TreeManagerSlidingWindow : public TreeManagerBase +{ + public: + TreeManagerSlidingWindow(ParamsTreeManagerSlidingWindowPtr _params) : + TreeManagerBase("TreeManagerSlidingWindow", _params), + params_sw_(_params) + {}; + WOLF_TREE_MANAGER_CREATE(TreeManagerSlidingWindow, ParamsTreeManagerSlidingWindow) + + virtual ~TreeManagerSlidingWindow(){} + + virtual void keyFrameCallback(FrameBasePtr _key_frame) override; + + protected: + ParamsTreeManagerSlidingWindowPtr params_sw_; +}; + +} /* namespace wolf */ + +#endif /* INCLUDE_TREE_MANAGER_SLIDING_WINDOW_H_ */ diff --git a/src/problem/problem.cpp b/src/problem/problem.cpp index 53acc960ecc87a61d28d7e1567af966d0579b375..747737dc1ff0ea4b742a97017065d229889ea7d6 100644 --- a/src/problem/problem.cpp +++ b/src/problem/problem.cpp @@ -11,12 +11,13 @@ #include "core/sensor/sensor_factory.h" #include "core/processor/processor_factory.h" #include "core/state_block/state_block.h" +#include "core/tree_manager/factory_tree_manager.h" +#include "core/tree_manager/tree_manager_base.h" #include "core/utils/logging.h" #include "core/utils/params_server.h" #include "core/utils/loader.h" #include "core/utils/check_log.h" - // IRI libs includes // C++ includes @@ -28,10 +29,12 @@ #include <vector> #include <unordered_set> + namespace wolf { Problem::Problem(const std::string& _frame_structure, SizeEigen _dim) : + tree_manager_(nullptr), hardware_ptr_(std::make_shared<HardwareBase>()), trajectory_ptr_(std::make_shared<TrajectoryBase>(_frame_structure)), map_ptr_(std::make_shared<MapBase>()), @@ -152,6 +155,12 @@ ProblemPtr Problem::autoSetup(ParamsServer &_server) procesorMap.insert(std::pair<std::string, ProcessorBasePtr>(prc["name"], problem->installProcessor(prc["type"], prc["name"], prc["sensor_name"], _server))); } + // Tree manager + std::string tree_manager_type = _server.getParam<std::string>("problem/tree_manager/type"); + WOLF_TRACE("Tree Manager Type: ", tree_manager_type); + if (tree_manager_type != "None" and tree_manager_type != "none") + problem->setTreeManager(AutoConfFactoryTreeManager::get().create(tree_manager_type, "tree manager", _server)); + // Prior Eigen::VectorXd prior_state = _server.getParam<Eigen::VectorXd>("problem/prior/state"); Eigen::MatrixXd prior_cov = _server.getParam<Eigen::MatrixXd>("problem/prior/cov"); @@ -471,12 +480,22 @@ std::string Problem::getFrameStructure() const return frame_structure_; } +void Problem::setTreeManager(TreeManagerBasePtr _gm) +{ + if (tree_manager_) + tree_manager_->setProblem(nullptr); + tree_manager_ = _gm; + tree_manager_->setProblem(shared_from_this()); + +} + void Problem::addProcessorIsMotion(IsMotionPtr _processor_motion_ptr) { processor_is_motion_list_.push_back(_processor_motion_ptr); } -void Problem::clearProcessorIsMotion(IsMotionPtr proc){ +void Problem::clearProcessorIsMotion(IsMotionPtr proc) +{ auto it = std::find(processor_is_motion_list_.begin(), processor_is_motion_list_.end(), proc); if (it != processor_is_motion_list_.end()){ processor_is_motion_list_.erase(it); @@ -528,6 +547,10 @@ void Problem::keyFrameCallback(FrameBasePtr _keyframe_ptr, ProcessorBasePtr _pro " microseconds: ", duration.count()); #endif } + + // notify tree manager + if (tree_manager_) + tree_manager_->keyFrameCallback(_keyframe_ptr); } bool Problem::permitAuxFrame(ProcessorBasePtr _processor_ptr) const @@ -909,6 +932,10 @@ FrameBasePtr Problem::setPrior(const Eigen::VectorXd& _prior_state, const Eigen: if ( !processor->isMotion() ) processor->keyFrameCallback(origin_keyframe, _time_tolerance); + // Notify tree manager + if (tree_manager_) + tree_manager_->keyFrameCallback(origin_keyframe); + return origin_keyframe; } else diff --git a/src/tree_manager/tree_manager_sliding_window.cpp b/src/tree_manager/tree_manager_sliding_window.cpp new file mode 100644 index 0000000000000000000000000000000000000000..710cd3566cd477e2dd8f9c02c0a71070c20e07d5 --- /dev/null +++ b/src/tree_manager/tree_manager_sliding_window.cpp @@ -0,0 +1,43 @@ +#include "core/tree_manager/tree_manager_sliding_window.h" + +namespace wolf +{ + +void TreeManagerSlidingWindow::keyFrameCallback(FrameBasePtr _key_frame) +{ + int n_kf(0); + FrameBasePtr first_KF(nullptr), second_KF(nullptr); + for (auto frm : getProblem()->getTrajectory()->getFrameList()) + { + if (frm->isKey()) + { + n_kf++; + if (first_KF == nullptr) + first_KF = frm; + else if (second_KF == nullptr) + second_KF = frm; + } + } + + // remove first KF if too many KF + if (n_kf > params_sw_->n_key_frames) + { + WOLF_INFO("TreeManagerSlidingWindow removing first frame"); + first_KF->remove(params_sw_->viral_remove_empty_parent); + if (params_sw_->fix_first_key_frame) + { + WOLF_INFO("TreeManagerSlidingWindow fixing new first frame"); + second_KF->fix(); + } + } +} + +} /* namespace wolf */ + +// Register in the FactoryTreeManager +#include "core/tree_manager/factory_tree_manager.h" +namespace wolf { +WOLF_REGISTER_TREE_MANAGER("TreeManagerSlidingWindow", TreeManagerSlidingWindow); +WOLF_REGISTER_TREE_MANAGER_AUTO("TreeManagerSlidingWindow", TreeManagerSlidingWindow); +} // namespace wolf + diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index db82caf1fc34b83b2509fe7d4f3ac4d6cc9e8c82..501965cdff67102f807e482f87ca7eafb7109e54 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -149,6 +149,10 @@ target_link_libraries(gtest_track_matrix ${PROJECT_NAME}) wolf_add_gtest(gtest_trajectory gtest_trajectory.cpp) target_link_libraries(gtest_trajectory ${PROJECT_NAME}) +# TreeManager class test +wolf_add_gtest(gtest_tree_manager gtest_tree_manager.cpp) +target_link_libraries(gtest_tree_manager ${PROJECT_NAME}) + # ------- Now Derived classes ---------- IF (Ceres_FOUND) @@ -229,6 +233,10 @@ target_link_libraries(gtest_processor_tracker_landmark_dummy ${PROJECT_NAME} dum wolf_add_gtest(gtest_sensor_diff_drive gtest_sensor_diff_drive.cpp) target_link_libraries(gtest_sensor_diff_drive ${PROJECT_NAME}) +# TreeManagerSlidingWindow class test +wolf_add_gtest(gtest_tree_manager_sliding_window gtest_tree_manager_sliding_window.cpp) +target_link_libraries(gtest_tree_manager_sliding_window ${PROJECT_NAME}) + # yaml conversions wolf_add_gtest(gtest_yaml_conversions gtest_yaml_conversions.cpp) target_link_libraries(gtest_yaml_conversions ${PROJECT_NAME}) diff --git a/test/dummy/tree_manager_dummy.h b/test/dummy/tree_manager_dummy.h new file mode 100644 index 0000000000000000000000000000000000000000..379fdd23902daaa5e3ba9d29a3f6a445f9e21373 --- /dev/null +++ b/test/dummy/tree_manager_dummy.h @@ -0,0 +1,61 @@ +#ifndef INCLUDE_TREE_MANAGER_DUMMY_H_ +#define INCLUDE_TREE_MANAGER_DUMMY_H_ + +#include "core/tree_manager/tree_manager_base.h" + +namespace wolf +{ + +WOLF_STRUCT_PTR_TYPEDEFS(ParamsTreeManagerDummy) +struct ParamsTreeManagerDummy : public ParamsTreeManagerBase +{ + ParamsTreeManagerDummy() = default; + ParamsTreeManagerDummy(std::string _unique_name, const ParamsServer& _server): + ParamsTreeManagerBase(_unique_name, _server) + { + toy_param = _server.getParam<double>(prefix + "/toy_param"); + } + + virtual ~ParamsTreeManagerDummy() = default; + + bool toy_param; + + std::string print() const + { + return ParamsTreeManagerBase::print() + "\n" + + "toy_param: " + std::to_string(toy_param) + "\n"; + } +}; + +WOLF_PTR_TYPEDEFS(TreeManagerDummy) + +class TreeManagerDummy : public TreeManagerBase +{ + public: + TreeManagerDummy(ParamsTreeManagerBasePtr _params) : + TreeManagerBase("TreeManagerDummy", _params), + n_KF_(0) + {}; + WOLF_TREE_MANAGER_CREATE(TreeManagerDummy, ParamsTreeManagerBase) + + virtual ~TreeManagerDummy(){} + + virtual void keyFrameCallback(FrameBasePtr _KF) override + { + n_KF_++; + }; + + int n_KF_; +}; + +} /* namespace wolf */ + +// Register in the FactoryTreeManager +#include "core/tree_manager/factory_tree_manager.h" +namespace wolf { +WOLF_REGISTER_TREE_MANAGER("TreeManagerDummy", TreeManagerDummy) +WOLF_REGISTER_TREE_MANAGER_AUTO("TreeManagerDummy", TreeManagerDummy) + +} /* namespace wolf */ + +#endif /* INCLUDE_TREE_MANAGER_DUMMY_H_ */ diff --git a/test/gtest_tree_manager.cpp b/test/gtest_tree_manager.cpp new file mode 100644 index 0000000000000000000000000000000000000000..5799117ffa523a9cbf5132ed504fa1525001c0ae --- /dev/null +++ b/test/gtest_tree_manager.cpp @@ -0,0 +1,105 @@ +#include "core/utils/utils_gtest.h" +#include "core/utils/logging.h" + +#include "core/problem/problem.h" +#include "dummy/tree_manager_dummy.h" +#include "core/yaml/parser_yaml.h" + +using namespace wolf; +using namespace Eigen; + +std::string wolf_root = _WOLF_ROOT_DIR; + +TEST(TreeManager, make_shared) +{ + ProblemPtr P = Problem::create("PO", 2); + + auto ParamsGM = std::make_shared<ParamsTreeManagerBase>(); + + auto GM = std::make_shared<TreeManagerDummy>(ParamsGM); + + P->setTreeManager(GM); + + ASSERT_EQ(std::static_pointer_cast<TreeManagerDummy>(P->getTreeManager())->n_KF_, 0); + ASSERT_EQ(P->getTreeManager(), GM); +} + +TEST(TreeManager, createParams) +{ + ProblemPtr P = Problem::create("PO", 2); + + auto ParamsGM = std::make_shared<ParamsTreeManagerBase>(); + + auto GM = TreeManagerDummy::create("tree_manager", ParamsGM); + + ASSERT_TRUE(std::dynamic_pointer_cast<TreeManagerDummy>(GM) != nullptr); + + P->setTreeManager(GM); + + ASSERT_EQ(std::static_pointer_cast<TreeManagerDummy>(P->getTreeManager())->n_KF_, 0); + ASSERT_EQ(P->getTreeManager(), GM); +} + +TEST(TreeManager, createParamServer) +{ + ProblemPtr P = Problem::create("PO", 2); + + ParserYAML parser = ParserYAML("test/yaml/params_tree_manager1.yaml", wolf_root); + ParamsServer server = ParamsServer(parser.getParams()); + + auto GM = TreeManagerDummy::create("tree_manager", server); + + ASSERT_TRUE(std::dynamic_pointer_cast<TreeManagerDummy>(GM) != nullptr); + + P->setTreeManager(GM); + + ASSERT_EQ(std::static_pointer_cast<TreeManagerDummy>(P->getTreeManager())->n_KF_, 0); + ASSERT_EQ(P->getTreeManager(), GM); +} + +TEST(TreeManager, autoConf) +{ + + ParserYAML parser = ParserYAML("test/yaml/params_tree_manager1.yaml", wolf_root); + ParamsServer server = ParamsServer(parser.getParams()); + + ProblemPtr P = Problem::autoSetup(server); + + ASSERT_TRUE(std::dynamic_pointer_cast<TreeManagerDummy>(P->getTreeManager()) != nullptr); + ASSERT_EQ(std::static_pointer_cast<TreeManagerDummy>(P->getTreeManager())->n_KF_, 1); // prior KF +} + +TEST(TreeManager, autoConfNone) +{ + + ParserYAML parser = ParserYAML("test/yaml/params_tree_manager2.yaml", wolf_root); + ParamsServer server = ParamsServer(parser.getParams()); + + ProblemPtr P = Problem::autoSetup(server); + + ASSERT_TRUE(P->getTreeManager() == nullptr); // params_tree_manager2.yaml problem/tree_manager/type: None +} + +TEST(TreeManager, keyFrameCallback) +{ + ProblemPtr P = Problem::create("PO", 3); + + auto ParamsGM = std::make_shared<ParamsTreeManagerBase>(); + + auto GM = std::make_shared<TreeManagerDummy>(ParamsGM); + + P->setTreeManager(GM); + + ASSERT_EQ(GM->n_KF_, 0); + + auto F0 = P->emplaceFrame("PO", 3, KEY, VectorXd(7), TimeStamp(0.0)); + P->keyFrameCallback(F0, nullptr, 0); + + ASSERT_EQ(GM->n_KF_, 1); +} + +int main(int argc, char **argv) +{ + testing::InitGoogleTest(&argc, argv); + return RUN_ALL_TESTS(); +} diff --git a/test/gtest_tree_manager_sliding_window.cpp b/test/gtest_tree_manager_sliding_window.cpp new file mode 100644 index 0000000000000000000000000000000000000000..ed3a8052bfb4a73b4395cc885904d8f752af91d2 --- /dev/null +++ b/test/gtest_tree_manager_sliding_window.cpp @@ -0,0 +1,267 @@ +#include "core/utils/utils_gtest.h" +#include "core/utils/logging.h" + +#include "core/problem/problem.h" +#include "core/tree_manager/tree_manager_sliding_window.h" +#include "core/yaml/parser_yaml.h" +#include "core/capture/capture_void.h" +#include "core/feature/feature_base.h" +#include "core/factor/factor_odom_3d.h" +#include "core/factor/factor_pose_3d.h" + +using namespace wolf; +using namespace Eigen; + +std::string wolf_root = _WOLF_ROOT_DIR; + +TEST(TreeManagerSlidingWindow, make_shared) +{ + ProblemPtr P = Problem::create("PO", 2); + + auto ParamsGM = std::make_shared<ParamsTreeManagerSlidingWindow>(); + + auto GM = std::make_shared<TreeManagerSlidingWindow>(ParamsGM); + + P->setTreeManager(GM); + + ASSERT_EQ(P->getTreeManager(), GM); +} + +TEST(TreeManagerSlidingWindow, createParams) +{ + ProblemPtr P = Problem::create("PO", 2); + + auto ParamsGM = std::make_shared<ParamsTreeManagerSlidingWindow>(); + + auto GM = TreeManagerSlidingWindow::create("tree_manager", ParamsGM); + + ASSERT_TRUE(std::dynamic_pointer_cast<TreeManagerSlidingWindow>(GM) != nullptr); + + P->setTreeManager(GM); + + ASSERT_TRUE(std::dynamic_pointer_cast<TreeManagerSlidingWindow>(P->getTreeManager()) != nullptr); + ASSERT_EQ(P->getTreeManager(), GM); +} + +TEST(TreeManagerSlidingWindow, createParamServer) +{ + ProblemPtr P = Problem::create("PO", 2); + + ParserYAML parser = ParserYAML("test/yaml/params_tree_manager_sliding_window1.yaml", wolf_root); + ParamsServer server = ParamsServer(parser.getParams()); + + auto GM = TreeManagerSlidingWindow::create("tree_manager", server); + + ASSERT_TRUE(std::dynamic_pointer_cast<TreeManagerSlidingWindow>(GM) != nullptr); + + P->setTreeManager(GM); + + ASSERT_TRUE(std::dynamic_pointer_cast<TreeManagerSlidingWindow>(P->getTreeManager()) != nullptr); + ASSERT_EQ(P->getTreeManager(), GM); +} + +TEST(TreeManagerSlidingWindow, autoConf) +{ + ParserYAML parser = ParserYAML("test/yaml/params_tree_manager_sliding_window1.yaml", wolf_root); + ParamsServer server = ParamsServer(parser.getParams()); + + ProblemPtr P = Problem::autoSetup(server); + + ASSERT_TRUE(std::dynamic_pointer_cast<TreeManagerSlidingWindow>(P->getTreeManager()) != nullptr); +} + +TEST(TreeManagerSlidingWindow, slidingWindowFixViral) +{ + ParserYAML parser = ParserYAML("test/yaml/params_tree_manager_sliding_window1.yaml", wolf_root); + ParamsServer server = ParamsServer(parser.getParams()); + + ProblemPtr P = Problem::autoSetup(server); + + // FRAME 1 ---------------------------------------------------------- + auto F1 = P->getTrajectory()->getLastKeyFrame(); + ASSERT_TRUE(F1 != nullptr); + + Vector7d state = F1->getState(); + Vector7d zero_disp(state); + Matrix6d cov = Matrix6d::Identity(); + + // FRAME 2 ---------------------------------------------------------- + auto F2 = P->emplaceFrame("PO", 3, KEY, state, TimeStamp(2)); + P->keyFrameCallback(F2, nullptr, 0); + + // absolute factor + auto C2 = CaptureBase::emplace<CaptureVoid>(F2, TimeStamp(2), nullptr); + auto f2 = FeatureBase::emplace<FeatureBase>(C2, "absolute", state, cov); + auto c2 = FactorBase::emplace<FactorPose3d>(f2, f2, nullptr, false); + // displacement + auto C12 = CaptureBase::emplace<CaptureVoid>(F2, TimeStamp(2), nullptr); + auto f12 = FeatureBase::emplace<FeatureBase>(C12, "odom", zero_disp, cov); + auto c12 = FactorBase::emplace<FactorOdom3d>(f12, f12, F1, nullptr, false); + + // Check no frame removed + ASSERT_FALSE(F1->isRemoving()); + + // FRAME 3 ---------------------------------------------------------- + auto F3 = P->emplaceFrame("PO", 3, KEY, state, TimeStamp(3)); + P->keyFrameCallback(F3, nullptr, 0); + + // absolute factor + auto C3 = CaptureBase::emplace<CaptureVoid>(F3, TimeStamp(3), nullptr); + auto f3 = FeatureBase::emplace<FeatureBase>(C3, "absolute", state, cov); + auto c3 = FactorBase::emplace<FactorPose3d>(f3, f3, nullptr, false); + // displacement + auto C23 = CaptureBase::emplace<CaptureVoid>(F3, TimeStamp(3), nullptr); + auto f23 = FeatureBase::emplace<FeatureBase>(C23, "odom", zero_disp, cov); + auto c23 = FactorBase::emplace<FactorOdom3d>(f23, f23, F2, nullptr, false); + + // Check no frame removed + ASSERT_FALSE(F1->isRemoving()); + + // FRAME 4 ---------------------------------------------------------- + auto F4 = P->emplaceFrame("PO", 3, KEY, state, TimeStamp(4)); + P->keyFrameCallback(F4, nullptr, 0); + + // absolute factor + auto C4 = CaptureBase::emplace<CaptureVoid>(F4, TimeStamp(4), nullptr); + auto f4 = FeatureBase::emplace<FeatureBase>(C4, "absolute", state, cov); + auto c4 = FactorBase::emplace<FactorPose3d>(f4, f4, nullptr, false); + // displacement + auto C34 = CaptureBase::emplace<CaptureVoid>(F4, TimeStamp(4), nullptr); + auto f34 = FeatureBase::emplace<FeatureBase>(C34, "odom", zero_disp, cov); + auto c34 = FactorBase::emplace<FactorOdom3d>(f34, f34, F3, nullptr, false); + + // Checks + ASSERT_TRUE(F1->isRemoving()); + ASSERT_TRUE(c12->isRemoving()); + ASSERT_TRUE(C12->isRemoving()); //Virally removed + ASSERT_TRUE(f12->isRemoving()); //Virally removed + ASSERT_TRUE(F2->isFixed()); //Fixed + + // FRAME 5 ---------------------------------------------------------- + auto F5 = P->emplaceFrame("PO", 3, KEY, state, TimeStamp(5)); + P->keyFrameCallback(F5, nullptr, 0); + + // absolute factor + auto C5 = CaptureBase::emplace<CaptureVoid>(F5, TimeStamp(5), nullptr); + auto f5 = FeatureBase::emplace<FeatureBase>(C5, "absolute", state, cov); + auto c5 = FactorBase::emplace<FactorPose3d>(f5, f5, nullptr, false); + // displacement + auto C45 = CaptureBase::emplace<CaptureVoid>(F5, TimeStamp(5), nullptr); + auto f45 = FeatureBase::emplace<FeatureBase>(C45, "odom", zero_disp, cov); + auto c45 = FactorBase::emplace<FactorOdom3d>(f45, f45, F4, nullptr, false); + + // Checks + ASSERT_TRUE(F1->isRemoving()); + ASSERT_TRUE(c12->isRemoving()); + ASSERT_TRUE(C12->isRemoving()); //Virally removed + ASSERT_TRUE(f12->isRemoving()); //Virally removed + ASSERT_TRUE(F2->isRemoving()); + ASSERT_TRUE(c2->isRemoving()); + ASSERT_TRUE(C2->isRemoving()); //Virally removed + ASSERT_TRUE(f2->isRemoving()); //Virally removed + ASSERT_TRUE(c23->isRemoving()); + ASSERT_TRUE(C23->isRemoving()); //Virally removed + ASSERT_TRUE(f23->isRemoving()); //Virally removed + ASSERT_TRUE(F3->isFixed()); //Fixed +} + +TEST(TreeManagerSlidingWindow, slidingWindowNoFixNoViral) +{ + ParserYAML parser = ParserYAML("test/yaml/params_tree_manager_sliding_window2.yaml", wolf_root); + ParamsServer server = ParamsServer(parser.getParams()); + + ProblemPtr P = Problem::autoSetup(server); + + // FRAME 1 ---------------------------------------------------------- + auto F1 = P->getTrajectory()->getLastKeyFrame(); + ASSERT_TRUE(F1 != nullptr); + + Vector7d state = F1->getState(); + Vector7d zero_disp(state); + Matrix6d cov = Matrix6d::Identity(); + + // FRAME 2 ---------------------------------------------------------- + auto F2 = P->emplaceFrame("PO", 3, KEY, state, TimeStamp(2)); + P->keyFrameCallback(F2, nullptr, 0); + + // absolute factor + auto C2 = CaptureBase::emplace<CaptureVoid>(F2, TimeStamp(2), nullptr); + auto f2 = FeatureBase::emplace<FeatureBase>(C2, "absolute", state, cov); + auto c2 = FactorBase::emplace<FactorPose3d>(f2, f2, nullptr, false); + // displacement + auto C12 = CaptureBase::emplace<CaptureVoid>(F2, TimeStamp(2), nullptr); + auto f12 = FeatureBase::emplace<FeatureBase>(C12, "odom", zero_disp, cov); + auto c12 = FactorBase::emplace<FactorOdom3d>(f12, f12, F1, nullptr, false); + + // Check no frame removed + ASSERT_FALSE(F1->isRemoving()); + + // FRAME 3 ---------------------------------------------------------- + auto F3 = P->emplaceFrame("PO", 3, KEY, state, TimeStamp(3)); + P->keyFrameCallback(F3, nullptr, 0); + + // absolute factor + auto C3 = CaptureBase::emplace<CaptureVoid>(F3, TimeStamp(3), nullptr); + auto f3 = FeatureBase::emplace<FeatureBase>(C3, "absolute", state, cov); + auto c3 = FactorBase::emplace<FactorPose3d>(f3, f3, nullptr, false); + // displacement + auto C23 = CaptureBase::emplace<CaptureVoid>(F3, TimeStamp(3), nullptr); + auto f23 = FeatureBase::emplace<FeatureBase>(C23, "odom", zero_disp, cov); + auto c23 = FactorBase::emplace<FactorOdom3d>(f23, f23, F2, nullptr, false); + + // Check no frame removed + ASSERT_FALSE(F1->isRemoving()); + + // FRAME 4 ---------------------------------------------------------- + auto F4 = P->emplaceFrame("PO", 3, KEY, state, TimeStamp(4)); + P->keyFrameCallback(F4, nullptr, 0); + + // absolute factor + auto C4 = CaptureBase::emplace<CaptureVoid>(F4, TimeStamp(4), nullptr); + auto f4 = FeatureBase::emplace<FeatureBase>(C4, "absolute", state, cov); + auto c4 = FactorBase::emplace<FactorPose3d>(f4, f4, nullptr, false); + // displacement + auto C34 = CaptureBase::emplace<CaptureVoid>(F4, TimeStamp(4), nullptr); + auto f34 = FeatureBase::emplace<FeatureBase>(C34, "odom", zero_disp, cov); + auto c34 = FactorBase::emplace<FactorOdom3d>(f34, f34, F3, nullptr, false); + + // Checks + ASSERT_TRUE(F1->isRemoving()); + ASSERT_TRUE(c12->isRemoving()); + ASSERT_FALSE(C12->isRemoving()); //Not virally removed + ASSERT_FALSE(f12->isRemoving()); //Not virally removed + ASSERT_FALSE(F2->isFixed()); //Not fixed + + // FRAME 5 ---------------------------------------------------------- + auto F5 = P->emplaceFrame("PO", 3, KEY, state, TimeStamp(5)); + P->keyFrameCallback(F5, nullptr, 0); + + // absolute factor + auto C5 = CaptureBase::emplace<CaptureVoid>(F5, TimeStamp(5), nullptr); + auto f5 = FeatureBase::emplace<FeatureBase>(C5, "absolute", state, cov); + auto c5 = FactorBase::emplace<FactorPose3d>(f5, f5, nullptr, false); + // displacement + auto C45 = CaptureBase::emplace<CaptureVoid>(F5, TimeStamp(5), nullptr); + auto f45 = FeatureBase::emplace<FeatureBase>(C45, "odom", zero_disp, cov); + auto c45 = FactorBase::emplace<FactorOdom3d>(f45, f45, F4, nullptr, false); + + // Checks + ASSERT_TRUE(F1->isRemoving()); + ASSERT_TRUE(c12->isRemoving()); + ASSERT_TRUE(C12->isRemoving()); + ASSERT_TRUE(f12->isRemoving()); + ASSERT_TRUE(F2->isRemoving()); + ASSERT_TRUE(c2->isRemoving()); + ASSERT_TRUE(C2->isRemoving()); + ASSERT_TRUE(f2->isRemoving()); + ASSERT_TRUE(c23->isRemoving()); + ASSERT_FALSE(C23->isRemoving()); //Not virally removed + ASSERT_FALSE(f23->isRemoving()); //Not virally removed + ASSERT_FALSE(F3->isFixed()); //Not fixed +} + +int main(int argc, char **argv) +{ + testing::InitGoogleTest(&argc, argv); + return RUN_ALL_TESTS(); +} diff --git a/test/yaml/params_tree_manager1.yaml b/test/yaml/params_tree_manager1.yaml new file mode 100644 index 0000000000000000000000000000000000000000..25e8ac8a4417ffec910fee4cac96669a00ebdc4f --- /dev/null +++ b/test/yaml/params_tree_manager1.yaml @@ -0,0 +1,41 @@ +config: + problem: + frame_structure: "POV" + dimension: 3 + prior: + state: [0,0,0,0,0,0,1,0,0,0] + cov: [[9,9],.1,0,0,0,0,0,0,0,0, 0,.1,0,0,0,0,0,0,0, 0,0,.1,0,0,0,0,0,0, 0,0,0,.1,0,0,0,0,0, 0,0,0,0,.1,0,0,0,0, 0,0,0,0,0,.1,0,0,0, 0,0,0,0,0,0,.1,0,0, 0,0,0,0,0,0,0,.1,0, 0,0,0,0,0,0,0,0,.1] + time_tolerance: 0.1 + timestamp: 0 + tree_manager: + type: "TreeManagerDummy" + toy_param: 0 + sensors: + - + type: "SensorOdom3d" + name: "odom" + plugin: "core" + k_disp_to_disp: 0.1 + k_disp_to_rot: 0.1 + k_rot_to_rot: 0.1 + min_disp_var: 0.1 + min_rot_var: 0.1 + extrinsic: + pose: [1,2,3,0,0,0,1] + processors: + - + type: "ProcessorOdom3d" + name: "my_proc_odom3d" + sensor_name: "odom" + plugin: "core" + apply_loss_function: false + time_tolerance: 0.01 # seconds + keyframe_vote: + voting_active: false + voting_aux_active: false + max_time_span: 0.2 # seconds + max_buff_length: 10 # motion deltas + dist_traveled: 0.5 # meters + angle_turned: 0.1 # radians (1 rad approx 57 deg, approx 60 deg) + + unmeasured_perturbation_std: 0.00111 \ No newline at end of file diff --git a/test/yaml/params_tree_manager2.yaml b/test/yaml/params_tree_manager2.yaml new file mode 100644 index 0000000000000000000000000000000000000000..913f5875bfd09750e024fcfeab910ff45d6058ee --- /dev/null +++ b/test/yaml/params_tree_manager2.yaml @@ -0,0 +1,40 @@ +config: + problem: + frame_structure: "POV" + dimension: 3 + prior: + state: [0,0,0,0,0,0,1,0,0,0] + cov: [[9,9],.1,0,0,0,0,0,0,0,0, 0,.1,0,0,0,0,0,0,0, 0,0,.1,0,0,0,0,0,0, 0,0,0,.1,0,0,0,0,0, 0,0,0,0,.1,0,0,0,0, 0,0,0,0,0,.1,0,0,0, 0,0,0,0,0,0,.1,0,0, 0,0,0,0,0,0,0,.1,0, 0,0,0,0,0,0,0,0,.1] + time_tolerance: 0.1 + timestamp: 0 + tree_manager: + type: "None" + sensors: + - + type: "SensorOdom3d" + name: "odom" + plugin: "core" + k_disp_to_disp: 0.1 + k_disp_to_rot: 0.1 + k_rot_to_rot: 0.1 + min_disp_var: 0.1 + min_rot_var: 0.1 + extrinsic: + pose: [1,2,3,0,0,0,1] + processors: + - + type: "ProcessorOdom3d" + name: "my_proc_odom3d" + sensor_name: "odom" + plugin: "core" + apply_loss_function: false + time_tolerance: 0.01 # seconds + keyframe_vote: + voting_active: false + voting_aux_active: false + max_time_span: 0.2 # seconds + max_buff_length: 10 # motion deltas + dist_traveled: 0.5 # meters + angle_turned: 0.1 # radians (1 rad approx 57 deg, approx 60 deg) + + unmeasured_perturbation_std: 0.00111 \ No newline at end of file diff --git a/test/yaml/params_tree_manager_sliding_window1.yaml b/test/yaml/params_tree_manager_sliding_window1.yaml new file mode 100644 index 0000000000000000000000000000000000000000..5cbb9e5a787b4ad2e70f9cf7f283ab1747e1279b --- /dev/null +++ b/test/yaml/params_tree_manager_sliding_window1.yaml @@ -0,0 +1,43 @@ +config: + problem: + frame_structure: "PO" + dimension: 3 + prior: + state: [0,0,0,0,0,0,1] + cov: [[6,6],.1,0,0,0,0,0, 0,.1,0,0,0,0, 0,0,.1,0,0,0, 0,0,0,.1,0,0, 0,0,0,0,.1,0, 0,0,0,0,0,.1] + time_tolerance: 0.1 + timestamp: 0 + tree_manager: + type: "TreeManagerSlidingWindow" + n_key_frames: 3 + fix_first_key_frame: true + viral_remove_empty_parent: true + sensors: + - + type: "SensorOdom3d" + name: "odom" + plugin: "core" + k_disp_to_disp: 0.1 + k_disp_to_rot: 0.1 + k_rot_to_rot: 0.1 + min_disp_var: 0.1 + min_rot_var: 0.1 + extrinsic: + pose: [1,2,3,0,0,0,1] + processors: + - + type: "ProcessorOdom3d" + name: "my_proc_odom3d" + sensor_name: "odom" + plugin: "core" + apply_loss_function: false + time_tolerance: 0.01 # seconds + keyframe_vote: + voting_active: false + voting_aux_active: false + max_time_span: 0.2 # seconds + max_buff_length: 10 # motion deltas + dist_traveled: 0.5 # meters + angle_turned: 0.1 # radians (1 rad approx 57 deg, approx 60 deg) + + unmeasured_perturbation_std: 0.00111 \ No newline at end of file diff --git a/test/yaml/params_tree_manager_sliding_window2.yaml b/test/yaml/params_tree_manager_sliding_window2.yaml new file mode 100644 index 0000000000000000000000000000000000000000..01f41eea97c7cca943d4aa12a143736668c2673f --- /dev/null +++ b/test/yaml/params_tree_manager_sliding_window2.yaml @@ -0,0 +1,43 @@ +config: + problem: + frame_structure: "PO" + dimension: 3 + prior: + state: [0,0,0,0,0,0,1] + cov: [[6,6],.1,0,0,0,0,0, 0,.1,0,0,0,0, 0,0,.1,0,0,0, 0,0,0,.1,0,0, 0,0,0,0,.1,0, 0,0,0,0,0,.1] + time_tolerance: 0.1 + timestamp: 0 + tree_manager: + type: "TreeManagerSlidingWindow" + n_key_frames: 3 + fix_first_key_frame: false + viral_remove_empty_parent: false + sensors: + - + type: "SensorOdom3d" + name: "odom" + plugin: "core" + k_disp_to_disp: 0.1 + k_disp_to_rot: 0.1 + k_rot_to_rot: 0.1 + min_disp_var: 0.1 + min_rot_var: 0.1 + extrinsic: + pose: [1,2,3,0,0,0,1] + processors: + - + type: "ProcessorOdom3d" + name: "my_proc_odom3d" + sensor_name: "odom" + plugin: "core" + apply_loss_function: false + time_tolerance: 0.01 # seconds + keyframe_vote: + voting_active: false + voting_aux_active: false + max_time_span: 0.2 # seconds + max_buff_length: 10 # motion deltas + dist_traveled: 0.5 # meters + angle_turned: 0.1 # radians (1 rad approx 57 deg, approx 60 deg) + + unmeasured_perturbation_std: 0.00111 \ No newline at end of file