diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
index 58aab197f8174e67b584742198ea2ce8fd88e1cb..249b84e5c1902743a60b5ad0665318b4b622bc1a 100644
--- a/.gitlab-ci.yml
+++ b/.gitlab-ci.yml
@@ -88,8 +88,6 @@ license_header:
 build_and_test:bionic:
   stage: build_and_test
   image: labrobotica/wolf_deps:18.04
-  except:
-    - master
   script:
     - *build_and_test_definition
 
@@ -97,8 +95,6 @@ build_and_test:bionic:
 build_and_test:focal:
   stage: build_and_test
   image: labrobotica/wolf_deps:20.04
-  except:
-    - master
   script:
     - *build_and_test_definition
 
@@ -110,6 +106,7 @@ deploy_imu:
     DEPLOY_CI_ROS: "false"
   trigger: 
     project: mobile_robotics/wolf_projects/wolf_lib/plugins/imu
+    branch: $WOLF_IMU_BRANCH
     strategy: depend
 
 deploy_gnss:
@@ -119,6 +116,7 @@ deploy_gnss:
     DEPLOY_CI_ROS: "false"
   trigger: 
     project: mobile_robotics/wolf_projects/wolf_lib/plugins/gnss
+    branch: $WOLF_GNSS_BRANCH
     strategy: depend
 
 deploy_vision:
@@ -128,6 +126,7 @@ deploy_vision:
     DEPLOY_CI_ROS: "false"
   trigger: 
     project: mobile_robotics/wolf_projects/wolf_lib/plugins/vision
+    branch: $WOLF_VISION_BRANCH
     strategy: depend
 
 deploy_laser:
@@ -137,6 +136,7 @@ deploy_laser:
     DEPLOY_CI_ROS: "false"
   trigger: 
     project: mobile_robotics/wolf_projects/wolf_lib/plugins/laser
+    branch: $WOLF_LASER_BRANCH
     strategy: depend
 
 deploy_apriltag:
@@ -146,6 +146,7 @@ deploy_apriltag:
     DEPLOY_CI_ROS: "false"
   trigger: 
     project: mobile_robotics/wolf_projects/wolf_lib/plugins/apriltag
+    branch: $WOLF_APRILTAG_BRANCH
     strategy: depend
 
 deploy_bodydynamics:
@@ -155,6 +156,7 @@ deploy_bodydynamics:
     DEPLOY_CI_ROS: "false"
   trigger: 
     project: mobile_robotics/wolf_projects/wolf_lib/plugins/bodydynamics
+    branch: $WOLF_BODYDYNAMICS_BRANCH
     strategy: depend
 
 ############ WAIT FOR PLUGINS ############
@@ -177,7 +179,6 @@ deploy_wolf_ros_node:
     WOLF_VISION_BRANCH: $WOLF_VISION_BRANCH
     WOLF_APRILTAG_BRANCH: $WOLF_APRILTAG_BRANCH
     WOLF_BODYDYNAMICS_BRANCH: $WOLF_BODYDYNAMICS_BRANCH
-    WOLF_ROS_CORE_BRANCH: $WOLF_ROS_CORE_BRANCH
     WOLF_ROS_IMU_BRANCH: $WOLF_ROS_IMU_BRANCH
     WOLF_ROS_GNSS_BRANCH: $WOLF_ROS_GNSS_BRANCH
     WOLF_ROS_LASER_BRANCH: $WOLF_ROS_LASER_BRANCH
@@ -186,6 +187,7 @@ deploy_wolf_ros_node:
     WOLF_ROS_BODYDYNAMICS_BRANCH: $WOLF_ROS_BODYDYNAMICS_BRANCH
   trigger: 
     project: mobile_robotics/wolf_projects/wolf_ros/wolf_ros_node
+    branch: $WOLF_ROS_CORE_BRANCH
 
 no_deploy_wolf_ros_node:
   stage: deploy_ros
diff --git a/demos/hello_wolf/hello_wolf_autoconf.cpp b/demos/hello_wolf/hello_wolf_autoconf.cpp
index db934ca13174443de5053e3a427206de41799c18..27214245096f91fefad1351f611613516010f40a 100644
--- a/demos/hello_wolf/hello_wolf_autoconf.cpp
+++ b/demos/hello_wolf/hello_wolf_autoconf.cpp
@@ -138,8 +138,8 @@ int main()
     SolverManagerPtr ceres = FactorySolver::create("SolverCeres", problem, server);
 
     // recover sensor pointers and other stuff for later use (access by sensor name)
