diff --git a/include/core/problem/problem.h b/include/core/problem/problem.h
index 3ba49645c9c81613e3cc32855ca16786dd17dcd9..3d0eba08b8e234a1adcd3ab4bd00a149e10e6f65 100644
--- a/include/core/problem/problem.h
+++ b/include/core/problem/problem.h
@@ -178,10 +178,8 @@ class Problem : public std::enable_shared_from_this<Problem>
 
     public:
         IsMotionPtr getProcessorIsMotion();
-        std::map<int,IsMotionPtr> getProcessorIsMotionMap();
-        
-
-
+        std::map<int,IsMotionPtr>& getProcessorIsMotionMap();
+        const std::map<int,IsMotionPtr>& getProcessorIsMotionMap() const;
 
         // Trajectory branch ----------------------------------
         TrajectoryBasePtr getTrajectory() const;
@@ -437,8 +435,12 @@ inline IsMotionPtr Problem::getProcessorIsMotion()
     return nullptr;
 }
 
+inline std::map<int,IsMotionPtr>& Problem::getProcessorIsMotionMap()
+{
+    return processor_is_motion_map_;
+}
 
-inline std::map<int,IsMotionPtr> Problem::getProcessorIsMotionMap()
+inline const std::map<int,IsMotionPtr>& Problem::getProcessorIsMotionMap() const
 {
     return processor_is_motion_map_;
 }
diff --git a/src/processor/is_motion.cpp b/src/processor/is_motion.cpp
index 4309f6a68fb889ac2151b5e33c6429d80ce23b9b..b3a510472087094a38682081e7d27cd3b00a07b6 100644
--- a/src/processor/is_motion.cpp
+++ b/src/processor/is_motion.cpp
@@ -14,9 +14,11 @@ void IsMotion::addToProblem(ProblemPtr _prb_ptr, IsMotionPtr _motion_ptr)
     _prb_ptr->addProcessorIsMotion(_motion_ptr);
 }
 
-void IsMotion::setOdometry(const VectorComposite& _zero_odom)
+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 (_zero_odom.count(key) != 0)
-            odometry_[key] = _zero_odom.at(key); //overwrite or insert only keys of the state_structure_
+        if (_odom.count(key) != 0)
+            odometry_[key] = _odom.at(key); //overwrite or insert only keys of the state_structure_
 }
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());