diff --git a/demos/hello_wolf/yaml/processor_odom_2d.yaml b/demos/hello_wolf/yaml/processor_odom_2d.yaml
index 04d0ff166981259edc9ca51dc3e39260fd427a62..907bbfab3be6e9f66feb6c027f34fa752fd893c4 100644
--- a/demos/hello_wolf/yaml/processor_odom_2d.yaml
+++ b/demos/hello_wolf/yaml/processor_odom_2d.yaml
@@ -10,3 +10,6 @@ keyframe_vote:
   max_buff_length:    999
   cov_det:            999
 apply_loss_function: true
+
+state_getter: true
+state_priority: 1
diff --git a/include/core/problem/problem.h b/include/core/problem/problem.h
index dc810f2764b895923f7a0516f6e7a6e14e2ebc5d..3d0eba08b8e234a1adcd3ab4bd00a149e10e6f65 100644
--- a/include/core/problem/problem.h
+++ b/include/core/problem/problem.h
@@ -58,7 +58,7 @@ class Problem : public std::enable_shared_from_this<Problem>
         HardwareBasePtr     hardware_ptr_;
         TrajectoryBasePtr   trajectory_ptr_;
         MapBasePtr          map_ptr_;
-        std::list<IsMotionPtr>  processor_is_motion_list_;
+        std::map<int, IsMotionPtr>  processor_is_motion_map_;
         std::map<std::pair<StateBlockPtr, StateBlockPtr>, Eigen::MatrixXd> covariances_;
         SizeEigen state_size_, state_cov_size_, dim_;
         std::map<FactorBasePtr, Notification> factor_notification_map_;
@@ -174,14 +174,12 @@ class Problem : public std::enable_shared_from_this<Problem>
          * Add a new processor of type is motion to the processor is motion list.
          */
         void addProcessorIsMotion(IsMotionPtr _processor_motion_ptr);
-        void clearProcessorIsMotion(IsMotionPtr proc);
+        void removeProcessorIsMotion(IsMotionPtr proc);
 
     public:
         IsMotionPtr getProcessorIsMotion();
-        std::list<IsMotionPtr> getProcessorIsMotionList();
-        
-
-
+        std::map<int,IsMotionPtr>& getProcessorIsMotionMap();
+        const std::map<int,IsMotionPtr>& getProcessorIsMotionMap() const;
 
         // Trajectory branch ----------------------------------
         TrajectoryBasePtr getTrajectory() const;
@@ -321,6 +319,7 @@ class Problem : public std::enable_shared_from_this<Problem>
         TimeStamp       getTimeStamp    ( ) const;
         VectorComposite getState        ( const StateStructure& _structure = "" ) const;
         VectorComposite getState        ( const TimeStamp& _ts, const StateStructure& _structure = "" ) const;
+        VectorComposite getOdometry     ( const StateStructure& _structure = "" ) const;
 
         // Zero state provider
         VectorComposite stateZero       ( const StateStructure& _structure = "" ) const;
@@ -431,15 +430,19 @@ inline bool Problem::isPriorSet() const
 
 inline IsMotionPtr Problem::getProcessorIsMotion()
 {
-    if (!processor_is_motion_list_.empty())
-        return processor_is_motion_list_.front();
+    if (not processor_is_motion_map_.empty())
+        return processor_is_motion_map_.begin()->second;
     return nullptr;
 }
 
+inline std::map<int,IsMotionPtr>& Problem::getProcessorIsMotionMap()
+{
+    return processor_is_motion_map_;
+}
 
-inline std::list<IsMotionPtr> Problem::getProcessorIsMotionList()
+inline const std::map<int,IsMotionPtr>& Problem::getProcessorIsMotionMap() const
 {
-    return processor_is_motion_list_;
+    return processor_is_motion_map_;
 }
 
 inline SizeStd Problem::getStateBlockNotificationMapSize() const
diff --git a/include/core/processor/is_motion.h b/include/core/processor/is_motion.h
index dc0487046e5013626ebc02288a00915a7df58b24..a17ac88e7f2d78bc83e5866f10e85173af380638 100644
--- a/include/core/processor/is_motion.h
+++ b/include/core/processor/is_motion.h
@@ -10,10 +10,31 @@
 
 #include "core/common/wolf.h"
 #include "core/state_block/state_composite.h"