-    SensorBasePtr sensor_odo    = problem->getSensor("sen odom");
-    SensorBasePtr sensor_rb     = problem->getSensor("sen rb");
+    SensorBasePtr sensor_odo    = problem->findSensor("sen odom");
+    SensorBasePtr sensor_rb     = problem->findSensor("sen rb");
 
     // APPLY PRIOR and SET PROCESSOR ODOM ORIGIN ===================================================
     TimeStamp     t(0.0);
diff --git a/include/core/problem/problem.h b/include/core/problem/problem.h
index 7405ae8320deb339ed6efdfe7319b4df8ec14cff..08a7ab52fd0598315adf2b9150ad80efd77043d0 100644
--- a/include/core/problem/problem.h
+++ b/include/core/problem/problem.h
@@ -151,7 +151,11 @@ class Problem : public std::enable_shared_from_this<Problem>
         /** \brief get a sensor pointer by its name
          * \param _sensor_name The sensor name, as it was installed with installSensor()
          */
-        SensorBasePtr getSensor(const std::string& _sensor_name) const;
+        SensorBasePtr findSensor(const std::string& _sensor_name) const;
+        /** \brief get a processor pointer by its name
+         * \param _processor_name The processor name, as it was installed with installProcessor()
+         */
+        ProcessorBasePtr findProcessor(const std::string& _processor_name) const;
 
         /** \brief Factory method to install (create, and add to sensor) processors only from its properties
          *
diff --git a/include/core/processor/track_matrix.h b/include/core/processor/track_matrix.h
index 87511440e721baf20d2b3aa05123f0499caa4c84..e60a59f8233abb7fade714f20cbabc417a76e091 100644
--- a/include/core/processor/track_matrix.h
+++ b/include/core/processor/track_matrix.h
@@ -119,11 +119,13 @@ class TrackMatrix
         FeatureBasePtr  feature     (const SizeStd& _track_id, CaptureBasePtr _cap) const;
         CaptureBasePtr  firstCapture(const SizeStd& _track_id) const;
 
+        list<size_t>    trackIds() const;
+
         // tracks across captures that belong to keyframe
-//        SizeStd         numKeyframeTracks();
         Track           trackAtKeyframes(size_t _track_id) const;
-//        bool            markKeyframe(CaptureBasePtr _capture);
-//        bool            unmarkKeyframe(CaptureBasePtr _capture);
+
+        const map<SizeStd, Track>& getTracks() const {return tracks_;}
+        const map<CaptureBasePtr, Snapshot >& getSnapshots() const {return snapshots_;}
 
     private:
 
@@ -131,8 +133,6 @@ class TrackMatrix
 
         // tracks across all Captures
         map<SizeStd, Track > tracks_;       // map indexed by track_Id   of ( maps indexed by TimeStamp  of ( features ) )
-//        // tracks across captures that belong to keyframe
-//        map<size_t, Track > tracks_kf_;    // map indexed by track_Id   of ( maps indexed by TimeStamp  of ( features ) )
 
         // Across track: maps of Feature pointers indexed by track_Id.
         map<CaptureBasePtr, Snapshot > snapshots_; // map indexed by capture_ptr of ( maps indexed by track_Id of ( features ) )
diff --git a/include/core/state_block/state_quaternion.h b/include/core/state_block/state_quaternion.h
index 4200f81f7e3faac814a45bea8995a13436b6b7c3..f22772908c411fba8a096fb764af40fe6b39316e 100644
--- a/include/core/state_block/state_quaternion.h
+++ b/include/core/state_block/state_quaternion.h
@@ -51,12 +51,19 @@ class StateQuaternion : public StateBlock
 inline StateQuaternion::StateQuaternion(const Eigen::Quaterniond& _quaternion, bool _fixed) :
         StateBlock(_quaternion.coeffs(), _fixed, std::make_shared<LocalParametrizationQuaternion<DQ_LOCAL>>())
 {
+    // TODO: remove these lines after issue #381 is addressed
+    assert(isValid(1e-5)  && "Quaternion unit norm is worse than 1e-5 tolerance!");
+    state_.normalize();
 }
 
 inline StateQuaternion::StateQuaternion(const Eigen::VectorXd& _state, bool _fixed) :
         StateBlock(_state, _fixed, std::make_shared<LocalParametrizationQuaternion<DQ_LOCAL>>())
 {
-    assert(_state.size() == 4 && "The quaternion state vector must be of size 4");
+    assert(state_.size() == 4 && "The quaternion state vector must be of size 4");
+
+    // TODO: remove these lines after issue #381 is addressed
+    assert(isValid(1e-5)  && "Quaternion unit norm is worse than 1e-5 tolerance!");
+    state_.normalize();
 }
 
 inline StateQuaternion::StateQuaternion(bool _fixed) :
diff --git a/src/feature/feature_base.cpp b/src/feature/feature_base.cpp
index 11db6b079bd8371a48a660547997f7c68d3198bf..5e3516cccc2f6095e2c4c8905ceb90649cfeda9e 100644
--- a/src/feature/feature_base.cpp
+++ b/src/feature/feature_base.cpp
@@ -198,7 +198,7 @@ void FeatureBase::link(CaptureBasePtr _cpt_ptr)
 }
 void FeatureBase::printHeader(int _depth, bool _constr_by, bool _metric, bool _state_blocks, std::ostream& _stream, std::string _tabs) const
 {
-    _stream << _tabs << "Ftr" << id() << " trk" << trackId() << " " << getType() << ((_depth < 4) ? " -- " + std::to_string(getFactorList().size()) + "c  " : "");
+    _stream << _tabs << "Ftr" << id() << " trk" << trackId() << " " << getType() << ((_depth < 4) ? " -- " + std::to_string(getFactorList().size()) + "fac  " : "");
     if (_constr_by)
     {
         _stream << "  <--\t";
diff --git a/src/problem/problem.cpp b/src/problem/problem.cpp
index 1e5c88a2db6cf68a2032c8be1b50dbbe3c2206d9..d80dafb51c2d4e2dfd772c19fa0786e4f5c173b7 100644
--- a/src/problem/problem.cpp
+++ b/src/problem/problem.cpp
@@ -300,7 +300,7 @@ ProcessorBasePtr Problem::installProcessor(const std::string& _prc_type, //
                                            const std::string& _corresponding_sensor_name, //
                                            const std::string& _params_filename)
 {
-    SensorBasePtr sen_ptr = getSensor(_corresponding_sensor_name);
+    SensorBasePtr sen_ptr = findSensor(_corresponding_sensor_name);
     if (sen_ptr == nullptr)
         throw std::runtime_error("Cannot bind processor. Reason: Sensor \"" + _corresponding_sensor_name + "\" not found. Check sensor name, it must match in sensor and processor!");
     if (_params_filename == "")
@@ -318,7 +318,7 @@ ProcessorBasePtr Problem::installProcessor(const std::string& _prc_type, //
                                            const std::string& _corresponding_sensor_name, //
                                            const ParamsServer& _server)
 {
-    SensorBasePtr sen_ptr = getSensor(_corresponding_sensor_name);
+    SensorBasePtr sen_ptr = findSensor(_corresponding_sensor_name);
     if (sen_ptr == nullptr)
         throw std::runtime_error("Cannot bind processor. Reason: Sensor \"" + _corresponding_sensor_name + "\" not found. Check sensor name, it must match in sensor and processor!");
 
@@ -335,7 +335,7 @@ ProcessorBasePtr Problem::installProcessor(const std::string& _prc_type, //
     return prc_ptr;
 }
 
-SensorBasePtr Problem::getSensor(const std::string& _sensor_name) const
+SensorBasePtr Problem::findSensor(const std::string& _sensor_name) const
 {
     auto sen_it = std::find_if(getHardware()->getSensorList().begin(),
                                getHardware()->getSensorList().end(),
@@ -350,6 +350,16 @@ SensorBasePtr Problem::getSensor(const std::string& _sensor_name) const
     return (*sen_it);
 }
 
+ProcessorBasePtr Problem::findProcessor(const std::string& _processor_name) const
+{
+    for (const auto& sensor : getHardware()->getSensorList())
+        for (const auto& processor : sensor->getProcessorList())
+            if (processor->getName() == _processor_name)
+                return processor;
+    return nullptr;
+}
+
+
 FrameBasePtr Problem::emplaceFrame(const TimeStamp& _time_stamp, //
                                       const StateStructure& _frame_structure, //
                                       const SizeEigen _dim, //
diff --git a/src/processor/processor_tracker.cpp b/src/processor/processor_tracker.cpp
index c707c37eadae74f631b392317c286fe057713f76..512d941b7669c13e22a87aee23c5a8f84ed44329 100644
--- a/src/processor/processor_tracker.cpp
+++ b/src/processor/processor_tracker.cpp
@@ -87,7 +87,7 @@ void ProcessorTracker::processCapture(CaptureBasePtr _incoming_ptr)
 
             // Process info
             // TrackerFeature:  We only process new features in Last, here last = nullptr, so we do not have anything to do.
-            // TrackerLandmark: If we have given a map, all landmarks in the map are know. Process them.
+            // TrackerLandmark: If we have been given a map, all landmarks in the map are known. Process them.
             processKnown();
 
             // Update pointers
diff --git a/src/processor/track_matrix.cpp b/src/processor/track_matrix.cpp
index 1830270b13d7fea4d6462f2c97c7977b0879308f..d7154a788b5727b6e2f8cd201b382643110d5bf1 100644
--- a/src/processor/track_matrix.cpp
+++ b/src/processor/track_matrix.cpp
@@ -244,4 +244,14 @@ Track TrackMatrix::trackAtKeyframes(size_t _track_id) const
         return Track();
 }
 
+list<size_t> TrackMatrix::trackIds() const
+{
+    list<size_t> track_ids;
+    for (auto track : tracks_)
+    {
+        track_ids.push_back(track.first);
+    }
+    return track_ids;
+}
+
 }
diff --git a/test/gtest_factory_state_block.cpp b/test/gtest_factory_state_block.cpp
index 33b358362e0247c570ccd6ae48d64bf7a89ef31b..6332a69928a558cfdede9125a73fd7ab7f835338 100644
--- a/test/gtest_factory_state_block.cpp
+++ b/test/gtest_factory_state_block.cpp
@@ -108,7 +108,7 @@ TEST(FactoryStateBlock, creator_StateBlock)
 
 TEST(FactoryStateBlock, creator_Quaternion)
 {
-    auto sbq = FactoryStateBlock::create("StateQuaternion", Eigen::Vector4d(1,2,3,4), false);
+    auto sbq = FactoryStateBlock::create("StateQuaternion", Eigen::Vector4d(1,2,3,4).normalized(), false);
 
     ASSERT_EQ(sbq->getSize()     , 4);
     ASSERT_EQ(sbq->getLocalSize(), 3);
@@ -144,7 +144,7 @@ TEST(FactoryStateBlock, creator_H)
 
 TEST(FactoryStateBlock, creator_O_is_quaternion)
 {
-    auto sbq = FactoryStateBlock::create("O", Eigen::Vector4d(1,2,3,4), false);
+    auto sbq = FactoryStateBlock::create("O", Eigen::Vector4d(1,2,3,4).normalized(), false);
 
     ASSERT_EQ(sbq->getSize()     , 4);
     ASSERT_EQ(sbq->getLocalSize(), 3);
diff --git a/test/gtest_problem.cpp b/test/gtest_problem.cpp
index d86942de20f525f0b0995e2a5b43e18750311697..80fe044c410c9b07f5e059461875a97199d1c6de 100644
--- a/test/gtest_problem.cpp
+++ b/test/gtest_problem.cpp
@@ -101,7 +101,7 @@ TEST(Problem, Installers)
 {
     std::string wolf_root = _WOLF_ROOT_DIR;
     ProblemPtr P = Problem::create("PO", 3);
-    Eigen::Vector7d xs;
+    Eigen::Vector7d xs; xs.setRandom(); xs.tail(4).normalize();
 
     SensorBasePtr    S = P->installSensor   ("SensorOdom3d", "odometer",        xs,         wolf_root + "/test/yaml/sensor_odom_3d.yaml");
 
@@ -183,7 +183,8 @@ TEST(Problem, SetOrigin_PO_3d)
 {
     ProblemPtr P = Problem::create("PO", 3);
     TimeStamp       t0(0);
-    Eigen::VectorXd vec7(7); vec7 << 1,2,3,4,5,6,7; // not normalized quaternion, this is not what's tested
+    Eigen::VectorXd vec7(7); vec7 << 1,2,3,4,5,6,7;
+    vec7.tail(4).normalize();
     VectorComposite x0(vec7, "PO", {3,4});
     // Eigen::MatrixXd P0(6,6); P0.setIdentity(); P0 *= 0.1; // P0 is 0.1*Id
     Eigen::VectorXd vec6(6); vec6 << sqrt(0.1), sqrt(0.1), sqrt(0.1), sqrt(0.1), sqrt(0.1), sqrt(0.1);
@@ -242,9 +243,13 @@ TEST(Problem, emplaceFrame_factory)
 {
     ProblemPtr P = Problem::create("PO", 2);
 
-    FrameBasePtr f0 = P->emplaceFrame(0, "PO" , 2,  VectorXd(3)  );
-    FrameBasePtr f1 = P->emplaceFrame(1, "PO" , 3,  VectorXd(7)  );
-    FrameBasePtr f2 = P->emplaceFrame(2, "POV", 3,  VectorXd(10) );
+    Vector3d xpo2;
+    Vector7d xpo3; xpo3 << 1,2,3,.5,.5,.5,.5;
+    VectorXd xpov3(10); xpov3 << 1,2,3,.5,.5,.5,.5,1,2,3;
+
+    FrameBasePtr f0 = P->emplaceFrame(0, "PO" , 2,  xpo2  );
+    FrameBasePtr f1 = P->emplaceFrame(1, "PO" , 3,  xpo3  );
+    FrameBasePtr f2 = P->emplaceFrame(2, "POV", 3,  xpov3 );
 
 
     // check that all frames are effectively in the trajectory
@@ -324,7 +329,8 @@ TEST(Problem, Covariances)
     std::string wolf_root = _WOLF_ROOT_DIR;
 
     ProblemPtr P = Problem::create("PO", 3);
-    Eigen::Vector7d xs3d;
+    Eigen::Vector7d xs3d; xs3d.setRandom(); xs3d.tail(4).normalize();
+
     Eigen::Vector3d xs2d;
 
     SensorBasePtr    Sm = P->installSensor   ("SensorOdom3d", "odometer",       xs3d, wolf_root + "/test/yaml/sensor_odom_3d.yaml");
diff --git a/test/gtest_sensor_pose.cpp b/test/gtest_sensor_pose.cpp
index 4294d2ab663a7d7e171c3b663a6cf2575c6c5049..d37c700a7daf6a45862a4d8b830b8b8e67767282 100644
--- a/test/gtest_sensor_pose.cpp
+++ b/test/gtest_sensor_pose.cpp
@@ -38,7 +38,7 @@ TEST(Pose, constructor)
 {
 
     auto intr = std::make_shared<ParamsSensorPose>();
-    Vector7d extr; extr << 1,2,3,4,5,6,7;
+    Vector7d extr; extr << 1,2,3,.5,.5,.5,.5;
 
     auto sen = std::make_shared<SensorPose>(extr, intr);
 
@@ -54,7 +54,7 @@ TEST(Pose, getParams)
     intr->std_p = 2;
     intr->std_o = 3;
 
-    Vector7d extr; extr << 1,2,3,4,5,6,7;
+    Vector7d extr; extr << 1,2,3,.5,.5,.5,.5;
 
     auto sen = std::make_shared<SensorPose>(extr, intr);
 
@@ -70,7 +70,7 @@ TEST(Pose, create)
     intr->std_p = 2;
     intr->std_o = 3;
 
-    Vector7d extr; extr << 1,2,3,4,5,6,7;
+    Vector7d extr; extr << 1,2,3,.5,.5,.5,.5;
 
     auto sen_base = SensorPose::create("name", extr, intr);
 
diff --git a/test/gtest_tree_manager.cpp b/test/gtest_tree_manager.cpp
index 914b8a7c3a989c52f86abbb2b8274732acf3aa2f..3d3ded934d762d21ba081779155f320db1b5327f 100644
--- a/test/gtest_tree_manager.cpp
+++ b/test/gtest_tree_manager.cpp
@@ -114,7 +114,8 @@ TEST(TreeManager, keyFrameCallback)
 
     ASSERT_EQ(GM->n_KF_, 0);
 
-    auto F0 = P->emplaceFrame(0, "PO", 3, VectorXd(7) );
+    Vector7d x; x << 1,2,3,0,0,0,1;
+    auto F0 = P->emplaceFrame(0, "PO", 3, x );
     P->keyFrameCallback(F0, nullptr);
 
     ASSERT_EQ(GM->n_KF_, 1);
diff --git a/test/gtest_tree_manager_sliding_window_dual_rate.cpp b/test/gtest_tree_manager_sliding_window_dual_rate.cpp
index e394a7c59279bb4d0e52c94b7eef479406ce5797..448fc0d93d27e1db1ee76c6ae46223be81a3c505 100644
--- a/test/gtest_tree_manager_sliding_window_dual_rate.cpp
+++ b/test/gtest_tree_manager_sliding_window_dual_rate.cpp
@@ -1050,11 +1050,11 @@ TEST(TreeManagerSlidingWindowDualRate, slidingWindowWithProcessor)
     TimeStamp t(0.0);
     double dt = 1;
     CaptureMotionPtr capture = std::make_shared<CaptureOdom3d>(t,
-                                                               problem->getSensor("odom"),
+                                                               problem->findSensor("odom"),
                                                                data,
                                                                data_cov);
     CaptureMotionPtr capture_bl = std::make_shared<CaptureOdom3d>(t,
-                                                                  problem_bl->getSensor("odom"),
+                                                                  problem_bl->findSensor("odom"),
                                                                   data,
                                                                   data_cov);