diff --git a/include/core/state_block/state_block.h b/include/core/state_block/state_block.h index 3238fb8ece01ff1f48e4cfcd5b403760a5bb4c2f..9b8f979fc57b93658cb2caebb951ef375e7cfafa 100644 --- a/include/core/state_block/state_block.h +++ b/include/core/state_block/state_block.h @@ -147,7 +147,10 @@ public: void resetLocalParamUpdated(); virtual void setIdentity(bool _notify = true); - virtual void setZero (bool _notify = true); + void setZero (bool _notify = true); + + virtual Eigen::VectorXd identity() const; + Eigen::VectorXd zero() const; /** \brief perturb state */ @@ -299,6 +302,14 @@ inline void StateBlock::setZero(bool _notify) setIdentity(_notify); } +inline Eigen::VectorXd StateBlock::identity() const +{ + return Eigen::VectorXd::Zero(state_size_); +} +inline Eigen::VectorXd StateBlock::zero() const +{ + return identity(); +} }// namespace wolf diff --git a/include/core/state_block/state_composite.h b/include/core/state_block/state_composite.h index 267a6e1b23caddfa5f8f210510e6cde2a0d3b99b..b533eb686740ee2db8c8643fb4356c71d96d39c3 100644 --- a/include/core/state_block/state_composite.h +++ b/include/core/state_block/state_composite.h @@ -29,25 +29,12 @@ typedef StateBlockMap::const_iterator StateBlockMapCIter; class StateBlockComposite { public: - StateBlockComposite() = default; - virtual ~StateBlockComposite() = default; + StateBlockComposite() = default; + ~StateBlockComposite() = default; - const StateBlockMap& getStateBlockMap() const; + const StateBlockMap& getStateBlockMap() const; - // These act on all state blocks. Per-block action must be done through state_block.fix() or through extended API in derived classes of this. - virtual void fix(); - virtual void unfix(); - virtual bool isFixed() const; - - virtual unsigned int remove(const std::string& _sb_type); - bool has(const std::string& _sb_type) const { return state_block_map_.count(_sb_type) > 0; } - bool has(const StateBlockPtr& _sb) const; - StateBlockPtr at(const std::string& _sb_type) const; - void set(const std::string _sb_type, const StateBlockPtr& _sb); - bool key(const StateBlockPtr& _sb, std::string& _key) const; - StateBlockMapCIter find(const StateBlockPtr& _sb) const; - - virtual StateBlockPtr add(const std::string& _sb_type, const StateBlockPtr& _sb); + StateBlockPtr add(const std::string& _sb_type, const StateBlockPtr& _sb); // Emplace derived state blocks (angle, quaternion, etc). template<typename SB, typename ... Args> @@ -57,12 +44,32 @@ class StateBlockComposite template<typename ... Args> inline StateBlockPtr emplace(const std::string& _sb_type, Args&&... _args_of_base_state_block_constructor); - // Perturb state with noise - void perturb(double amplitude = 0.01); + unsigned int remove(const std::string& _sb_type); + bool has(const std::string& _sb_type) const { return state_block_map_.count(_sb_type) > 0; } + bool has(const StateBlockPtr& _sb) const; + StateBlockPtr at(const std::string& _sb_type) const; + void set(const std::string _sb_type, const StateBlockPtr& _sb); + bool key(const StateBlockPtr& _sb, std::string& _key) const; + std::string key(const StateBlockPtr& _sb) const; + StateBlockMapCIter find(const StateBlockPtr& _sb) const; + + // identity and zero (they are the same with different names) + void setIdentity(bool _notify = true); + void setZero(bool _notify = true); + VectorComposite identity() const; + VectorComposite zero() const; // Plus operator void plus(const VectorComposite& _dx); + // Perturb state with random noise + void perturb(double amplitude = 0.01); + + // These act on all state blocks. Per-block action must be done through state_block.fix() or through extended API in derived classes of this. + void fix(); + void unfix(); + bool isFixed() const; + // Get composite of state vectors (not blocks) VectorComposite getVectorComposite() const; bool getVectorComposite(VectorComposite& _state) const; @@ -81,8 +88,8 @@ class MatrixComposite std::unordered_map < string, unsigned int> size_rows_, size_cols_; public: - MatrixComposite() = default; - virtual ~MatrixComposite() = default; + MatrixComposite() = default; + ~MatrixComposite() = default; unsigned int count(const std::string &_row, const std::string &_col) const; @@ -108,7 +115,7 @@ class MatrixComposite const MatrixXd& operator ()(const std::string &_row, const std::string &_col) const; - VectorComposite operator *(const VectorComposite &_second) const; + VectorComposite operator *(const VectorComposite &_second) const; MatrixComposite operator *(const MatrixComposite &_second) const; friend std::ostream& operator << (std::ostream& _os, const MatrixComposite& _M); diff --git a/include/core/state_block/state_homogeneous_3d.h b/include/core/state_block/state_homogeneous_3d.h index 547e849005666a97fe36e6761b95dca94cf06182..7a8e233b74816b347afa240183fad49dbed6141b 100644 --- a/include/core/state_block/state_homogeneous_3d.h +++ b/include/core/state_block/state_homogeneous_3d.h @@ -20,6 +20,8 @@ class StateHomogeneous3d : public StateBlock StateHomogeneous3d(const Eigen::VectorXd _state, bool _fixed = false); virtual ~StateHomogeneous3d(); virtual void setIdentity(bool _notify = true) override; + virtual Eigen::VectorXd identity() const override; + }; inline StateHomogeneous3d::StateHomogeneous3d(const Eigen::VectorXd _state, bool _fixed) : @@ -46,7 +48,10 @@ inline void StateHomogeneous3d::setIdentity(bool _notify) setState(Eigen::Quaterniond::Identity().coeffs(), _notify); } - +inline Eigen::VectorXd StateHomogeneous3d::identity() const +{ + return Eigen::Quaterniond::Identity().coeffs(); +} } // namespace wolf diff --git a/include/core/state_block/state_quaternion.h b/include/core/state_block/state_quaternion.h index a7f460b81324c44fa7d319a88e3569a3f2e796b6..3e9c2c09ae0c03b690dbfba0551855f636e6aa38 100644 --- a/include/core/state_block/state_quaternion.h +++ b/include/core/state_block/state_quaternion.h @@ -21,6 +21,7 @@ class StateQuaternion : public StateBlock StateQuaternion(const Eigen::Quaterniond& _quaternion, bool _fixed = false); virtual ~StateQuaternion(); virtual void setIdentity(bool _notify = true) override; + virtual Eigen::VectorXd identity() const override; }; inline StateQuaternion::StateQuaternion(const Eigen::Quaterniond& _quaternion, bool _fixed) : @@ -51,6 +52,11 @@ inline void StateQuaternion::setIdentity(bool _notify) setState(Eigen::Quaterniond::Identity().coeffs(), _notify); } +inline Eigen::VectorXd StateQuaternion::identity() const +{ + return Eigen::Quaterniond::Identity().coeffs(); +} + } // namespace wolf #endif /* SRC_STATE_QUATERNION_H_ */ diff --git a/src/state_block/state_composite.cpp b/src/state_block/state_composite.cpp index 6fd4cdded28dbfe9fcc7b0e42d976678b25a975a..b11d911fd3e32f273fd3d2dfb30fd72b68df78ee 100644 --- a/src/state_block/state_composite.cpp +++ b/src/state_block/state_composite.cpp @@ -155,10 +155,16 @@ const StateBlockMap& StateBlockComposite::getStateBlockMap() const void StateBlockComposite::fix() { + for (auto pair_key_sbp : state_block_map_) + if (pair_key_sbp.second != nullptr) + pair_key_sbp.second->fix(); } void StateBlockComposite::unfix() { + for (auto pair_key_sbp : state_block_map_) + if (pair_key_sbp.second != nullptr) + pair_key_sbp.second->unfix(); } bool StateBlockComposite::isFixed() const @@ -222,6 +228,19 @@ bool StateBlockComposite::key(const StateBlockPtr &_sb, std::string &_key) const } } +std::string StateBlockComposite::key(const StateBlockPtr& _sb) const +{ + const auto& it = this->find(_sb); + + bool found = (it != state_block_map_.end()); + + if (found) + return it->first; + else + return ""; +} + + StateBlockMapCIter StateBlockComposite::find(const StateBlockPtr &_sb) const { const auto& it = std::find_if(state_block_map_.begin(), @@ -290,4 +309,31 @@ void StateBlockComposite::setVectorComposite(const VectorComposite &_state) } } +void StateBlockComposite::setIdentity(bool _notify) +{ + for (const auto& pair_key_sb : getStateBlockMap()) + { + pair_key_sb.second->setIdentity(_notify); + } +} + +void StateBlockComposite::setZero(bool _notify) +{ + setIdentity(_notify); +} + +VectorComposite StateBlockComposite::identity() const +{ + VectorComposite x; + for (const auto& pair_key_sb : getStateBlockMap()) + x.emplace(pair_key_sb.first, pair_key_sb.second->identity()); + return x; +} + +VectorComposite StateBlockComposite::zero() const +{ + return identity(); +} + } // namespace wolf + diff --git a/test/gtest_state_composite.cpp b/test/gtest_state_composite.cpp index d814d0918fab6f1f15b63ae5051ddbc571f7a1a4..ce6897eaa0c0ec175605883a7b49eb696aaaaf73 100644 --- a/test/gtest_state_composite.cpp +++ b/test/gtest_state_composite.cpp @@ -83,7 +83,7 @@ TEST_F(StateBlockCompositeInit, set) ASSERT_EQ(states.at("X"), nullptr); } -TEST_F(StateBlockCompositeInit, key) +TEST_F(StateBlockCompositeInit, key_ref) { std::string key; ASSERT_TRUE(states.key(sbp, key)); @@ -93,6 +93,15 @@ TEST_F(StateBlockCompositeInit, key) ASSERT_EQ(key, ""); } +TEST_F(StateBlockCompositeInit, key_return) +{ + // existing key + ASSERT_EQ(states.key(sbp), "P"); + + // non existing key returns empty string + ASSERT_EQ(states.key(sbx), ""); +} + TEST_F(StateBlockCompositeInit, find) { auto it = states.find(sbp); @@ -109,6 +118,17 @@ TEST_F(StateBlockCompositeInit, add) ASSERT_EQ(states.at("X"), sbx); } +TEST_F(StateBlockCompositeInit, remove) +{ + // remove existing block + states.remove("V"); + ASSERT_EQ(states.getStateBlockMap().size(), 2); + + // remove non existing block -- no effect + states.remove("X"); + ASSERT_EQ(states.getStateBlockMap().size(), 2); +} + TEST_F(StateBlockCompositeInit, perturb) { ASSERT_TRUE(states.at("P")->getState().isApprox(sbp->getState(), 1e-3)); @@ -123,6 +143,64 @@ TEST_F(StateBlockCompositeInit, perturb) ASSERT_FALSE(states.at("Q")->getState().isApprox(Vector4d(.5,.5,.5,.5), 1e-3)); } +TEST_F(StateBlockCompositeInit, setIdentity) +{ + ASSERT_TRUE(states.at("P")->getState().isApprox(sbp->getState(), 1e-3)); + ASSERT_TRUE(states.at("V")->getState().isApprox(sbv->getState(), 1e-3)); + ASSERT_TRUE(states.at("Q")->getState().isApprox(sbq->getState(), 1e-3)); + + states.setIdentity(); + + // values have moved wrt original + ASSERT_TRUE(states.at("P")->getState().isApprox(Vector3d(0,0,0), 1e-10)); + ASSERT_TRUE(states.at("V")->getState().isApprox(Vector3d(0,0,0), 1e-10)); + ASSERT_TRUE(states.at("Q")->getState().isApprox(Vector4d(0,0,0,1), 1e-10)); +} + +TEST_F(StateBlockCompositeInit, identity) +{ + VectorComposite v = states.identity(); + + ASSERT_TRUE(v.at("P").isApprox(Vector3d(0,0,0), 1e-10)); + ASSERT_TRUE(v.at("V").isApprox(Vector3d(0,0,0), 1e-10)); + ASSERT_TRUE(v.at("Q").isApprox(Vector4d(0,0,0,1), 1e-10)); +} + +TEST_F(StateBlockCompositeInit, fix) +{ + states.fix(); + + ASSERT_TRUE(states.at("P")->isFixed()); + ASSERT_TRUE(states.at("V")->isFixed()); + ASSERT_TRUE(states.at("Q")->isFixed()); +} + +TEST_F(StateBlockCompositeInit, unfix) +{ + states.fix(); + + ASSERT_TRUE(states.at("P")->isFixed()); + ASSERT_TRUE(states.at("V")->isFixed()); + ASSERT_TRUE(states.at("Q")->isFixed()); + + states.unfix(); + + ASSERT_FALSE(states.at("P")->isFixed()); + ASSERT_FALSE(states.at("V")->isFixed()); + ASSERT_FALSE(states.at("Q")->isFixed()); +} + +TEST_F(StateBlockCompositeInit, isFixed) +{ + states.fix(); + + ASSERT_TRUE(states.isFixed()); + + states.at("P")->unfix(); + + ASSERT_FALSE(states.isFixed()); +} +