+#include "core/utils/params_server.h"
 
 namespace wolf
 {
 
+WOLF_STRUCT_PTR_TYPEDEFS(ParamsIsMotion);
+
+struct ParamsIsMotion
+{
+    bool state_getter = true;
+    int state_priority = 1;
+
+    ParamsIsMotion() = default;
+    ParamsIsMotion(std::string _unique_name, const ParamsServer& _server)
+    {
+        state_getter    = _server.getParam<bool>("processor/" + _unique_name + "/state_getter");
+        state_priority  = _server.getParam<double>("processor/" + _unique_name + "/state_priority");
+    }
+    std::string print() const
+    {
+      return  "state_getter: "   + std::to_string(state_getter)   + "\n"
+            + "state_priority: " + std::to_string(state_priority) + "\n";
+    }
+
+};
 class TimeStamp;
 
 WOLF_PTR_TYPEDEFS(IsMotion);
@@ -22,7 +43,7 @@ class IsMotion
 {
     public:
 
-        IsMotion(const StateStructure& _structure);
+        IsMotion(const StateStructure& _structure, ParamsIsMotionPtr _params);
         virtual ~IsMotion();
 
         // Queries to the processor:
@@ -31,8 +52,11 @@ class IsMotion
         virtual VectorComposite getState(const TimeStamp& _ts, const StateStructure& _structure = "") const = 0;
 
         VectorComposite getOdometry ( ) const;
-    private:
-        void setOdometry(const VectorComposite& _zero_odom) {odometry_ = _zero_odom;}
+        void setOdometry(const VectorComposite&);
+
+        bool isStateGetter() const;
+        int getStatePriority() const;
+        void setStatePriority(int);
 
     public:
         const StateStructure& getStateStructure ( ) { return state_structure_; };
@@ -42,16 +66,16 @@ class IsMotion
     protected:
         StateStructure state_structure_; ///< The structure of the state vector (to retrieve state blocks from frames)
         VectorComposite odometry_;
-
+        ParamsIsMotionPtr params_is_motion_;
 };
 
-inline IsMotion::IsMotion(const StateStructure& _structure) :
-        state_structure_(_structure)
+inline IsMotion::IsMotion(const StateStructure& _structure, ParamsIsMotionPtr _params) :
+        state_structure_(_structure),
+        params_is_motion_(_params)
 {
     //
 }
 
-
 inline wolf::VectorComposite IsMotion::getOdometry ( ) const
 {
     return odometry_;
@@ -60,14 +84,27 @@ inline wolf::VectorComposite IsMotion::getOdometry ( ) const
 }
 
 /////  IMPLEMENTATION ///////
-#include "core/common/time_stamp.h"
-
 namespace wolf{
 
 inline IsMotion::~IsMotion()
 {
 }
 
+inline bool IsMotion::isStateGetter() const
+{
+    return params_is_motion_->state_getter;
+}
+
+inline int IsMotion::getStatePriority() const
+{
+    return params_is_motion_->state_priority;
+}
+
+inline void IsMotion::setStatePriority(int _priority)
+{
+    params_is_motion_->state_priority = _priority;
+}
+
 } /* namespace wolf */
 
 #endif /* PROCESSOR_IS_MOTION_H_ */
diff --git a/include/core/processor/processor_motion.h b/include/core/processor/processor_motion.h
index 75053ab0f35d1c338092c723573d5cfbf85755b6..207bacb8eb7c9770787e00e9a811b30543708c51 100644
--- a/include/core/processor/processor_motion.h
+++ b/include/core/processor/processor_motion.h
@@ -23,7 +23,7 @@ namespace wolf
 
 WOLF_STRUCT_PTR_TYPEDEFS(ParamsProcessorMotion);
 
-struct ParamsProcessorMotion : public ParamsProcessorBase
+struct ParamsProcessorMotion : public ParamsProcessorBase, public ParamsIsMotion
 {
         double max_time_span    = 0.5;
         unsigned int max_buff_length  = 10;
@@ -33,7 +33,8 @@ struct ParamsProcessorMotion : public ParamsProcessorBase
 
         ParamsProcessorMotion() = default;
         ParamsProcessorMotion(std::string _unique_name, const ParamsServer& _server):
-            ParamsProcessorBase(_unique_name, _server)
+            ParamsProcessorBase(_unique_name, _server),
+            ParamsIsMotion(_unique_name, _server)
         {
           max_time_span   = _server.getParam<double>(prefix + _unique_name       + "/keyframe_vote/max_time_span");
           max_buff_length = _server.getParam<unsigned int>(prefix + _unique_name + "/keyframe_vote/max_buff_length");
@@ -43,7 +44,8 @@ struct ParamsProcessorMotion : public ParamsProcessorBase
         }
         std::string print() const override
         {
-          return ParamsProcessorBase::print() + "\n"
+          return ParamsProcessorBase::print() + "\n" +
+                 ParamsIsMotion::print() + "\n"
             + "max_time_span: "     + std::to_string(max_time_span)     + "\n"
             + "max_buff_length: "   + std::to_string(max_buff_length)   + "\n"
             + "dist_traveled: "     + std::to_string(dist_traveled)     + "\n"
diff --git a/include/core/state_block/state_composite.h b/include/core/state_block/state_composite.h
index c7a125ac0d96b1d1b0799ab9e983bccf76bf36db..7989fd807eab08187c802e0386af02de56ef4f1b 100644
--- a/include/core/state_block/state_composite.h
+++ b/include/core/state_block/state_composite.h
@@ -69,6 +69,8 @@ class VectorComposite : public std::unordered_map < char, Eigen::VectorXd >
         void set(const VectorXd& _v, const StateStructure& _structure, const std::list<int>& _sizes);
         void setZero();
 
+        bool includesStructure(const StateStructure &_structure) const;
+
         friend std::ostream& operator <<(std::ostream &_os, const wolf::VectorComposite &_x);
         friend wolf::VectorComposite operator +(const wolf::VectorComposite &_x, const wolf::VectorComposite &_y);
         friend wolf::VectorComposite operator -(const wolf::VectorComposite &_x, const wolf::VectorComposite &_y);
diff --git a/src/frame/frame_base.cpp b/src/frame/frame_base.cpp
index 549b1435222c8cda2c0615a54632d6c8c5b63840..4b278bf8bf8ef16eca8ea61ed4702d85358b6730 100644
--- a/src/frame/frame_base.cpp
+++ b/src/frame/frame_base.cpp
@@ -21,13 +21,11 @@ FrameBase::FrameBase(const TimeStamp& _ts,
         frame_id_(++frame_id_count_),
         time_stamp_(_ts)
 {
-    for (const auto& pair_key_vec : _state)
-    {
-        const auto& key  = pair_key_vec.first;
-        const auto& vec  = pair_key_vec.second;
-
-        StateBlockPtr sb = FactoryStateBlock::create(string(1,key), vec, false); // false = non fixed
+    assert(_state.includesStructure(_frame_structure) && "_state does not include all keys of _frame_structure");
 
+    for (auto key : getStructure())
+    {
+        StateBlockPtr sb = FactoryStateBlock::create(string(1,key), _state.at(key), false); // false = non fixed
         addStateBlock(key, sb, getProblem());
     }
 }
diff --git a/src/problem/problem.cpp b/src/problem/problem.cpp
index 40396509fd506ce25a65a8e510b9b4dde8818f64..0bb18fd52c7ec787c65298afcae06e19abff3230 100644
--- a/src/problem/problem.cpp
+++ b/src/problem/problem.cpp
@@ -45,7 +45,7 @@ Problem::Problem(const std::string& _frame_structure, SizeEigen _dim) :
         hardware_ptr_(std::make_shared<HardwareBase>()),
         trajectory_ptr_(std::make_shared<TrajectoryBase>()),
         map_ptr_(std::make_shared<MapBase>()),
-        processor_is_motion_list_(std::list<IsMotionPtr>()),
+        processor_is_motion_map_(),
         frame_structure_(_frame_structure),
         prior_options_(std::make_shared<PriorOptions>())
 {
@@ -420,10 +420,10 @@ TimeStamp Problem::getTimeStamp ( ) const
 {
     TimeStamp  ts = TimeStamp::Invalid();
 
-    for (const auto& prc : processor_is_motion_list_)
-        if (prc->getTimeStamp().ok())
-            if ( (not ts.ok() ) or prc->getTimeStamp() > ts)
-                ts = prc->getTimeStamp();
+    for (const auto& prc_pair : processor_is_motion_map_)
+        if (prc_pair.second->getTimeStamp().ok())
+            if ( (not ts.ok() ) or prc_pair.second->getTimeStamp() > ts)
+                ts = prc_pair.second->getTimeStamp();
 
 
     if (not ts.ok())
@@ -447,13 +447,15 @@ VectorComposite Problem::getState(const StateStructure& _structure) const
 
     VectorComposite state;
 
-    // compose the states of all processor motions into one only state
-    for (const auto& prc : processor_is_motion_list_)
+    // compose the states of all IsMotion processors (ordered by user-defined priority) into one only state
+    for (const auto& prc_pair : processor_is_motion_map_)
     {
-        const auto& prc_state = prc->getState(structure);
+        const auto& prc_state = prc_pair.second->getState(structure);
+
+        // transfer processor vector blocks to problem state
         for (const auto& pair_key_vec : prc_state)
         {
-            if (state.count(pair_key_vec.first) == 0) // only add those keys that do not exist yet
+            if (state.count(pair_key_vec.first) == 0) // Only write once. This gives priority to processors with more priority
                 state.insert(pair_key_vec);
         }
     }
@@ -493,16 +495,15 @@ VectorComposite Problem::getState (const TimeStamp& _ts, const StateStructure& _
 
     VectorComposite state;
 
-    for (const auto& prc : processor_is_motion_list_)
+    // compose the states of all IsMotion processors (ordered by user-defined priority) into one only state
+    for (const auto& prc_pair : processor_is_motion_map_)
     {
-        const auto& prc_state = prc->getState(_ts, structure);
+        const auto& prc_state = prc_pair.second->getState(_ts, structure);
 
         // transfer processor vector blocks to problem state
         for (const auto& pair_key_vec : prc_state)
         {
-            const auto& key = pair_key_vec.first;
-
-            if (state.count(key) == 0) // Only write once. This gives priority to processors upfront in the list
+            if (state.count(pair_key_vec.first) == 0) // Only write once. This gives priority to processors with more priority
                 state.insert(pair_key_vec);
         }
     }
@@ -536,6 +537,49 @@ VectorComposite Problem::getState (const TimeStamp& _ts, const StateStructure& _
     return state;
 }
 
+VectorComposite Problem::getOdometry(const StateStructure& _structure) const
+{
+    StateStructure structure = (_structure == "" ? getFrameStructure() : _structure);
+
+    VectorComposite odom_state;
+
+    // compose the states of all IsMotion processors (ordered by user-defined priority) into one only state
+    for (const auto& prc_pair : processor_is_motion_map_)
+    {
+        const auto& prc_state = prc_pair.second->getOdometry();
+
+        // transfer processor vector blocks to problem state
+        for (const auto& pair_key_vec : prc_state)
+        {
+            if (odom_state.count(pair_key_vec.first) == 0) // Only write once. This gives priority to processors with more priority
+                odom_state.insert(pair_key_vec);
+        }
+    }
+
+    // check for empty blocks and fill them with the the prior, or with zeros in the worst case
+
+    VectorComposite state_last;
+
+    if (prior_options_ and prior_options_->mode != "nothing")
+        state_last = prior_options_->state;
+
+    for (const auto& key : structure)
+    {
+        if (odom_state.count(key) == 0)
+        {
+            auto state_last_it = state_last.find(key);
+
+            if (state_last_it != state_last.end())
+                odom_state.emplace(key, state_last_it->second);
+
+            else
+                odom_state.emplace(key, stateZero(string(1,key)).at(key));
+        }
+    }
+
+    return odom_state;
+}
+
 SizeEigen Problem::getDim() const
 {
     return dim_;
@@ -562,23 +606,40 @@ void Problem::setTreeManager(TreeManagerBasePtr _gm)
 
 }
 
-void Problem::addProcessorIsMotion(IsMotionPtr _processor_motion_ptr)
+void Problem::addProcessorIsMotion(IsMotionPtr _is_motion_ptr)
 {
-    processor_is_motion_list_.push_back(_processor_motion_ptr);
-    appendToStructure(_processor_motion_ptr->getStateStructure());
+    // Check if is state getter
+    if (not _is_motion_ptr->isStateGetter())
+    {
+        WOLF_WARN("Problem::addProcessorIsMotion: adding a IsMotion processor with state_getter=false. Not adding this processor");
+        return;
+    }
+
+    // check duplicated priority
+    while (processor_is_motion_map_.count(_is_motion_ptr->getStatePriority()) == 1)
+    {
+        WOLF_ERROR("Problem::addProcessorIsMotion: adding a IsMotion processor with priority = ",
+                   _is_motion_ptr->getStatePriority(),
+                   " which is already taken. Trying to add it with priority = ",
+                   _is_motion_ptr->getStatePriority()+1);
+        _is_motion_ptr->setStatePriority(_is_motion_ptr->getStatePriority()+1);
+    }
+
+    // add to map ordered by priority
+    processor_is_motion_map_.emplace(_is_motion_ptr->getStatePriority(), _is_motion_ptr);
+    appendToStructure(_is_motion_ptr->getStateStructure());
 }
 
-void Problem::clearProcessorIsMotion(IsMotionPtr proc)
+void Problem::removeProcessorIsMotion(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);
-    }
+    WOLF_WARN_COND(processor_is_motion_map_.count(proc->getStatePriority()) == 0, "Problem::clearProcessorIsMotion: missing processor");
+
+    processor_is_motion_map_.erase(proc->getStatePriority());
 
     // rebuild frame structure with remaining motion processors
     frame_structure_.clear();
-    for (const auto& pm : processor_is_motion_list_)
-        appendToStructure(pm->getStateStructure());
+    for (const auto& pm : processor_is_motion_map_)
+        appendToStructure(pm.second->getStateStructure());
 }
 
 VectorComposite Problem::stateZero ( const StateStructure& _structure ) const
@@ -962,6 +1023,7 @@ void Problem::setPriorOptions(const std::string& _mode,
     if (prior_options_->mode != "nothing")
     {
         assert(_time_tolerance > 0 && "time tolerance should be bigger than 0");
+        assert(_state.includesStructure(frame_structure_) && "any missing key in prior state");
 
         WOLF_TRACE("prior state:          ", _state);
         WOLF_TRACE("prior time tolerance: ", _time_tolerance);
@@ -970,11 +1032,13 @@ void Problem::setPriorOptions(const std::string& _mode,
 
         if (prior_options_->mode == "factor")
         {
+            assert(_sigma.includesStructure(frame_structure_) && "any missing key in prior sigma");
+
             bool isPositive = true;
             for(const auto& it: _sigma)
                 isPositive = isPositive and (it.second.array() > Constants::EPS).all();
 
-            assert(isPositive && "sigma is not positive");
+            assert(isPositive && "prior sigma is not positive");
 
             MatrixComposite Q;
             for (const auto& pair_key_sig : _sigma)
@@ -999,8 +1063,11 @@ FrameBasePtr Problem::applyPriorOptions(const TimeStamp& _ts)
 
     if (prior_options_->mode != "nothing" and prior_options_->mode != "")
     {
-        prior_keyframe = emplaceFrame(_ts,
-                                         prior_options_->state);
+        prior_keyframe = emplaceFrame(_ts, frame_structure_, prior_options_->state);
+
+        // Update origin for odometry processors
+        for (auto proc_pair : processor_is_motion_map_)
+            proc_pair.second->setOdometry(prior_options_->state);
 
         if (prior_options_->mode == "fix")
             prior_keyframe->fix();
diff --git a/src/processor/is_motion.cpp b/src/processor/is_motion.cpp
index a17142e80bf69198674b29f0dc5f3bde955412a4..b3a510472087094a38682081e7d27cd3b00a07b6 100644
--- a/src/processor/is_motion.cpp
+++ b/src/processor/is_motion.cpp
@@ -5,6 +5,20 @@ using namespace wolf;
 
 void IsMotion::addToProblem(ProblemPtr _prb_ptr, IsMotionPtr _motion_ptr)
 {
+    if (not isStateGetter())
+    {
+        WOLF_WARN("IsMotion::addToProblem: IsMotion processor with state_getter=false. Not adding this processor");
+        return;
+    }
     setOdometry(_prb_ptr->stateZero(state_structure_));
     _prb_ptr->addProcessorIsMotion(_motion_ptr);
 }
+
+void IsMotion::setOdometry(const VectorComposite& _odom)
+{
+    assert(_odom.includesStructure(state_structure_) && "IsMotion::setOdometry(): provided odom has not any key.");
+
+    for (auto key : state_structure_)
+        if (_odom.count(key) != 0)
+            odometry_[key] = _odom.at(key); //overwrite or insert only keys of the state_structure_
+}
diff --git a/src/processor/processor_base.cpp b/src/processor/processor_base.cpp
index e8f891b8c51098909b5db479f7e3d3a8139457c0..794699f4533a7d2f5e6271e8f31b05b0b36cbd69 100644
--- a/src/processor/processor_base.cpp
+++ b/src/processor/processor_base.cpp
@@ -91,7 +91,7 @@ void ProcessorBase::remove()
             ProblemPtr P = getProblem();
             auto this_proc_cast_attempt = std::dynamic_pointer_cast<IsMotion>( shared_from_this() );
             if(P && this_proc_cast_attempt )
-                P->clearProcessorIsMotion(this_proc_cast_attempt);
+                P->removeProcessorIsMotion(this_proc_cast_attempt);
         }
 
         // remove from upstream
diff --git a/src/processor/processor_motion.cpp b/src/processor/processor_motion.cpp
index 2fb9f2bab8cbd88b5239a72168610decda30c38f..17aa676f434d049875ecd8405c842b5ec95d1653 100644
--- a/src/processor/processor_motion.cpp
+++ b/src/processor/processor_motion.cpp
@@ -23,7 +23,7 @@ ProcessorMotion::ProcessorMotion(const std::string& _type,
                                  SizeEigen _calib_size,
                                  ParamsProcessorMotionPtr _params_motion) :
         ProcessorBase(_type, _dim, _params_motion),
-        IsMotion(_state_structure),
+        IsMotion(_state_structure, _params_motion),
         params_motion_(_params_motion),
         processing_step_(RUNNING_WITHOUT_KF),
         x_size_(_state_size),
diff --git a/src/state_block/state_composite.cpp b/src/state_block/state_composite.cpp
index 0f4efab6f1f093d8f1425d0855a453c6370f1c93..169bc82ca8edd1fa751bac1e309aa2ce1eb95379 100644
--- a/src/state_block/state_composite.cpp
+++ b/src/state_block/state_composite.cpp
@@ -81,6 +81,14 @@ Eigen::VectorXd VectorComposite::vector(const StateStructure &_structure) const
     return x;
 }
 
+bool VectorComposite::includesStructure(const StateStructure &_structure) const
+{
+    for (auto key : _structure)
+        if (count(key) == 0)
+            return false;
+    return true;
+}
+
 std::ostream& operator <<(std::ostream &_os, const wolf::VectorComposite &_x)
 {
     for (const auto &pair_key_vec : _x)
diff --git a/src/tree_manager/tree_manager_sliding_window_dual_rate.cpp b/src/tree_manager/tree_manager_sliding_window_dual_rate.cpp
index 54fadc44d8ac752f8d522374e9ccdb8812241585..c590c4b718504cfd357a15df2bdc27f379a9deea 100644
--- a/src/tree_manager/tree_manager_sliding_window_dual_rate.cpp
+++ b/src/tree_manager/tree_manager_sliding_window_dual_rate.cpp
@@ -31,11 +31,17 @@ void TreeManagerSlidingWindowDualRate::keyFrameCallback(FrameBasePtr _frame)
                                                         params_swdr_->n_frames_recent - 1)->second;
 
         // compose motion captures for all processors motion
-        for (auto is_motion : getProblem()->getProcessorIsMotionList())
+        for (auto is_motion_pair : getProblem()->getProcessorIsMotionMap())
         {
-            auto proc_motion = std::dynamic_pointer_cast<ProcessorMotion>(is_motion);
+            auto proc_motion = std::dynamic_pointer_cast<ProcessorMotion>(is_motion_pair.second);
             if (proc_motion == nullptr)
+            {
+                // FIXME: IsMotion::mergeCaptures pure virtual in IsMotion without need of casting
+                WOLF_INFO("TreeManagerSlidingWindowDualRate::keyFrameCallback: IsMotion ",
+                          std::dynamic_pointer_cast<ProcessorBase>(is_motion_pair.second)->getName(),
+                          " couldn't be casted to ProcessorMotion. Not merging its captures...");
                 continue;
+            }
 
             auto cap_prev = std::static_pointer_cast<CaptureMotion>(remove_recent_frame->getCaptureOf(proc_motion->getSensor()));
             auto cap_next = std::static_pointer_cast<CaptureMotion>(keep_recent_frame->getCaptureOf(proc_motion->getSensor()));
diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt
index 885c1f53a456deb4b74392d011d560cb7216bafe..8a5eb8fa3a068dca72974a86bdcdee1fd9453baf 100644
--- a/test/CMakeLists.txt
+++ b/test/CMakeLists.txt
@@ -84,6 +84,10 @@ target_link_libraries(gtest_frame_base ${PLUGIN_NAME})
 wolf_add_gtest(gtest_has_state_blocks gtest_has_state_blocks.cpp)
 target_link_libraries(gtest_has_state_blocks ${PLUGIN_NAME})
 
+# IsMotion classes test
+wolf_add_gtest(gtest_is_motion gtest_is_motion.cpp)
+target_link_libraries(gtest_is_motion ${PLUGIN_NAME})
+
 # LocalParametrizationXxx classes test
 wolf_add_gtest(gtest_local_param gtest_local_param.cpp)
 target_link_libraries(gtest_local_param ${PLUGIN_NAME})
diff --git a/test/dummy/processor_is_motion_dummy.h b/test/dummy/processor_is_motion_dummy.h
new file mode 100644
index 0000000000000000000000000000000000000000..dca4808c90602d550156a9e486514480b2c7f6b1
--- /dev/null
+++ b/test/dummy/processor_is_motion_dummy.h
@@ -0,0 +1,76 @@
+/*
+ * processor_is_motion_dummy.h
+ *
+ *  Created on: Mar 8, 2021
+ *      Author: joanvallve
+ */
+
+#ifndef TEST_DUMMY_PROCESSOR_IS_MOTION_DUMMY_H_
+#define TEST_DUMMY_PROCESSOR_IS_MOTION_DUMMY_H_
+
+#include "core/processor/processor_base.h"
+#include "core/processor/is_motion.h"
+
+namespace wolf
+{
+
+WOLF_STRUCT_PTR_TYPEDEFS(ParamsProcessorIsMotionDummy);
+
+struct ParamsProcessorIsMotionDummy : public ParamsProcessorBase, public ParamsIsMotion
+{
+        std::string state_structure = "PO";
+
+        ParamsProcessorIsMotionDummy() = default;
+        ParamsProcessorIsMotionDummy(std::string _unique_name, const ParamsServer& _server):
+            ParamsProcessorBase(_unique_name, _server),
+            ParamsIsMotion(_unique_name, _server)
+        {
+
+        };
+};
+
+WOLF_PTR_TYPEDEFS(ProcessorIsMotionDummy);
+
+class ProcessorIsMotionDummy : public ProcessorBase, public IsMotion
+{
+    public:
+        ProcessorIsMotionDummy(ParamsProcessorIsMotionDummyPtr _params) :
+            ProcessorBase("ProcessorIsMotionDummy", 2, _params),
+            IsMotion(_params->state_structure, _params)
+        {}
+        ~ProcessorIsMotionDummy(){};
+
+        // Factory method for high level API
+        WOLF_PROCESSOR_CREATE(ProcessorIsMotionDummy, ParamsProcessorIsMotionDummy);
+
+        void configure(SensorBasePtr _sensor) override {};
+        void processCapture(CaptureBasePtr) override {};
+        void processKeyFrame(FrameBasePtr _keyframe_ptr, const double& _time_tolerance) override {};
+        bool triggerInCapture(CaptureBasePtr) const override { return false; };
+        bool triggerInKeyFrame(FrameBasePtr _keyframe_ptr, const double& _time_tolerance) const override { return false; };
+        bool storeKeyFrame(FrameBasePtr) override { return false; };
+        bool storeCapture(CaptureBasePtr) override { return false; };
+        bool voteForKeyFrame() const override { return false; };
+        TimeStamp getTimeStamp() const override {return TimeStamp(0);};
+
+        VectorComposite getState(const StateStructure& _structure = "") const override
+        {
+            return getOdometry();
+        };
+
+        VectorComposite getState(const TimeStamp& _ts, const StateStructure& _structure = "") const override
+        {
+            return getOdometry();
+        };
+};
+
+} /* namespace wolf */
+
+// Register in the FactoryProcessor
+#include "core/processor/factory_processor.h"
+namespace wolf {
+WOLF_REGISTER_PROCESSOR(ProcessorIsMotionDummy);
+WOLF_REGISTER_PROCESSOR_AUTO(ProcessorIsMotionDummy);
+} // namespace wolf
+
+#endif /* TEST_DUMMY_PROCESSOR_IS_MOTION_DUMMY_H_ */
diff --git a/test/gtest_is_motion.cpp b/test/gtest_is_motion.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..0c8b8fa620a1f8b5261d9a5ca13a6299c896d6d9
--- /dev/null
+++ b/test/gtest_is_motion.cpp
@@ -0,0 +1,185 @@
+//Wolf
+#include "core/utils/utils_gtest.h"
+
+#include "core/processor/is_motion.h"
+#include "dummy/processor_is_motion_dummy.h"
+#include "core/sensor/sensor_odom_2d.h"
+
+#include "core/problem/problem.h"
+
+// STL
+#include <iterator>
+#include <iostream>
+
+using namespace wolf;
+using namespace Eigen;
+
+
+class IsMotionTest : public testing::Test
+{
+    public:
+        ProblemPtr problem;
+        SensorBasePtr sen;
+        ProcessorBasePtr prc1, prc2, prc3;
+        IsMotionPtr im1, im2, im3;
+
+        std::string wolf_root = _WOLF_ROOT_DIR;
+        double dt = 0.01;
+
+        void SetUp() override
+        {
+            // Wolf problem
+            problem = Problem::create("POV", 2);
+
+            // Install odom sensor
+            sen = problem->installSensor("SensorOdom2d",
+                                         "odometer",
+                                         Vector3d(0,0,0),
+                                         wolf_root + "/test/yaml/sensor_odom_2d.yaml");
+
+            // Install 3 odom processors
+            ParamsProcessorIsMotionDummyPtr prc1_params = std::make_shared<ParamsProcessorIsMotionDummy>();
+            prc1_params->time_tolerance = dt/2;
+            prc1_params->state_structure = "PO";
+            prc1_params->state_getter = false;
+            prc1 = problem->installProcessor("ProcessorIsMotionDummy",
+                                             "not getter processor",
+                                             sen,
+                                             prc1_params);
+            im1 = std::dynamic_pointer_cast<IsMotion>(prc1);
+
+            ParamsProcessorIsMotionDummyPtr prc2_params = std::make_shared<ParamsProcessorIsMotionDummy>();
+            prc2_params->time_tolerance = dt/2;
+            prc2_params->state_structure = "PO";
+            prc2_params->state_getter = true;
+            prc2_params->state_priority = 1;
+            prc2 = problem->installProcessor("ProcessorIsMotionDummy",
+                                             "getter processor",
+                                             sen,
+                                             prc2_params);
+            im2 = std::dynamic_pointer_cast<IsMotion>(prc2);
+
+            ParamsProcessorIsMotionDummyPtr prc3_params = std::make_shared<ParamsProcessorIsMotionDummy>();
+            prc3_params->time_tolerance = dt/2;
+            prc3_params->state_structure = "POV";
+            prc3_params->state_getter = true;
+            prc3_params->state_priority = 1;
+            prc3 = problem->installProcessor("ProcessorIsMotionDummy",
+                                             "getter processor low priority",
+                                             sen,
+                                             prc3_params);
+            im3 = std::dynamic_pointer_cast<IsMotion>(prc3);
+        }
+};
+
+/*
+ * Things to be tested:
+ * - state_getter
+ * - state_priority
+ * - Duplicated priority (Problem handles this)
+ * - setOdometry (stateStructures)
+ * - getOdomtry
+ * - Problem::getState/getOdometry (state_getter, state_priority)
+ */
+
+TEST_F(IsMotionTest, install)
+{
+    // All isMotion() = true
+    ASSERT_TRUE (prc1->isMotion());
+    ASSERT_TRUE (prc2->isMotion());
+    ASSERT_TRUE (prc3->isMotion());
+    ASSERT_TRUE (im1 != nullptr);
+    ASSERT_TRUE (im2 != nullptr);
+    ASSERT_TRUE (im3 != nullptr);
+
+    // well configured
+    ASSERT_FALSE(im1->isStateGetter());
+    ASSERT_TRUE(im2->isStateGetter());
+    ASSERT_TRUE(im3->isStateGetter());
+    ASSERT_EQ(im2->getStatePriority(), 1);
+    ASSERT_EQ(im3->getStatePriority(), 2); // If duplicated priority, 2nd is changed to +1 priority. A WARN should be raised.
+    ASSERT_EQ(im1->getStateStructure(), "PO");
+    ASSERT_EQ(im2->getStateStructure(), "PO");
+    ASSERT_EQ(im3->getStateStructure(), "POV");
+
+    // Only 2 and 3 in problem::processor_is_motion_map_
+    ASSERT_EQ(problem->getProcessorIsMotionMap().size(), 2);
+    ASSERT_EQ(problem->getProcessorIsMotionMap().begin()->second, im2);
+    ASSERT_EQ(std::next(problem->getProcessorIsMotionMap().begin())->second, im3);
+}
+
+TEST_F(IsMotionTest, odometry)
+{
+    VectorComposite odom_p("P"); // missing P key
+    odom_p['P'] = Vector2d::Zero();
+    VectorComposite odom_pov("POV"); // key V not needed by prc1 and prc2
+    odom_pov['P'] = Vector2d::Zero();
+    odom_pov['O'] = Vector1d::Zero();
+    odom_pov['V'] = Vector2d::Zero();
+
+    // Error: required PO keys to be added
+    ASSERT_DEATH({im1->setOdometry(odom_p);},"");
+    im1->setOdometry(odom_pov);
+    im2->setOdometry(odom_pov);
+    im3->setOdometry(odom_pov);
+
+    // im1 ->set odom = 0, 0, 0
+    VectorComposite odom1("PO");
+    odom1['P'] = Vector2d::Zero();
+    odom1['O'] = Vector1d::Zero();
+    im1->setOdometry(odom1);
+    auto odom1_get = im1->getOdometry();
+    EXPECT_TRUE(odom1_get.count('P') == 1);
+    EXPECT_TRUE(odom1_get.count('O') == 1);
+    EXPECT_MATRIX_APPROX(odom1_get.at('P'), odom1.at('P'), 1e-9);
+    EXPECT_MATRIX_APPROX(odom1_get.at('O'), odom1.at('O'), 1e-9);
+
+    // im1 ->set odom = 1, 1, 1
+    VectorComposite odom2("PO");
+    odom2['P'] = Vector2d::Ones();
+    odom2['O'] = Vector1d::Ones();
+    im2->setOdometry(odom2);
+    auto odom2_get = im2->getOdometry();
+    EXPECT_TRUE(odom2_get.count('P') == 1);
+    EXPECT_TRUE(odom2_get.count('O') == 1);
+    EXPECT_MATRIX_APPROX(odom2_get.at('P'), odom2.at('P'), 1e-9);
+    EXPECT_MATRIX_APPROX(odom2_get.at('O'), odom2.at('O'), 1e-9);
+
+    // im1 ->set odom = 2, 2, 2, 2, 2
+    VectorComposite odom3("POV");
+    odom3['P'] = 2 * Vector2d::Ones();
+    odom3['O'] = 2 * Vector1d::Ones();
+    odom3['V'] = 2 * Vector2d::Ones();
+    im3->setOdometry(odom3);
+    auto odom3_get = im3->getOdometry();
+    EXPECT_TRUE(odom3_get.count('P') == 1);
+    EXPECT_TRUE(odom3_get.count('O') == 1);
+    EXPECT_TRUE(odom3_get.count('V') == 1);
+    EXPECT_MATRIX_APPROX(odom3_get.at('P'), odom3.at('P'), 1e-9);
+    EXPECT_MATRIX_APPROX(odom3_get.at('O'), odom3.at('O'), 1e-9);
+    EXPECT_MATRIX_APPROX(odom3_get.at('V'), odom3.at('V'), 1e-9);
+
+    // problem::getOdometry(): by priority P and O should come from im2 and V from im3
+    auto odom_get = problem->getOdometry();
+    EXPECT_TRUE(odom_get.count('P') == 1);
+    EXPECT_TRUE(odom_get.count('O') == 1);
+    EXPECT_TRUE(odom_get.count('V') == 1);
+    EXPECT_MATRIX_APPROX(odom_get.at('P'), odom2.at('P'), 1e-9);
+    EXPECT_MATRIX_APPROX(odom_get.at('O'), odom2.at('O'), 1e-9);
+    EXPECT_MATRIX_APPROX(odom_get.at('V'), odom3.at('V'), 1e-9);
+
+    // problem::getState(): by priority P and O should come from im2 and V from im3
+    auto state_get = problem->getState();
+    EXPECT_TRUE(state_get.count('P') == 1);
+    EXPECT_TRUE(state_get.count('O') == 1);
+    EXPECT_TRUE(state_get.count('V') == 1);
+    EXPECT_MATRIX_APPROX(state_get.at('P'), odom2.at('P'), 1e-9);
+    EXPECT_MATRIX_APPROX(state_get.at('O'), odom2.at('O'), 1e-9);
+    EXPECT_MATRIX_APPROX(state_get.at('V'), odom3.at('V'), 1e-9);
+}
+
+int main(int argc, char **argv)
+{
+  testing::InitGoogleTest(&argc, argv);
+  return RUN_ALL_TESTS();
+}
diff --git a/test/gtest_processor_base.cpp b/test/gtest_processor_base.cpp
index c3277078df9300439a6dee3721f0084df9751522..4497954899991b26100d23af38130e8218ed4a14 100644
--- a/test/gtest_processor_base.cpp
+++ b/test/gtest_processor_base.cpp
@@ -48,10 +48,16 @@ TEST(ProcessorBase, IsMotion)
     auto proc_trk = problem->installProcessor("ProcessorTrackerFeatureDummy",  "dummy", sens_trk);
 
     // Install odometer (sensor and processor)
-    SensorBasePtr sens_odo = problem->installSensor("SensorOdom2d", "odometer", Vector3d(0,0,0), wolf_root + "/test/yaml/sensor_odom_2d.yaml");
+    SensorBasePtr sens_odo = problem->installSensor("SensorOdom2d",
+                                                    "odometer",
+                                                    Vector3d(0,0,0),
+                                                    wolf_root + "/test/yaml/sensor_odom_2d.yaml");
     ParamsProcessorOdom2dPtr proc_odo_params = make_shared<ParamsProcessorOdom2d>();
     proc_odo_params->time_tolerance = dt/2;
-    ProcessorBasePtr proc_odo = problem->installProcessor("ProcessorOdom2d", "odom processor", sens_odo, proc_odo_params);
+    ProcessorBasePtr proc_odo = problem->installProcessor("ProcessorOdom2d",
+                                                          "odom processor",
+                                                          sens_odo,
+                                                          proc_odo_params);
 
     ASSERT_FALSE(proc_trk->isMotion());
     ASSERT_TRUE (proc_odo->isMotion());
diff --git a/test/yaml/params_problem_odom_3d.yaml b/test/yaml/params_problem_odom_3d.yaml
index 7e0b0ccb110c0545ff24a9726c035124f0d1686a..6c5ed47c2efc2afc3ba960b075e60cea73b58a73 100644
--- a/test/yaml/params_problem_odom_3d.yaml
+++ b/test/yaml/params_problem_odom_3d.yaml
@@ -41,3 +41,6 @@ config:
         angle_turned:           999   # radians (1 rad approx 57 deg, approx 60 deg)
       
       unmeasured_perturbation_std: 0.00111
+      
+      state_getter: true
+      state_priority: 1
diff --git a/test/yaml/params_tree_manager1.yaml b/test/yaml/params_tree_manager1.yaml
index 6a69b63a6918e13b0f492c7b51ef6dfe3c97ba94..fa43fecb397dff295b683cfcd6a282adac61cc44 100644
--- a/test/yaml/params_tree_manager1.yaml
+++ b/test/yaml/params_tree_manager1.yaml
@@ -46,3 +46,7 @@ config:
         angle_turned:           0.1   # radians (1 rad approx 57 deg, approx 60 deg)
       
       unmeasured_perturbation_std: 0.00111
+      
+      state_getter: true
+      state_priority: 1
+      
diff --git a/test/yaml/params_tree_manager2.yaml b/test/yaml/params_tree_manager2.yaml
index 879421e7915581f52355d1874ebb78f302b768df..f37e31459d9a883aca9eb12898aa5ac285e63210 100644
--- a/test/yaml/params_tree_manager2.yaml
+++ b/test/yaml/params_tree_manager2.yaml
@@ -45,3 +45,7 @@ config:
         angle_turned:           0.1   # radians (1 rad approx 57 deg, approx 60 deg)
       
       unmeasured_perturbation_std: 0.00111
+      
+      state_getter: true
+      state_priority: 1
+      
diff --git a/test/yaml/params_tree_manager_sliding_window1.yaml b/test/yaml/params_tree_manager_sliding_window1.yaml
index 704e8530ed2c8b8eb99ac35c29c36f62d01a3fb4..277810464d6f619ed342ce3706bec30d7ca8e5f9 100644
--- a/test/yaml/params_tree_manager_sliding_window1.yaml
+++ b/test/yaml/params_tree_manager_sliding_window1.yaml
@@ -44,3 +44,7 @@ config:
         angle_turned:           0.1   # radians (1 rad approx 57 deg, approx 60 deg)
       
       unmeasured_perturbation_std: 0.00111
+      
+      state_getter: true
+      state_priority: 1
+      
diff --git a/test/yaml/params_tree_manager_sliding_window2.yaml b/test/yaml/params_tree_manager_sliding_window2.yaml
index 701fc6fbfb71e35c800563224cf7a86cce6d846b..f22fdde12f065d17accb122ef7f8d1728ef6fb6c 100644
--- a/test/yaml/params_tree_manager_sliding_window2.yaml
+++ b/test/yaml/params_tree_manager_sliding_window2.yaml
@@ -44,3 +44,7 @@ config:
         angle_turned:           0.1   # radians (1 rad approx 57 deg, approx 60 deg)
       
       unmeasured_perturbation_std: 0.00111
+      
+      state_getter: true
+      state_priority: 1
+      
diff --git a/test/yaml/params_tree_manager_sliding_window_dual_rate3.yaml b/test/yaml/params_tree_manager_sliding_window_dual_rate3.yaml
index 47d81f409a5ed09d37ba3b307c2fb23152759791..8f00f6499df2c96c9993bd6c486554579e7fbab9 100644
--- a/test/yaml/params_tree_manager_sliding_window_dual_rate3.yaml
+++ b/test/yaml/params_tree_manager_sliding_window_dual_rate3.yaml
@@ -52,3 +52,7 @@ config:
         angle_turned:           3.1   # radians (1 rad approx 57 deg, approx 60 deg)
       
       unmeasured_perturbation_std: 0.00111
+      
+      state_getter: true
+      state_priority: 1
+      
diff --git a/test/yaml/params_tree_manager_sliding_window_dual_rate_baseline.yaml b/test/yaml/params_tree_manager_sliding_window_dual_rate_baseline.yaml
index 494d27be3f0b9e3c68ef33919451a0f7e6ba065c..114e865bdc3a86b6d0cddf42e0f5360b7b2d5928 100644
--- a/test/yaml/params_tree_manager_sliding_window_dual_rate_baseline.yaml
+++ b/test/yaml/params_tree_manager_sliding_window_dual_rate_baseline.yaml
@@ -46,3 +46,6 @@ config:
         angle_turned:           3.1   # radians (1 rad approx 57 deg, approx 60 deg)
       
       unmeasured_perturbation_std: 0.00111
+      
+      state_getter: true
+      state_priority: 1