diff --git a/.gitignore b/.gitignore
index ea3b11ae3f1e21c872d7f069c6d6b56ca83c2a54..b690efc9b285d63727f435a9db3ee8b2039aee82 100644
--- a/.gitignore
+++ b/.gitignore
@@ -33,3 +33,4 @@ src/examples/map_apriltag_save.yaml
 build_release/
 .clangd
 wolfcore.found
+/wolf.found
diff --git a/include/core/ceres_wrapper/solver_ceres.h b/include/core/ceres_wrapper/solver_ceres.h
index e4306aa8ca126185a6343435405c1bcb5940e650..c899b7a054d6e1a9ebab5f45cca35fa0bd86c3d0 100644
--- a/include/core/ceres_wrapper/solver_ceres.h
+++ b/include/core/ceres_wrapper/solver_ceres.h
@@ -116,6 +116,10 @@ class SolverCeres : public SolverManager
 
         const Eigen::SparseMatrixd computeHessian() const;
 
+        virtual int numStateBlocksDerived() const override;
+
+        virtual int numFactorsDerived() const override;
+
     protected:
 
         bool checkDerived(std::string prefix="") const override;
@@ -138,7 +142,14 @@ class SolverCeres : public SolverManager
 
         bool isFactorRegisteredDerived(const FactorBasePtr& fac_ptr) const override;
 
-        bool isStateBlockRegisteredDerived(const StateBlockPtr& state_ptr) override;
+        bool isStateBlockRegisteredDerived(const StateBlockPtr& state_ptr) const override;
+
+        bool isStateBlockFixedDerived(const StateBlockPtr& st) override;
+
+        bool hasThisLocalParametrizationDerived(const StateBlockPtr& st,
+                                                const LocalParametrizationBasePtr& local_param) override;
+
+        bool hasLocalParametrizationDerived(const StateBlockPtr& st)  const override;
 };
 
 inline ceres::Solver::Summary SolverCeres::getSummary()
@@ -158,16 +169,35 @@ inline ceres::Solver::Options& SolverCeres::getSolverOptions()
 
 inline bool SolverCeres::isFactorRegisteredDerived(const FactorBasePtr& fac_ptr) const
 {
-    return fac_2_residual_idx_.find(fac_ptr) != fac_2_residual_idx_.end()
-            && fac_2_costfunction_.find(fac_ptr) != fac_2_costfunction_.end();
+    return fac_2_residual_idx_.find(fac_ptr) != fac_2_residual_idx_.end() and
+           fac_2_costfunction_.find(fac_ptr) != fac_2_costfunction_.end();
 }
 
-inline bool SolverCeres::isStateBlockRegisteredDerived(const StateBlockPtr& state_ptr)
+inline bool SolverCeres::isStateBlockRegisteredDerived(const StateBlockPtr& state_ptr) const
 {
-    return state_blocks_local_param_.find(state_ptr) != state_blocks_local_param_.end()
-            && ceres_problem_->HasParameterBlock(getAssociatedMemBlockPtr(state_ptr));
+    return ceres_problem_->HasParameterBlock(getAssociatedMemBlockPtr(state_ptr));
 }
 
+inline bool SolverCeres::isStateBlockFixedDerived(const StateBlockPtr& st)
+{
+    return ceres_problem_->IsParameterBlockConstant(SolverManager::getAssociatedMemBlockPtr(st));
+};
+
+inline bool SolverCeres::hasLocalParametrizationDerived(const StateBlockPtr& st) const
+{
+    return state_blocks_local_param_.count(st) == 1;
+};
+
+inline int SolverCeres::numStateBlocksDerived() const
+{
+    return ceres_problem_->NumParameterBlocks();
+}
+
+inline int SolverCeres::numFactorsDerived() const
+{
+    return ceres_problem_->NumResidualBlocks();
+};
+
 } // namespace wolf
 
 #endif
diff --git a/include/core/solver/solver_manager.h b/include/core/solver/solver_manager.h
index 17341101c0d2ee4ee7074d220fda006e42fd0b31..bdd8a37aaa817b36609cc672402161f60a5fdba2 100644
--- a/include/core/solver/solver_manager.h
+++ b/include/core/solver/solver_manager.h
@@ -119,31 +119,47 @@ class SolverManager
 
         ReportVerbosity getVerbosity() const;
 
-        virtual bool isStateBlockRegistered(const StateBlockPtr& state_ptr);
+        virtual bool isStateBlockRegistered(const StateBlockPtr& state_ptr) const final;
 
-        virtual bool isFactorRegistered(const FactorBasePtr& fac_ptr) const;
+        virtual bool isStateBlockFloating(const StateBlockPtr& state_ptr) const final;
 
-        bool check(std::string prefix="") const;
+        virtual bool isFactorRegistered(const FactorBasePtr& fac_ptr) const final;
+        virtual bool isStateBlockFixed(const StateBlockPtr& st) final;
+
+        virtual bool hasThisLocalParametrization(const StateBlockPtr& st,
+                                                 const LocalParametrizationBasePtr& local_param) final;
+
+        virtual bool hasLocalParametrization(const StateBlockPtr& st) const final;
+
+        virtual int numFactors() const final;
+        virtual int numStateBlocks() const final;
+        virtual int numStateBlocksFloating() const final;
+
+        virtual int numFactorsDerived() const = 0;
+        virtual int numStateBlocksDerived() const = 0;
+
+        virtual bool check(std::string prefix="") const final;
 
     protected:
 
         std::map<StateBlockPtr, Eigen::VectorXd> state_blocks_;
         std::map<StateBlockPtr, FactorBasePtrList> state_blocks_2_factors_;
         std::set<FactorBasePtr> factors_;
+        std::set<StateBlockPtr> floating_state_blocks_;
 
         virtual Eigen::VectorXd& getAssociatedMemBlock(const StateBlockPtr& state_ptr);
         const double* getAssociatedMemBlockPtr(const StateBlockPtr& state_ptr) const;
-        virtual double* getAssociatedMemBlockPtr(const StateBlockPtr& state_ptr);
+        double* getAssociatedMemBlockPtr(const StateBlockPtr& state_ptr);
 
     private:
         // SolverManager functions
-        void addFactor(const FactorBasePtr& fac_ptr);
-        void removeFactor(const FactorBasePtr& fac_ptr);
-        void addStateBlock(const StateBlockPtr& state_ptr);
-        void removeStateBlock(const StateBlockPtr& state_ptr);
-        void updateStateBlockState(const StateBlockPtr& state_ptr);
-        void updateStateBlockStatus(const StateBlockPtr& state_ptr);
-        void updateStateBlockLocalParametrization(const StateBlockPtr& state_ptr);
+        virtual void addFactor(const FactorBasePtr& fac_ptr) final;
+        virtual void removeFactor(const FactorBasePtr& fac_ptr) final;
+        virtual void addStateBlock(const StateBlockPtr& state_ptr) final;
+        virtual void removeStateBlock(const StateBlockPtr& state_ptr) final;
+        virtual void updateStateBlockState(const StateBlockPtr& state_ptr) final;
+        virtual void updateStateBlockStatus(const StateBlockPtr& state_ptr) final;
+        virtual void updateStateBlockLocalParametrization(const StateBlockPtr& state_ptr) final;
 
     protected:
         // Derived virtual functions
@@ -154,9 +170,13 @@ class SolverManager
         virtual void removeStateBlockDerived(const StateBlockPtr& state_ptr) = 0;
         virtual void updateStateBlockStatusDerived(const StateBlockPtr& state_ptr) = 0;
         virtual void updateStateBlockLocalParametrizationDerived(const StateBlockPtr& state_ptr) = 0;
-        virtual bool isStateBlockRegisteredDerived(const StateBlockPtr& state_ptr) = 0;
+        virtual bool isStateBlockRegisteredDerived(const StateBlockPtr& state_ptr) const = 0;
         virtual bool isFactorRegisteredDerived(const FactorBasePtr& fac_ptr) const = 0;
         virtual bool checkDerived(std::string prefix="") const = 0;
+        virtual bool isStateBlockFixedDerived(const StateBlockPtr& st) = 0;
+        virtual bool hasThisLocalParametrizationDerived(const StateBlockPtr& st,
+                                                        const LocalParametrizationBasePtr& local_param) = 0;
+        virtual bool hasLocalParametrizationDerived(const StateBlockPtr& st) const = 0;
 };
 
 // Params (here becaure it needs of declaration of SolverManager::ReportVerbosity)
diff --git a/src/ceres_wrapper/solver_ceres.cpp b/src/ceres_wrapper/solver_ceres.cpp
index 033b0f9100b2befc728157cb0fb8d282d9808dd0..1d9cc7dd2e8f43c76820974caa473ad876b0a97c 100644
--- a/src/ceres_wrapper/solver_ceres.cpp
+++ b/src/ceres_wrapper/solver_ceres.cpp
@@ -579,6 +579,14 @@ const Eigen::SparseMatrixd SolverCeres::computeHessian() const
     return H;
 }
 
+bool SolverCeres::hasThisLocalParametrizationDerived(const StateBlockPtr& st,
+                                                     const LocalParametrizationBasePtr& local_param)
+{
+    return state_blocks_local_param_.count(st) == 1
+            && state_blocks_local_param_.at(st)->getLocalParametrization() == local_param
+            && ceres_problem_->GetParameterization(getAssociatedMemBlockPtr(st))
+                    == state_blocks_local_param_.at(st).get();
+}
 
 } // namespace wolf
 #include "core/solver/factory_solver.h"
diff --git a/src/solver/solver_manager.cpp b/src/solver/solver_manager.cpp
index 4a74ca8194f9b2b6111fb69d4c97bb7a4875b60e..60b06fd1f7b0744f8c8a293ff4f35e0e265c9f60 100644
--- a/src/solver/solver_manager.cpp
+++ b/src/solver/solver_manager.cpp
@@ -56,12 +56,24 @@ void SolverManager::update()
 
         // remove
         else
-            removeStateBlock(sb_notification_map.begin()->first);
+        {
+            if (floating_state_blocks_.count(sb_notification_map.begin()->first) == 1)
+                floating_state_blocks_.erase(sb_notification_map.begin()->first);
+            else
+                removeStateBlock(sb_notification_map.begin()->first);
+        }
 
         // remove notification
         sb_notification_map.erase(sb_notification_map.begin());
     }
 
+    // ADD "floating" STATE BLOCKS (last update they weren't involved in any factor)
+    while (!floating_state_blocks_.empty())
+    {
+        addStateBlock(*floating_state_blocks_.begin());
+        floating_state_blocks_.erase(floating_state_blocks_.begin());
+    }
+
     // ADD FACTORS
     while (!fac_notification_map.empty())
     {
@@ -79,6 +91,14 @@ void SolverManager::update()
     {
         auto state_ptr = state_pair.first;
 
+        // Check for "floating" state blocks (estimated but not involved in any factor -> not observable problem)
+        if (state_blocks_2_factors_.at(state_ptr).empty())
+        {
+            WOLF_INFO("SolverManager::update(): 'Floating' StateBlock ", state_ptr, " (not involved in any factor) Storing it apart.");
+            floating_state_blocks_.insert(state_ptr);
+            continue;
+        }
+
         // state update
         if (state_ptr->stateUpdated())
             updateStateBlockState(state_ptr);
@@ -92,6 +112,16 @@ void SolverManager::update()
             updateStateBlockLocalParametrization(state_ptr);
     }
 
+    // REMOVE "floating" STATE BLOCKS (will be added next update() call)
+    for (auto state_ptr : floating_state_blocks_)
+    {
+        removeStateBlock(state_ptr);
+        // reset flags meaning "solver will handle this change" (state, fix and local param will be set in addStateBlock)
+        state_ptr->resetStateUpdated();
+        state_ptr->resetFixUpdated();
+        state_ptr->resetLocalParamUpdated();
+    }
+
     #ifdef _WOLF_DEBUG
         assert(check("after update()"));
     #endif
@@ -321,14 +351,67 @@ SolverManager::ReportVerbosity SolverManager::getVerbosity() const
     return params_->verbose;
 }
 
-bool SolverManager::isStateBlockRegistered(const StateBlockPtr& state_ptr)
+bool SolverManager::isStateBlockRegistered(const StateBlockPtr& state_ptr) const
+{
+    return isStateBlockFloating(state_ptr) or (state_blocks_.count(state_ptr) == 1 and isStateBlockRegisteredDerived(state_ptr));
+}
+
+bool SolverManager::isStateBlockFloating(const StateBlockPtr& state_ptr) const
 {
-    return state_blocks_.count(state_ptr) ==1 && isStateBlockRegisteredDerived(state_ptr);
+    return floating_state_blocks_.count(state_ptr) == 1;
 }
 
 bool SolverManager::isFactorRegistered(const FactorBasePtr& fac_ptr) const
 {
-    return isFactorRegisteredDerived(fac_ptr);
+    return factors_.count(fac_ptr) and isFactorRegisteredDerived(fac_ptr);
+}
+
+bool SolverManager::isStateBlockFixed(const StateBlockPtr& st)
+{
+    if (!isStateBlockRegistered(st))
+        return false;
+
+    if (isStateBlockFloating(st))
+        return st->isFixed();
+
+    return isStateBlockFixedDerived(st);
+}
+
+bool SolverManager::hasThisLocalParametrization(const StateBlockPtr& st, const LocalParametrizationBasePtr& local_param)
+{
+    if (!isStateBlockRegistered(st))
+        return false;
+
+    if (isStateBlockFloating(st))
+        return st->getLocalParametrization() == local_param;
+
+    return hasThisLocalParametrizationDerived(st, local_param);
+};
+
+bool SolverManager::hasLocalParametrization(const StateBlockPtr& st) const
+{
+    if (!isStateBlockRegistered(st))
+        return false;
+
+    if (isStateBlockFloating(st))
+        return st->hasLocalParametrization();
+
+    return hasLocalParametrizationDerived(st);
+};
+
+int SolverManager::numFactors() const
+{
+    return factors_.size();
+}
+
+int SolverManager::numStateBlocks() const
+{
+    return state_blocks_.size() + floating_state_blocks_.size();
+}
+
+int SolverManager::numStateBlocksFloating() const
+{
+    return floating_state_blocks_.size();
 }
 
 double SolverManager::getPeriod() const
@@ -357,15 +440,32 @@ bool SolverManager::check(std::string prefix) const
             ok = false;
         }
 
-        // factor involving state block in factors_
-        for (auto fac : sb_fac_it->second)
+        // no factors involving state block
+        if (sb_fac_it->second.empty())
+        {
+            WOLF_ERROR("SolverManager::check: state block ", sb_fac_it->first, " is in state_blocks_ but not involved in any factor - in ", prefix);
+            ok = false;
+        }
+        else
         {
-            if (factors_.count(fac) == 0)
+            // factor involving state block in factors_
+            for (auto fac : sb_fac_it->second)
             {
-                WOLF_ERROR("SolverManager::check: factor ", fac->id(), " (involved in sb ", sb_fac_it->first, ") missing in factors_ map - in ", prefix);
-                ok = false;
+                if (factors_.count(fac) == 0)
+                {
+                    WOLF_ERROR("SolverManager::check: factor ", fac->id(), " (involved in sb ", sb_fac_it->first, ") missing in factors_ map - in ", prefix);
+                    ok = false;
+                }
             }
         }
+
+        // can't be in both state_blocks_ and floating_state_blocks_
+        if (floating_state_blocks_.count(sb_fac_it->first) == 1)
+        {
+            WOLF_ERROR("SolverManager::check: state block ", sb_fac_it->first, " is both in state_blocks_ and floating_state_blocks_ - in ", prefix);
+            ok = false;
+        }
+
         sb_vec_it++;
         sb_fac_it++;
     }
@@ -384,9 +484,38 @@ bool SolverManager::check(std::string prefix) const
         }
     }
 
-    // checkDerived
+    // CHECK DERIVED ----------------------
     ok &= checkDerived(prefix);
 
+    // CHECK IF DERIVED IS UP TO DATE ----------------------
+    // state blocks registered in derived solver
+    for (auto sb : state_blocks_)
+        if (!isStateBlockRegisteredDerived(sb.first))
+        {
+            WOLF_ERROR("SolverManager::check: state block ", sb.first, " is in state_blocks_ but not registered in derived solver - in ", prefix);
+            ok = false;
+        }
+
+    // factors registered in derived solver
+    for (auto fac : factors_)
+        if (!isFactorRegisteredDerived(fac))
+        {
+            WOLF_ERROR("SolverManager::check: factor ", fac->id(), " is in factors_ but not registered in derived solver - in ", prefix);
+            ok = false;
+        }
+
+    // numbers
+    if (numStateBlocksDerived() != state_blocks_.size())
+    {
+        WOLF_ERROR("SolverManager::check: numStateBlocksDerived() = ", numStateBlocksDerived(), " DIFFERENT THAN state_blocks_.size() = ", state_blocks_.size(), " - in ", prefix);
+        ok = false;
+    }
+    if (numFactorsDerived() != numFactors())
+    {
+        WOLF_ERROR("SolverManager::check: numFactorsDerived() = ", numFactorsDerived(), " DIFFERENT THAN numFactors() = ", numFactors(), " - in ", prefix);
+        ok = false;
+    }
+
     return ok;
 }
 
diff --git a/test/dummy/solver_manager_dummy.h b/test/dummy/solver_manager_dummy.h
index 15db720a3c42f8151dd8745dc35d0232fc0fe885..5faef11f35874747a5f0b98f8d99b42911d116e1 100644
--- a/test/dummy/solver_manager_dummy.h
+++ b/test/dummy/solver_manager_dummy.h
@@ -17,7 +17,7 @@ WOLF_PTR_TYPEDEFS(SolverManagerDummy);
 class SolverManagerDummy : public SolverManager
 {
     public:
-        std::list<FactorBasePtr> factors_;
+        std::set<FactorBasePtr> factors_derived_;
         std::map<StateBlockPtr,bool> state_block_fixed_;
         std::map<StateBlockPtr,LocalParametrizationBasePtr> state_block_local_param_;
 
@@ -26,35 +26,34 @@ class SolverManagerDummy : public SolverManager
         {
         };
 
-        bool isStateBlockRegistered(const StateBlockPtr& st) override
+        bool isStateBlockFixedDerived(const StateBlockPtr& st) override
         {
-            return state_blocks_.find(st)!=state_blocks_.end();
+            return state_block_fixed_.at(st);
         };
 
-        bool isStateBlockFixed(const StateBlockPtr& st) const
+        bool hasThisLocalParametrizationDerived(const StateBlockPtr& st, const LocalParametrizationBasePtr& local_param) override
         {
-            return state_block_fixed_.at(st);
+            return state_block_local_param_.at(st) == local_param;
         };
 
-        bool isFactorRegistered(const FactorBasePtr& fac_ptr) const override
+        bool hasLocalParametrizationDerived(const StateBlockPtr& st) const override
         {
-            return std::find(factors_.begin(), factors_.end(), fac_ptr) != factors_.end();
+            return state_block_local_param_.at(st) != nullptr;
         };
 
-        bool hasThisLocalParametrization(const StateBlockPtr& st, const LocalParametrizationBasePtr& local_param) const
+        virtual int numStateBlocksDerived() const override
         {
-            return state_block_local_param_.find(st) != state_block_local_param_.end() && state_block_local_param_.at(st) == local_param;
-        };
+            return state_block_fixed_.size();
+        }
 
-        bool hasLocalParametrization(const StateBlockPtr& st) const
+        virtual int numFactorsDerived() const override
         {
-            return state_block_local_param_.find(st) != state_block_local_param_.end();
+            return factors_derived_.size();
         };
 
         void computeCovariances(const CovarianceBlocksToBeComputed blocks) override {};
         void computeCovariances(const std::vector<StateBlockPtr>& st_list) override {};
-        bool isStateBlockRegisteredDerived(const StateBlockPtr& state_ptr) override {return true;};
-        bool isFactorRegisteredDerived(const FactorBasePtr& fac_ptr) const override {return true;};
+
 
         // The following are dummy implementations
         bool    hasConverged() override  { return true;      }
@@ -62,19 +61,17 @@ class SolverManagerDummy : public SolverManager
         double  initialCost() override   { return double(1); }
         double  finalCost() override     { return double(0); }
 
-
-
     protected:
 
         bool checkDerived(std::string prefix="") const override {return true;}
         std::string solveDerived(const ReportVerbosity report_level) override { return std::string("");};
         void addFactorDerived(const FactorBasePtr& fac_ptr) override
         {
-            factors_.push_back(fac_ptr);
+            factors_derived_.insert(fac_ptr);
         };
         void removeFactorDerived(const FactorBasePtr& fac_ptr) override
         {
-            factors_.remove(fac_ptr);
+            factors_derived_.erase(fac_ptr);
         };
         void addStateBlockDerived(const StateBlockPtr& state_ptr) override
         {
@@ -92,10 +89,16 @@ class SolverManagerDummy : public SolverManager
         };
         void updateStateBlockLocalParametrizationDerived(const StateBlockPtr& state_ptr) override
         {
-            if (state_ptr->getLocalParametrization() == nullptr)
-                state_block_local_param_.erase(state_ptr);
-            else
-                state_block_local_param_[state_ptr] = state_ptr->getLocalParametrization();
+            state_block_local_param_[state_ptr] = state_ptr->getLocalParametrization();
+        };
+        bool isStateBlockRegisteredDerived(const StateBlockPtr& state_ptr) const override
+        {
+            return state_block_fixed_.count(state_ptr) == 1 and state_block_local_param_.count(state_ptr) == 1;
+        };
+
+        bool isFactorRegisteredDerived(const FactorBasePtr& fac_ptr) const override
+        {
+            return factors_derived_.count(fac_ptr) == 1;
         };
 };
 
diff --git a/test/gtest_solver_ceres.cpp b/test/gtest_solver_ceres.cpp
index a05fd74de52247abb7cc3047861d2ece21d5963c..9fe0e4306704919bcd7ab234716a3acf107e0227 100644
--- a/test/gtest_solver_ceres.cpp
+++ b/test/gtest_solver_ceres.cpp
@@ -1,5 +1,5 @@
 /*
- * gtest_solver_ceres.cpp
+ * gtest_solver_ptr.cpp
  *
  *  Created on: Jun, 2018
  *      Author: jvallve
@@ -13,6 +13,7 @@
 #include "core/capture/capture_void.h"
 #include "core/factor/factor_pose_2d.h"
 #include "core/factor/factor_quaternion_absolute.h"
+#include "core/factor/factor_block_absolute.h"
 #include "core/state_block/local_parametrization_angle.h"
 #include "core/state_block/local_parametrization_quaternion.h"
 
@@ -27,604 +28,1533 @@
 using namespace wolf;
 using namespace Eigen;
 
-WOLF_PTR_TYPEDEFS(SolverCeresWrapper);
-class SolverCeresWrapper : public SolverCeres
-{
-    public:
-        SolverCeresWrapper(const ProblemPtr& wolf_problem) :
-            SolverCeres(wolf_problem)
-        {
-        };
-
-        bool isStateBlockRegisteredSolverCeres(const StateBlockPtr& st)
-        {
-            return ceres_problem_->HasParameterBlock(SolverManager::getAssociatedMemBlockPtr(st));
-        };
-
-        bool isStateBlockRegisteredSolverManager(const StateBlockPtr& st)
-        {
-            return state_blocks_.find(st)!=state_blocks_.end();
-        };
-
-        bool isStateBlockFixed(const StateBlockPtr& st)
-        {
-            return ceres_problem_->IsParameterBlockConstant(SolverManager::getAssociatedMemBlockPtr(st));
-        };
-
-        int numStateBlocks()
-        {
-            return ceres_problem_->NumParameterBlocks();
-        };
-
-        int numFactors()
-        {
-            return ceres_problem_->NumResidualBlocks();
-        };
-
-        bool isFactorRegistered(const FactorBasePtr& fac_ptr) const override
-        {
-            return fac_2_residual_idx_.find(fac_ptr) != fac_2_residual_idx_.end() && fac_2_costfunction_.find(fac_ptr) != fac_2_costfunction_.end();
-        };
-
-        bool hasThisLocalParametrization(const StateBlockPtr& st, const LocalParametrizationBasePtr& local_param)
-        {
-            return state_blocks_local_param_.find(st) != state_blocks_local_param_.end() &&
-                   state_blocks_local_param_.at(st)->getLocalParametrization() == local_param &&
-                   ceres_problem_->GetParameterization(getAssociatedMemBlockPtr(st)) == state_blocks_local_param_.at(st).get();
-        };
+/*
+ * Following tests are the same as in gtest_solver_manager.cpp
+ * (modifications should be applied to both tests)
+ */
 
-        bool hasLocalParametrization(const StateBlockPtr& st) const
-        {
-            return state_blocks_local_param_.find(st) != state_blocks_local_param_.end();
-        };
+StateBlockPtr createStateBlock()
+{
+    Vector4d state; state << 1, 0, 0, 0;
+    return std::make_shared<StateBlock>(state);
+}
 
-};
+FactorBasePtr createFactor(StateBlockPtr sb_ptr)
+{
+    return std::make_shared<FactorBlockAbsolute>(std::make_shared<FeatureBase>("Dummy",
+                                                                               VectorXd::Zero(sb_ptr->getSize()),
+                                                                               MatrixXd::Identity(sb_ptr->getSize(),sb_ptr->getSize())),
+                                                 sb_ptr,
+                                                 nullptr,
+                                                 false);
+}
 
 TEST(SolverCeres, Create)
 {
-    ProblemPtr P = Problem::create("PO", 2);
-    SolverCeresWrapperPtr solver_ceres = std::make_shared<SolverCeresWrapper>(P);
+    ProblemPtr P = Problem::create("PO", 3);
+    auto solver_ptr = std::make_shared<SolverCeres>(P);
 
-    // check double ointers to branches
-    ASSERT_EQ(P, solver_ceres->getProblem());
+    // check pointers
+    EXPECT_EQ(P, solver_ptr->getProblem());
 
-    // run ceres manager check
-    ASSERT_TRUE(solver_ceres->check());
+    // run solver check
+    EXPECT_TRUE(solver_ptr->check());
 }
 
-TEST(SolverCeres, AddStateBlock)
+////////////////////////////////////////////////////////
+// FLOATING STATE BLOCKS
+TEST(SolverCeres, FloatingStateBlock_Add)
 {
-    ProblemPtr P = Problem::create("PO", 2);
-    SolverCeresWrapperPtr solver_ceres = std::make_shared<SolverCeresWrapper>(P);
+    ProblemPtr P = Problem::create("PO", 3);
+    auto solver_ptr = std::make_shared<SolverCeres>(P);
 
     // Create State block
-    Vector2d state; state << 1, 2;
-    StateBlockPtr sb_ptr = std::make_shared<StateBlock>(state);
+    auto sb_ptr = createStateBlock();
 
-    // add stateblock
+    // notify stateblock
     P->notifyStateBlock(sb_ptr,ADD);
 
+    // check notifications
+    Notification notif;
+    EXPECT_TRUE(P->getStateBlockNotification(sb_ptr, notif));
+    EXPECT_EQ(ADD, notif);
+    EXPECT_EQ(P->getFactorNotificationMapSize(), 0);
+
     // update solver
-    solver_ceres->update();
+    solver_ptr->update();
 
-    // check stateblock
-    ASSERT_TRUE(solver_ceres->isStateBlockRegisteredSolverManager(sb_ptr));
-    ASSERT_TRUE(solver_ceres->isStateBlockRegisteredSolverCeres(sb_ptr));
+    // check notifications
+    EXPECT_EQ(P->getStateBlockNotificationMapSize(), 0);
+    EXPECT_EQ(P->getFactorNotificationMapSize(), 0);
 
-    // run ceres manager check
-    ASSERT_TRUE(solver_ceres->check());
+    // check stateblock
+    EXPECT_TRUE(solver_ptr->isStateBlockRegistered(sb_ptr));
+    EXPECT_TRUE(solver_ptr->isStateBlockFloating(sb_ptr));
+    EXPECT_TRUE(solver_ptr->check());
 }
 
-TEST(SolverCeres, DoubleAddStateBlock)
+TEST(SolverCeres, FloatingStateBlock_DoubleAdd)
 {
-    ProblemPtr P = Problem::create("PO", 2);
-    SolverCeresWrapperPtr solver_ceres = std::make_shared<SolverCeresWrapper>(P);
+    ProblemPtr P = Problem::create("PO", 3);
+    auto solver_ptr = std::make_shared<SolverCeres>(P);
 
     // Create State block
-    Vector2d state; state << 1, 2;
-    StateBlockPtr sb_ptr = std::make_shared<StateBlock>(state);
+    auto sb_ptr = createStateBlock();
 
-    // add stateblock
+    // notify stateblock
     P->notifyStateBlock(sb_ptr,ADD);
 
+    // check notifications
+    Notification notif;
+    EXPECT_TRUE(P->getStateBlockNotification(sb_ptr, notif));
+    EXPECT_EQ(ADD, notif);
+    EXPECT_EQ(P->getFactorNotificationMapSize(), 0);
+
     // update solver
-    solver_ceres->update();
+    solver_ptr->update();
 
-    // add stateblock again
+    // check notifications
+    EXPECT_EQ(P->getStateBlockNotificationMapSize(), 0);
+    EXPECT_EQ(P->getFactorNotificationMapSize(), 0);
+
+    // notify stateblock again
     P->notifyStateBlock(sb_ptr,ADD);
 
+    // check notifications
+    EXPECT_TRUE(P->getStateBlockNotification(sb_ptr, notif));
+    EXPECT_EQ(ADD, notif);
+    EXPECT_EQ(P->getFactorNotificationMapSize(), 0);
+
     // update solver
-    solver_ceres->update();
+    solver_ptr->update();
 
-    // check stateblock
-    ASSERT_TRUE(solver_ceres->isStateBlockRegisteredSolverManager(sb_ptr));
-    ASSERT_TRUE(solver_ceres->isStateBlockRegisteredSolverCeres(sb_ptr));
+    // check notifications
+    EXPECT_EQ(P->getStateBlockNotificationMapSize(), 0);
+    EXPECT_EQ(P->getFactorNotificationMapSize(), 0);
 
-    // run ceres manager check
-    ASSERT_TRUE(solver_ceres->check());
+    // check stateblock
+    EXPECT_TRUE(solver_ptr->isStateBlockRegistered(sb_ptr));
+    EXPECT_TRUE(solver_ptr->isStateBlockFloating(sb_ptr));
+    EXPECT_TRUE(solver_ptr->check());
 }
 
-TEST(SolverCeres, UpdateStateBlock)
+TEST(SolverCeres, FloatingStateBlock_AddFix)
 {
-    ProblemPtr P = Problem::create("PO", 2);
-    SolverCeresWrapperPtr solver_ceres = std::make_shared<SolverCeresWrapper>(P);
+    ProblemPtr P = Problem::create("PO", 3);
+    auto solver_ptr = std::make_shared<SolverCeres>(P);
 
     // Create State block
-    Vector2d state; state << 1, 2;
-    StateBlockPtr sb_ptr = std::make_shared<StateBlock>(state);
+    auto sb_ptr = createStateBlock();
 
-    // add stateblock
+    // notify stateblock
     P->notifyStateBlock(sb_ptr,ADD);
 
+    // check notifications
+    Notification notif;
+    EXPECT_TRUE(P->getStateBlockNotification(sb_ptr, notif));
+    EXPECT_EQ(ADD, notif);
+    EXPECT_EQ(P->getFactorNotificationMapSize(), 0);
+
+    // check flags
+    EXPECT_FALSE(sb_ptr->stateUpdated());
+    EXPECT_FALSE(sb_ptr->fixUpdated());
+    EXPECT_FALSE(sb_ptr->localParamUpdated());
+
     // update solver
-    solver_ceres->update();
+    solver_ptr->update();
+
+    // check notifications
+    EXPECT_EQ(P->getStateBlockNotificationMapSize(), 0);
+    EXPECT_EQ(P->getFactorNotificationMapSize(), 0);
+
+    // check flags
+    EXPECT_FALSE(sb_ptr->stateUpdated());
+    EXPECT_FALSE(sb_ptr->fixUpdated());
+    EXPECT_FALSE(sb_ptr->localParamUpdated());
 
     // check stateblock unfixed
-    ASSERT_FALSE(solver_ceres->isStateBlockFixed(sb_ptr));
+    EXPECT_FALSE(solver_ptr->isStateBlockFixed(sb_ptr));
+    EXPECT_TRUE(solver_ptr->isStateBlockFloating(sb_ptr));
+    EXPECT_TRUE(solver_ptr->check());
 
     // Fix frame
     sb_ptr->fix();
 
+    // check notifications
+    EXPECT_EQ(P->getStateBlockNotificationMapSize(), 0);
+    EXPECT_EQ(P->getFactorNotificationMapSize(), 0);
+
+    // check flags
+    EXPECT_FALSE(sb_ptr->stateUpdated());
+    EXPECT_TRUE(sb_ptr->fixUpdated());
+    EXPECT_FALSE(sb_ptr->localParamUpdated());
+
     // update solver manager
-    solver_ceres->update();
+    solver_ptr->update();
+
+    // check notifications
+    EXPECT_EQ(P->getStateBlockNotificationMapSize(), 0);
+    EXPECT_EQ(P->getFactorNotificationMapSize(), 0);
+
+    // check flags
+    EXPECT_FALSE(sb_ptr->stateUpdated());
+    EXPECT_FALSE(sb_ptr->fixUpdated());
+    EXPECT_FALSE(sb_ptr->localParamUpdated());
 
     // check stateblock fixed
-    ASSERT_TRUE(solver_ceres->isStateBlockFixed(sb_ptr));
+    EXPECT_TRUE(solver_ptr->isStateBlockFixed(sb_ptr));
+    EXPECT_TRUE(solver_ptr->isStateBlockFloating(sb_ptr));
+    EXPECT_TRUE(solver_ptr->check());
+}
+
+TEST(SolverCeres, FloatingStateBlock_AddFixed)
+{
+    ProblemPtr P = Problem::create("PO", 3);
+    auto solver_ptr = std::make_shared<SolverCeres>(P);
+
+    // Create State block
+    auto sb_ptr = createStateBlock();
+
+    // notify stateblock
+    P->notifyStateBlock(sb_ptr,ADD);
+
+    // check notifications
+    Notification notif;
+    EXPECT_TRUE(P->getStateBlockNotification(sb_ptr, notif));
+    EXPECT_EQ(ADD, notif);
+    EXPECT_EQ(P->getFactorNotificationMapSize(), 0);
+
+    // check flags
+    EXPECT_FALSE(sb_ptr->stateUpdated());
+    EXPECT_FALSE(sb_ptr->fixUpdated());
+    EXPECT_FALSE(sb_ptr->localParamUpdated());
+
+    // Fix state block
+    sb_ptr->fix();
+
+    // check flags
+    EXPECT_FALSE(sb_ptr->stateUpdated());
+    EXPECT_TRUE(sb_ptr->fixUpdated());
+    EXPECT_FALSE(sb_ptr->localParamUpdated());
+
+    // update solver manager
+    solver_ptr->update();
+
+    // check notifications
+    EXPECT_EQ(P->getStateBlockNotificationMapSize(), 0);
+    EXPECT_EQ(P->getFactorNotificationMapSize(), 0);
+
+    // check flags
+    EXPECT_FALSE(sb_ptr->stateUpdated());
+    EXPECT_FALSE(sb_ptr->fixUpdated());
+    EXPECT_FALSE(sb_ptr->localParamUpdated());
 
-    // run ceres manager check
-    ASSERT_TRUE(solver_ceres->check());
+    // check stateblock fixed
+    EXPECT_TRUE(solver_ptr->isStateBlockRegistered(sb_ptr));
+    EXPECT_TRUE(solver_ptr->isStateBlockFixed(sb_ptr));
+    EXPECT_TRUE(solver_ptr->isStateBlockFloating(sb_ptr));
+    EXPECT_TRUE(solver_ptr->check());
 }
 
-TEST(SolverCeres, AddUpdateStateBlock)
+TEST(SolverCeres, FloatingStateBlock_AddUpdateLocalParam)
 {
-    ProblemPtr P = Problem::create("PO", 2);
-    SolverCeresWrapperPtr solver_ceres = std::make_shared<SolverCeresWrapper>(P);
+    ProblemPtr P = Problem::create("PO", 3);
+    auto solver_ptr = std::make_shared<SolverCeres>(P);
 
     // Create State block
-    Vector2d state; state << 1, 2;
-    StateBlockPtr sb_ptr = std::make_shared<StateBlock>(state);
+    auto sb_ptr = createStateBlock();
 
-    // add stateblock
+    // notify stateblock
     P->notifyStateBlock(sb_ptr,ADD);
 
+    // check notifications
+    Notification notif;
+    EXPECT_TRUE(P->getStateBlockNotification(sb_ptr, notif));
+    EXPECT_EQ(ADD, notif);
+    EXPECT_EQ(P->getFactorNotificationMapSize(), 0);
+
+    // check flags
+    EXPECT_FALSE(sb_ptr->stateUpdated());
+    EXPECT_FALSE(sb_ptr->fixUpdated());
+    EXPECT_FALSE(sb_ptr->localParamUpdated());
+
+    // Local param
+    LocalParametrizationBasePtr local_ptr = std::make_shared<LocalParametrizationQuaternionLocal>();
+    sb_ptr->setLocalParametrization(local_ptr);
+
     // Fix state block
     sb_ptr->fix();
 
+    // check flags
+    EXPECT_FALSE(sb_ptr->stateUpdated());
+    EXPECT_TRUE(sb_ptr->fixUpdated());
+    EXPECT_TRUE(sb_ptr->localParamUpdated());
+    solver_ptr->update();
+
+    // check notifications
+    EXPECT_EQ(P->getStateBlockNotificationMapSize(), 0);
+    EXPECT_EQ(P->getFactorNotificationMapSize(), 0);
+
     // update solver manager
-    solver_ceres->update();
+    solver_ptr->update();
+    solver_ptr->update();
+
+    // check notifications
+    EXPECT_EQ(P->getStateBlockNotificationMapSize(), 0);
+    EXPECT_EQ(P->getFactorNotificationMapSize(), 0);
+
+    // check flags
+    EXPECT_FALSE(sb_ptr->stateUpdated());
+    EXPECT_FALSE(sb_ptr->fixUpdated());
+    EXPECT_FALSE(sb_ptr->localParamUpdated());
 
     // check stateblock fixed
-    ASSERT_TRUE(solver_ceres->isStateBlockRegisteredSolverManager(sb_ptr));
-    ASSERT_TRUE(solver_ceres->isStateBlockRegisteredSolverCeres(sb_ptr));
-    ASSERT_TRUE(solver_ceres->isStateBlockFixed(sb_ptr));
+    EXPECT_TRUE(solver_ptr->isStateBlockFixed(sb_ptr));
+    EXPECT_TRUE(solver_ptr->hasThisLocalParametrization(sb_ptr,local_ptr));
+    EXPECT_TRUE(solver_ptr->isStateBlockRegistered(sb_ptr));
+    EXPECT_TRUE(solver_ptr->isStateBlockFloating(sb_ptr));
+    EXPECT_TRUE(solver_ptr->check());
+}
+
+TEST(SolverCeres, FloatingStateBlock_AddLocalParamRemoveLocalParam)
+{
+    ProblemPtr P = Problem::create("PO", 3);
+    auto solver_ptr = std::make_shared<SolverCeres>(P);
+
+    // Create State block
+    auto sb_ptr = createStateBlock();
+
+    // Local param
+    LocalParametrizationBasePtr local_ptr = std::make_shared<LocalParametrizationQuaternionLocal>();
+    sb_ptr->setLocalParametrization(local_ptr);
+
+    // check flags
+    EXPECT_FALSE(sb_ptr->stateUpdated());
+    EXPECT_FALSE(sb_ptr->fixUpdated());
+    EXPECT_TRUE(sb_ptr->localParamUpdated());
+
+    // notify stateblock
+    P->notifyStateBlock(sb_ptr,ADD);
+
+    // check notifications
+    Notification notif;
+    EXPECT_TRUE(P->getStateBlockNotification(sb_ptr, notif));
+    EXPECT_EQ(ADD, notif);
+    EXPECT_EQ(P->getFactorNotificationMapSize(), 0);
+
+    // update solver manager
+    solver_ptr->update();
+
+    // check notifications
+    EXPECT_EQ(P->getStateBlockNotificationMapSize(), 0);
+    EXPECT_EQ(P->getFactorNotificationMapSize(), 0);
 
-    // run ceres manager check
-    ASSERT_TRUE(solver_ceres->check());
+    // check stateblock localparam
+    EXPECT_TRUE(solver_ptr->hasThisLocalParametrization(sb_ptr,local_ptr));
+
+    // check flags
+    EXPECT_FALSE(sb_ptr->stateUpdated());
+    EXPECT_FALSE(sb_ptr->fixUpdated());
+    EXPECT_FALSE(sb_ptr->localParamUpdated());
+
+    // Remove local param
+    sb_ptr->removeLocalParametrization();
+
+    // check flags
+    EXPECT_FALSE(sb_ptr->stateUpdated());
+    EXPECT_FALSE(sb_ptr->fixUpdated());
+    EXPECT_TRUE(sb_ptr->localParamUpdated());
+
+    // update solver manager
+    solver_ptr->update();
+
+    // check notifications
+    EXPECT_EQ(P->getStateBlockNotificationMapSize(), 0);
+    EXPECT_EQ(P->getFactorNotificationMapSize(), 0);
+
+    // check stateblock localparam
+    EXPECT_FALSE(solver_ptr->hasLocalParametrization(sb_ptr));
+    EXPECT_TRUE(solver_ptr->isStateBlockRegistered(sb_ptr));
+    EXPECT_TRUE(solver_ptr->isStateBlockFloating(sb_ptr));
+    EXPECT_TRUE(solver_ptr->check());
 }
 
-TEST(SolverCeres, RemoveStateBlock)
+TEST(SolverCeres, FloatingStateBlock_Remove)
 {
-    ProblemPtr P = Problem::create("PO", 2);
-    SolverCeresWrapperPtr solver_ceres = std::make_shared<SolverCeresWrapper>(P);
+    ProblemPtr P = Problem::create("PO", 3);
+    auto solver_ptr = std::make_shared<SolverCeres>(P);
 
     // Create State block
-    Vector2d state; state << 1, 2;
-    StateBlockPtr sb_ptr = std::make_shared<StateBlock>(state);
+    auto sb_ptr = createStateBlock();
 
-    // add stateblock
+    // notify stateblock
     P->notifyStateBlock(sb_ptr,ADD);
 
+    // check notifications
+    Notification notif;
+    EXPECT_TRUE(P->getStateBlockNotification(sb_ptr, notif));
+    EXPECT_EQ(ADD, notif);
+    EXPECT_EQ(P->getFactorNotificationMapSize(), 0);
+
     // update solver
-    solver_ceres->update();
+    solver_ptr->update();
 
-    ASSERT_TRUE(solver_ceres->isStateBlockRegisteredSolverManager(sb_ptr));
-    ASSERT_TRUE(solver_ceres->isStateBlockRegisteredSolverCeres(sb_ptr));
+    // check notifications
+    EXPECT_EQ(P->getStateBlockNotificationMapSize(), 0);
+    EXPECT_EQ(P->getFactorNotificationMapSize(), 0);
 
     // remove state_block
     P->notifyStateBlock(sb_ptr,REMOVE);
 
+    // check notifications
+    EXPECT_TRUE(P->getStateBlockNotification(sb_ptr, notif));
+    EXPECT_EQ(REMOVE, notif);
+    EXPECT_EQ(P->getFactorNotificationMapSize(), 0);
+
     // update solver
-    solver_ceres->update();
+    solver_ptr->update();
 
-    // check stateblock
-    ASSERT_FALSE(solver_ceres->isStateBlockRegisteredSolverManager(sb_ptr));
-    ASSERT_EQ(solver_ceres->numStateBlocks(), 0);
+    // check notifications
+    EXPECT_EQ(P->getStateBlockNotificationMapSize(), 0);
+    EXPECT_EQ(P->getFactorNotificationMapSize(), 0);
 
-    // run ceres manager check
-    ASSERT_TRUE(solver_ceres->check());
+    // check stateblock
+    EXPECT_FALSE(solver_ptr->isStateBlockRegistered(sb_ptr));
+    EXPECT_TRUE(solver_ptr->check());
 }
 
-TEST(SolverCeres, AddRemoveStateBlock)
+TEST(SolverCeres, FloatingStateBlock_AddRemove)
 {
-    ProblemPtr P = Problem::create("PO", 2);
-    SolverCeresWrapperPtr solver_ceres = std::make_shared<SolverCeresWrapper>(P);
+    ProblemPtr P = Problem::create("PO", 3);
+    auto solver_ptr = std::make_shared<SolverCeres>(P);
 
     // Create State block
-    Vector2d state; state << 1, 2;
-    StateBlockPtr sb_ptr = std::make_shared<StateBlock>(state);
+    auto sb_ptr = createStateBlock();
 
-    // add stateblock
+    // notify stateblock
     P->notifyStateBlock(sb_ptr,ADD);
 
+    // check notifications
+    Notification notif;
+    EXPECT_TRUE(P->getStateBlockNotification(sb_ptr, notif));
+    EXPECT_EQ(ADD, notif);
+    EXPECT_EQ(P->getFactorNotificationMapSize(), 0);
+
     // remove state_block
-    P->notifyStateBlock(sb_ptr,REMOVE);
+    P->notifyStateBlock(sb_ptr,REMOVE); // should cancell out the ADD
+
+    // check notifications
+    EXPECT_EQ(P->getStateBlockNotificationMapSize(), 0);
+    EXPECT_EQ(P->getFactorNotificationMapSize(), 0);
 
     // update solver
-    solver_ceres->update();
+    solver_ptr->update();
 
-    // check no stateblocks
-    ASSERT_FALSE(solver_ceres->isStateBlockRegisteredSolverManager(sb_ptr));
-    ASSERT_EQ(solver_ceres->numStateBlocks(), 0);
+    // check notifications
+    EXPECT_EQ(P->getStateBlockNotificationMapSize(), 0);
+    EXPECT_EQ(P->getFactorNotificationMapSize(), 0);
 
-    // run ceres manager check
-    ASSERT_TRUE(solver_ceres->check());
+    // check state block
+    EXPECT_FALSE(solver_ptr->isStateBlockRegistered(sb_ptr));
+    EXPECT_TRUE(solver_ptr->check());
 }
 
-TEST(SolverCeres, RemoveUpdateStateBlock)
+TEST(SolverCeres, FloatingStateBlock_AddRemoveAdd)
 {
-    ProblemPtr P = Problem::create("PO", 2);
-    SolverCeresWrapperPtr solver_ceres = std::make_shared<SolverCeresWrapper>(P);
+    ProblemPtr P = Problem::create("PO", 3);
+    auto solver_ptr = std::make_shared<SolverCeres>(P);
 
     // Create State block
-    Vector2d state; state << 1, 2;
-    StateBlockPtr sb_ptr = std::make_shared<StateBlock>(state);
+    auto sb_ptr = createStateBlock();
 
-    // add stateblock
+    // notify stateblock
     P->notifyStateBlock(sb_ptr,ADD);
 
-    // update solver
-    solver_ceres->update();
+    // check notifications
+    Notification notif;
+    EXPECT_TRUE(P->getStateBlockNotification(sb_ptr, notif));
+    EXPECT_EQ(ADD, notif);
+    EXPECT_EQ(P->getFactorNotificationMapSize(), 0);
 
     // remove state_block
-    P->notifyStateBlock(sb_ptr,REMOVE);
+    P->notifyStateBlock(sb_ptr,REMOVE); // should cancell out the ADD
+
+    // check notifications
+    EXPECT_EQ(P->getStateBlockNotificationMapSize(), 0);
+    EXPECT_EQ(P->getFactorNotificationMapSize(), 0);
+
+    // notify stateblock
+    P->notifyStateBlock(sb_ptr,ADD); // again ADD in notification list
+
+    // check notifications
+    EXPECT_TRUE(P->getStateBlockNotification(sb_ptr, notif));
+    EXPECT_EQ(ADD, notif);
+    EXPECT_EQ(P->getFactorNotificationMapSize(), 0);
 
     // update solver
-    solver_ceres->update();
+    solver_ptr->update();
+
+    // check notifications
+    EXPECT_EQ(P->getStateBlockNotificationMapSize(), 0);
+    EXPECT_EQ(P->getFactorNotificationMapSize(), 0);
 
-    // run ceres manager check
-    ASSERT_TRUE(solver_ceres->check());
+    // check state block
+    EXPECT_TRUE(solver_ptr->isStateBlockRegistered(sb_ptr));
+    EXPECT_TRUE(solver_ptr->check());
 }
 
-TEST(SolverCeres, DoubleRemoveStateBlock)
+TEST(SolverCeres, FloatingStateBlock_DoubleRemove)
 {
-    ProblemPtr P = Problem::create("PO", 2);
-    SolverCeresWrapperPtr solver_ceres = std::make_shared<SolverCeresWrapper>(P);
+    ProblemPtr P = Problem::create("PO", 3);
+    auto solver_ptr = std::make_shared<SolverCeres>(P);
 
     // Create State block
-    Vector2d state; state << 1, 2;
-    StateBlockPtr sb_ptr = std::make_shared<StateBlock>(state);
+    auto sb_ptr = createStateBlock();
 
-    // add stateblock
+    // notify stateblock
     P->notifyStateBlock(sb_ptr,ADD);
 
+    // update solver
+    solver_ptr->update();
+
     // remove state_block
     P->notifyStateBlock(sb_ptr,REMOVE);
 
     // update solver
-    solver_ceres->update();
+    solver_ptr->update();
 
     // remove state_block
     P->notifyStateBlock(sb_ptr,REMOVE);
 
+    // check notifications
+    Notification notif;
+    EXPECT_TRUE(P->getStateBlockNotification(sb_ptr, notif));
+    EXPECT_EQ(REMOVE, notif);
+    EXPECT_EQ(P->getFactorNotificationMapSize(), 0);
+
     // update solver manager
-    solver_ceres->update();
+    solver_ptr->update();
 
-    // run ceres manager check
-    ASSERT_TRUE(solver_ceres->check());
+    // check notifications
+    EXPECT_EQ(P->getStateBlockNotificationMapSize(), 0);
+    EXPECT_EQ(P->getFactorNotificationMapSize(), 0);
+
+    // checks
+    EXPECT_TRUE(solver_ptr->check());
 }
 
-TEST(SolverCeres, AddFactor)
+TEST(SolverCeres, FloatingStateBlock_AddUpdated)
 {
-    ProblemPtr P = Problem::create("PO", 2);
-    SolverCeresWrapperPtr solver_ceres = std::make_shared<SolverCeresWrapper>(P);
+    ProblemPtr P = Problem::create("PO", 3);
+    auto solver_ptr = std::make_shared<SolverCeres>(P);
+
+    // Create State block
+    auto sb_ptr = createStateBlock();
+
+    // Fix
+    sb_ptr->fix();
+
+    // Set State
+    sb_ptr->setState(2*sb_ptr->getState());
+
+    // Check flags have been set true
+    EXPECT_TRUE(sb_ptr->fixUpdated());
+    EXPECT_TRUE(sb_ptr->stateUpdated());
+
+    // == When an ADD is notified: a ADD notification should be stored ==
+
+    // notify state block
+    P->notifyStateBlock(sb_ptr,ADD);
+
+    // check notifications
+    // check notifications
+    Notification notif;
+    EXPECT_EQ(P->getStateBlockNotificationMapSize(),1);
+    EXPECT_TRUE(P->getStateBlockNotification(sb_ptr, notif));
+    EXPECT_EQ(notif, ADD);
+
+    // == Insert OTHER notifications ==
+
+    // Set State --> FLAG
+    sb_ptr->setState(2*sb_ptr->getState());
+
+    // Fix --> FLAG
+    sb_ptr->unfix();
+    // Check flag has been set true
+    EXPECT_TRUE(sb_ptr->fixUpdated());
+
+    EXPECT_EQ(P->getStateBlockNotificationMapSize(),1); // No new notifications (fix and set state are flags in sb)
+
+    // == consume empties the notification map ==
+    solver_ptr->update(); // it calls P->consumeStateBlockNotificationMap();
+    EXPECT_EQ(P->getStateBlockNotificationMapSize(),0);
+    // Check flags have been reset
+    EXPECT_FALSE(sb_ptr->fixUpdated());
+    EXPECT_FALSE(sb_ptr->stateUpdated());
+
+    // == When an REMOVE is notified: a REMOVE notification should be stored ==
 
-    // Create (and add) factor point 2d
-    FrameBasePtr        F = P->emplaceKeyFrame( 0, P->stateZero() );
-    auto C = CaptureBase::emplace<CaptureVoid>(F, 0, nullptr);
-    auto f = FeatureBase::emplace<FeatureBase>(C, "FeatureOdom2d", Vector3d::Zero(), Matrix3d::Identity());
-    FactorPose2dPtr c = FactorBase::emplace<FactorPose2d>(f,f,nullptr,false);
+    // remove state_block
+    P->notifyStateBlock(sb_ptr,REMOVE);
+
+    // check notifications
+    EXPECT_EQ(P->getStateBlockNotificationMapSize(),1);
+    EXPECT_TRUE(P->getStateBlockNotification(sb_ptr, notif));
+    EXPECT_EQ(notif, REMOVE);
+
+    // == REMOVE + ADD: notification map should be empty ==
+    P->notifyStateBlock(sb_ptr,ADD);
+    EXPECT_EQ(P->getStateBlockNotificationMapSize(),0);
+
+    // == UPDATES should clear the list of notifications ==
+    // notify state block
+    P->notifyStateBlock(sb_ptr,ADD);
 
     // update solver
-    solver_ceres->update();
+    solver_ptr->update();
 
-    // check factor
-    ASSERT_TRUE(solver_ceres->isFactorRegistered(c));
-    ASSERT_EQ(solver_ceres->numFactors(), 1);
+    // check notifications
+    EXPECT_EQ(P->getStateBlockNotificationMapSize(),0); // After solver_manager->update, notifications should be empty
+    EXPECT_EQ(P->getFactorNotificationMapSize(), 0);
 
-    // run ceres manager check
-    ASSERT_TRUE(solver_ceres->check());
+    // == ADD + REMOVE: notification map should be empty ==
+    P->notifyStateBlock(sb_ptr,ADD);
+    P->notifyStateBlock(sb_ptr,REMOVE);
+    EXPECT_EQ(P->getStateBlockNotificationMapSize(),0);
 }
 
-TEST(SolverCeres, DoubleAddFactor)
+////////////////////////////////////////////////////////
+// STATE BLOCKS AND FACTOR
+TEST(SolverCeres, StateBlockAndFactor_Add)
 {
-    ProblemPtr P = Problem::create("PO", 2);
-    SolverCeresWrapperPtr solver_ceres = std::make_shared<SolverCeresWrapper>(P);
+    ProblemPtr P = Problem::create("PO", 3);
+    auto solver_ptr = std::make_shared<SolverCeres>(P);
 
-    // Create (and add) factor point 2d
-    FrameBasePtr        F = P->emplaceKeyFrame(0, P->stateZero() );
-    auto C = CaptureBase::emplace<CaptureVoid>(F, 0, nullptr);
-    auto f = FeatureBase::emplace<FeatureBase>(C, "FeatureOdom2d", Vector3d::Zero(), Matrix3d::Identity());
-    FactorPose2dPtr c = FactorBase::emplace<FactorPose2d>(f,f,nullptr,false);
+    // Create State block
+    auto sb_ptr = createStateBlock();
 
-    // add factor again
-    P->notifyFactor(c,ADD);
+    // Create Factor
+    auto fac_ptr = createFactor(sb_ptr);
+
+    // notify stateblock (floating for the moment)
+    P->notifyStateBlock(sb_ptr,ADD);
+
+    // check notifications
+    Notification notif;
+    EXPECT_TRUE(P->getStateBlockNotification(sb_ptr, notif));
+    EXPECT_EQ(ADD, notif);
+    EXPECT_EQ(P->getFactorNotificationMapSize(), 0);
+
+    // update solver
+    solver_ptr->update();
+
+    // checks
+    EXPECT_TRUE(solver_ptr->isStateBlockRegistered(sb_ptr));
+    EXPECT_TRUE(solver_ptr->isStateBlockFloating(sb_ptr));
+
+    // notify factor (state block now not floating)
+    P->notifyFactor(fac_ptr,ADD);
+
+    // check notifications
+    EXPECT_TRUE(P->getFactorNotification(fac_ptr, notif));
+    EXPECT_EQ(ADD, notif);
+    EXPECT_EQ(P->getStateBlockNotificationMapSize(), 0);
 
     // update solver
-    solver_ceres->update();
+    solver_ptr->update();
 
-    // check factor
-    ASSERT_TRUE(solver_ceres->isFactorRegistered(c));
-    ASSERT_EQ(solver_ceres->numFactors(), 1);
+    // check notifications
+    EXPECT_EQ(P->getStateBlockNotificationMapSize(),0);
+    EXPECT_EQ(P->getFactorNotificationMapSize(), 0);
 
-    // run ceres manager check
-    ASSERT_TRUE(solver_ceres->check());
+    // checks
+    EXPECT_TRUE(solver_ptr->isStateBlockRegistered(sb_ptr));
+    EXPECT_FALSE(solver_ptr->isStateBlockFloating(sb_ptr));
+    EXPECT_TRUE(solver_ptr->isFactorRegistered(fac_ptr));
+    EXPECT_TRUE(solver_ptr->check());
 }
 
-TEST(SolverCeres, RemoveFactor)
+TEST(SolverCeres, StateBlockAndFactor_DoubleAdd)
 {
-    ProblemPtr P = Problem::create("PO", 2);
-    SolverCeresWrapperPtr solver_ceres = std::make_shared<SolverCeresWrapper>(P);
+    ProblemPtr P = Problem::create("PO", 3);
+    auto solver_ptr = std::make_shared<SolverCeres>(P);
+
+    // Create State block
+    auto sb_ptr = createStateBlock();
+
+    // Create Factor
+    auto fac_ptr = createFactor(sb_ptr);
+
+    // notify stateblock
+    P->notifyStateBlock(sb_ptr,ADD);
+
+    // notify factor
+    P->notifyFactor(fac_ptr,ADD);
 
-    // Create (and add) factor point 2d
-    FrameBasePtr        F = P->emplaceKeyFrame(0, P->stateZero() );
-    auto C = CaptureBase::emplace<CaptureVoid>(F, 0, nullptr);
-    auto f = FeatureBase::emplace<FeatureBase>(C, "FeatureOdom2d", Vector3d::Zero(), Matrix3d::Identity());
-    FactorPose2dPtr c = FactorBase::emplace<FactorPose2d>(f,f,nullptr,false);
+    // check notifications
+    Notification notif;
+    EXPECT_TRUE(P->getStateBlockNotification(sb_ptr, notif));
+    EXPECT_EQ(ADD, notif);
+    EXPECT_TRUE(P->getFactorNotification(fac_ptr, notif));
+    EXPECT_EQ(ADD, notif);
 
     // update solver
-    solver_ceres->update();
+    solver_ptr->update();
+    solver_ptr->update();
 
-    // remove factor
-    P->notifyFactor(c,REMOVE);
+    // check notifications
+    EXPECT_EQ(P->getStateBlockNotificationMapSize(),0);
+    EXPECT_EQ(P->getFactorNotificationMapSize(), 0);
+
+    // notify stateblock again
+    P->notifyStateBlock(sb_ptr,ADD);
+
+    // notify factor
+    P->notifyFactor(fac_ptr,ADD);
+
+    // check notifications
+    EXPECT_TRUE(P->getStateBlockNotification(sb_ptr, notif));
+    EXPECT_EQ(ADD, notif);
+    EXPECT_TRUE(P->getFactorNotification(fac_ptr, notif));
+    EXPECT_EQ(ADD, notif);
 
     // update solver
-    solver_ceres->update();
+    solver_ptr->update();
 
-    // check factor
-    ASSERT_FALSE(solver_ceres->isFactorRegistered(c));
-    ASSERT_EQ(solver_ceres->numFactors(), 0);
+    // check notifications
+    EXPECT_EQ(P->getStateBlockNotificationMapSize(),0);
+    EXPECT_EQ(P->getFactorNotificationMapSize(), 0);
 
-    // run ceres manager check
-    ASSERT_TRUE(solver_ceres->check());
+    // check stateblock
+    EXPECT_TRUE(solver_ptr->isStateBlockRegistered(sb_ptr));
+    EXPECT_FALSE(solver_ptr->isStateBlockFloating(sb_ptr));
+    EXPECT_TRUE(solver_ptr->isFactorRegistered(fac_ptr));
+    EXPECT_TRUE(solver_ptr->check());
 }
 
-TEST(SolverCeres, AddRemoveFactor)
+TEST(SolverCeres, StateBlockAndFactor_Fix)
 {
-    ProblemPtr P = Problem::create("PO", 2);
-    SolverCeresWrapperPtr solver_ceres = std::make_shared<SolverCeresWrapper>(P);
+    ProblemPtr P = Problem::create("PO", 3);
+    auto solver_ptr = std::make_shared<SolverCeres>(P);
+
+    // Create State block
+    auto sb_ptr = createStateBlock();
+
+    // Create Factor
+    auto fac_ptr = createFactor(sb_ptr);
 
-    // Create (and add) factor point 2d
-    FrameBasePtr        F = P->emplaceKeyFrame(0, P->stateZero() );
-    auto C = CaptureBase::emplace<CaptureVoid>(F, 0, nullptr);
-    auto f = FeatureBase::emplace<FeatureBase>(C, "FeatureOdom2d", Vector3d::Zero(), Matrix3d::Identity());
-    FactorPose2dPtr c = FactorBase::emplace<FactorPose2d>(f,f,nullptr,false);
+    // notify stateblock
+    P->notifyStateBlock(sb_ptr,ADD);
 
-    // remove factor
-    P->notifyFactor(c,REMOVE);
+    // notify factor
+    P->notifyFactor(fac_ptr,ADD);
 
-    ASSERT_TRUE(P->getFactorNotificationMapSize() == 0); // add+remove = empty
+    // check notifications
+    Notification notif;
+    EXPECT_TRUE(P->getStateBlockNotification(sb_ptr, notif));
+    EXPECT_EQ(ADD, notif);
+    EXPECT_TRUE(P->getFactorNotification(fac_ptr, notif));
+    EXPECT_EQ(ADD, notif);
+
+    // check flags
+    EXPECT_FALSE(sb_ptr->stateUpdated());
+    EXPECT_FALSE(sb_ptr->fixUpdated());
+    EXPECT_FALSE(sb_ptr->localParamUpdated());
 
     // update solver
-    solver_ceres->update();
+    solver_ptr->update();
+
+    // check notifications
+    EXPECT_EQ(P->getStateBlockNotificationMapSize(),0);
+    EXPECT_EQ(P->getFactorNotificationMapSize(), 0);
+
+    // check flags
+    EXPECT_FALSE(sb_ptr->stateUpdated());
+    EXPECT_FALSE(sb_ptr->fixUpdated());
+    EXPECT_FALSE(sb_ptr->localParamUpdated());
+
+    // check stateblock unfixed
+    EXPECT_FALSE(solver_ptr->isStateBlockFixed(sb_ptr));
+    EXPECT_TRUE(solver_ptr->check());
+
+    // Fix frame
+    sb_ptr->fix();
+
+    // check flags
+    EXPECT_FALSE(sb_ptr->stateUpdated());
+    EXPECT_TRUE(sb_ptr->fixUpdated());
+    EXPECT_FALSE(sb_ptr->localParamUpdated());
+
+    // check notifications
+    EXPECT_EQ(P->getStateBlockNotificationMapSize(),0);
+    EXPECT_EQ(P->getFactorNotificationMapSize(), 0);
+
+    // update solver manager
+    solver_ptr->update();
+
+    // check notifications
+    EXPECT_EQ(P->getStateBlockNotificationMapSize(),0);
+    EXPECT_EQ(P->getFactorNotificationMapSize(), 0);
 
-    // check factor
-    ASSERT_FALSE(solver_ceres->isFactorRegistered(c));
-    ASSERT_EQ(solver_ceres->numFactors(), 0);
+    // check flags
+    EXPECT_FALSE(sb_ptr->stateUpdated());
+    EXPECT_FALSE(sb_ptr->fixUpdated());
+    EXPECT_FALSE(sb_ptr->localParamUpdated());
 
-    // run ceres manager check
-    ASSERT_TRUE(solver_ceres->check());
+    // check stateblock fixed
+    EXPECT_TRUE(solver_ptr->isStateBlockFixed(sb_ptr));
+    EXPECT_TRUE(solver_ptr->check());
 }
 
-TEST(SolverCeres, DoubleRemoveFactor)
+TEST(SolverCeres, StateBlockAndFactor_AddFixed)
 {
-    ProblemPtr P = Problem::create("PO", 2);
-    SolverCeresWrapperPtr solver_ceres = std::make_shared<SolverCeresWrapper>(P);
+    ProblemPtr P = Problem::create("PO", 3);
+    auto solver_ptr = std::make_shared<SolverCeres>(P);
+
+    // Create State block
+    auto sb_ptr = createStateBlock();
+
+    // Create Factor
+    auto fac_ptr = createFactor(sb_ptr);
 
-    // Create (and add) factor point 2d
-    FrameBasePtr        F = P->emplaceKeyFrame(0, P->stateZero() );
-    auto C = CaptureBase::emplace<CaptureVoid>(F, 0, nullptr);
-    auto f = FeatureBase::emplace<FeatureBase>(C, "FeatureOdom2d", Vector3d::Zero(), Matrix3d::Identity());
-    FactorPose2dPtr c = FactorBase::emplace<FactorPose2d>(f,f,nullptr,false);
+    // notify stateblock
+    P->notifyStateBlock(sb_ptr,ADD);
+
+    // notify factor
+    P->notifyFactor(fac_ptr,ADD);
+
+    // check notifications
+    Notification notif;
+    EXPECT_TRUE(P->getStateBlockNotification(sb_ptr, notif));
+    EXPECT_EQ(ADD, notif);
+    EXPECT_TRUE(P->getFactorNotification(fac_ptr, notif));
+    EXPECT_EQ(ADD, notif);
+
+    // check flags
+    EXPECT_FALSE(sb_ptr->stateUpdated());
+    EXPECT_FALSE(sb_ptr->fixUpdated());
+    EXPECT_FALSE(sb_ptr->localParamUpdated());
+
+    // Fix state block
+    sb_ptr->fix();
+
+    // check flags
+    EXPECT_FALSE(sb_ptr->stateUpdated());
+    EXPECT_TRUE(sb_ptr->fixUpdated());
+    EXPECT_FALSE(sb_ptr->localParamUpdated());
+
+    // update solver manager
+    solver_ptr->update();
+
+    // check notifications
+    EXPECT_EQ(P->getStateBlockNotificationMapSize(),0);
+    EXPECT_EQ(P->getFactorNotificationMapSize(), 0);
+
+    // check flags
+    EXPECT_FALSE(sb_ptr->stateUpdated());
+    EXPECT_FALSE(sb_ptr->fixUpdated());
+    EXPECT_FALSE(sb_ptr->localParamUpdated());
+
+    // check stateblock fixed
+    EXPECT_TRUE(solver_ptr->isStateBlockRegistered(sb_ptr));
+    EXPECT_TRUE(solver_ptr->isStateBlockFixed(sb_ptr));
+    EXPECT_TRUE(solver_ptr->check());
+}
+
+TEST(SolverCeres, StateBlockAndFactor_UpdateLocalParam)
+{
+    ProblemPtr P = Problem::create("PO", 3);
+    auto solver_ptr = std::make_shared<SolverCeres>(P);
+
+    // Create State block
+    auto sb_ptr = createStateBlock();
+
+    // Create Factor
+    auto fac_ptr = createFactor(sb_ptr);
+
+    // notify stateblock
+    P->notifyStateBlock(sb_ptr,ADD);
+
+    // notify factor
+    P->notifyFactor(fac_ptr,ADD);
+
+    // check notifications
+    Notification notif;
+    EXPECT_TRUE(P->getStateBlockNotification(sb_ptr, notif));
+    EXPECT_EQ(ADD, notif);
+    EXPECT_TRUE(P->getFactorNotification(fac_ptr, notif));
+    EXPECT_EQ(ADD, notif);
+
+    // check flags
+    EXPECT_FALSE(sb_ptr->stateUpdated());
+    EXPECT_FALSE(sb_ptr->fixUpdated());
+    EXPECT_FALSE(sb_ptr->localParamUpdated());
+
+    // Local param
+    LocalParametrizationBasePtr local_ptr = std::make_shared<LocalParametrizationQuaternionLocal>();
+    sb_ptr->setLocalParametrization(local_ptr);
+
+    // Fix state block
+    sb_ptr->fix();
+
+    // check flags
+    EXPECT_FALSE(sb_ptr->stateUpdated());
+    EXPECT_TRUE(sb_ptr->fixUpdated());
+    EXPECT_TRUE(sb_ptr->localParamUpdated());
+
+    // update solver manager
+    solver_ptr->update();
+
+    // check notifications
+    EXPECT_EQ(P->getStateBlockNotificationMapSize(),0);
+    EXPECT_EQ(P->getFactorNotificationMapSize(), 0);
+
+    // check flags
+    EXPECT_FALSE(sb_ptr->stateUpdated());
+    EXPECT_FALSE(sb_ptr->fixUpdated());
+    EXPECT_FALSE(sb_ptr->localParamUpdated());
+
+    // check stateblock fixed
+    EXPECT_TRUE(solver_ptr->isStateBlockRegistered(sb_ptr));
+    EXPECT_TRUE(solver_ptr->isStateBlockFixed(sb_ptr));
+    EXPECT_TRUE(solver_ptr->hasThisLocalParametrization(sb_ptr,local_ptr));
+    EXPECT_TRUE(solver_ptr->check());
+}
+
+TEST(SolverCeres, StateBlockAndFactor_AddLocalParamRemoveLocalParam)
+{
+    ProblemPtr P = Problem::create("PO", 3);
+    auto solver_ptr = std::make_shared<SolverCeres>(P);
+
+    // Create State block
+    auto sb_ptr = createStateBlock();
+
+    // Create Factor
+    auto fac_ptr = createFactor(sb_ptr);
+
+    // Local param
+    LocalParametrizationBasePtr local_ptr = std::make_shared<LocalParametrizationQuaternionLocal>();
+    sb_ptr->setLocalParametrization(local_ptr);
+
+    // check flags
+    EXPECT_FALSE(sb_ptr->stateUpdated());
+    EXPECT_FALSE(sb_ptr->fixUpdated());
+    EXPECT_TRUE(sb_ptr->localParamUpdated());
+
+    // notify stateblock
+    P->notifyStateBlock(sb_ptr,ADD);
+
+    // notify factor
+    P->notifyFactor(fac_ptr,ADD);
+
+    // check notifications
+    Notification notif;
+    EXPECT_TRUE(P->getStateBlockNotification(sb_ptr, notif));
+    EXPECT_EQ(ADD, notif);
+    EXPECT_TRUE(P->getFactorNotification(fac_ptr, notif));
+    EXPECT_EQ(ADD, notif);
+
+    // update solver manager
+    solver_ptr->update();
+
+    // check notifications
+    EXPECT_EQ(P->getStateBlockNotificationMapSize(),0);
+    EXPECT_EQ(P->getFactorNotificationMapSize(), 0);
+
+    // check solver
+    EXPECT_TRUE(solver_ptr->isStateBlockRegistered(sb_ptr));
+    EXPECT_TRUE(solver_ptr->hasLocalParametrization(sb_ptr));
+    EXPECT_TRUE(solver_ptr->hasThisLocalParametrization(sb_ptr,local_ptr));
+    EXPECT_TRUE(solver_ptr->check());
+
+    // check flags
+    EXPECT_FALSE(sb_ptr->stateUpdated());
+    EXPECT_FALSE(sb_ptr->fixUpdated());
+    EXPECT_FALSE(sb_ptr->localParamUpdated());
+
+    // Remove local param
+    sb_ptr->removeLocalParametrization();
+
+    // check flags
+    EXPECT_FALSE(sb_ptr->stateUpdated());
+    EXPECT_FALSE(sb_ptr->fixUpdated());
+    EXPECT_TRUE(sb_ptr->localParamUpdated());
+
+    // update solver manager
+    solver_ptr->update();
+
+    // check solver
+    EXPECT_TRUE(solver_ptr->isStateBlockRegistered(sb_ptr));
+    EXPECT_FALSE(solver_ptr->hasLocalParametrization(sb_ptr));
+    EXPECT_TRUE(solver_ptr->check());
+}
+
+TEST(SolverCeres, StateBlockAndFactor_RemoveStateBlock)
+{
+    ProblemPtr P = Problem::create("PO", 3);
+    auto solver_ptr = std::make_shared<SolverCeres>(P);
+
+    // Create State block
+    auto sb_ptr = createStateBlock();
+
+    // Create Factor
+    auto fac_ptr = createFactor(sb_ptr);
+
+    // notify stateblock
+    P->notifyStateBlock(sb_ptr,ADD);
+
+    // notify factor
+    P->notifyFactor(fac_ptr,ADD);
+
+    // check notifications
+    Notification notif;
+    EXPECT_TRUE(P->getStateBlockNotification(sb_ptr, notif));
+    EXPECT_EQ(ADD, notif);
+    EXPECT_TRUE(P->getFactorNotification(fac_ptr, notif));
+    EXPECT_EQ(ADD, notif);
 
     // update solver
-    solver_ceres->update();
+    solver_ptr->update();
 
-    // remove factor
-    P->notifyFactor(c,REMOVE);
+    // check notifications
+    EXPECT_EQ(P->getStateBlockNotificationMapSize(),0);
+    EXPECT_EQ(P->getFactorNotificationMapSize(), 0);
+
+    // remove state_block
+    P->notifyStateBlock(sb_ptr,REMOVE);
+
+    // check notifications
+    EXPECT_TRUE(P->getStateBlockNotification(sb_ptr, notif));
+    EXPECT_EQ(REMOVE, notif);
+    EXPECT_EQ(P->getFactorNotificationMapSize(), 0);
 
     // update solver
-    solver_ceres->update();
+    solver_ptr->update(); // there is a factor involved, removal posponed (REMOVE in notification list)
+
+    // check notifications
+    EXPECT_TRUE(P->getStateBlockNotification(sb_ptr, notif));
+    EXPECT_EQ(REMOVE, notif);
+    EXPECT_EQ(P->getFactorNotificationMapSize(), 0);
+
+    // checks
+    EXPECT_TRUE(solver_ptr->isStateBlockRegistered(sb_ptr));
+    EXPECT_TRUE(solver_ptr->isFactorRegistered(fac_ptr));
+    EXPECT_TRUE(solver_ptr->check());
+}
 
-    // remove factor
-    P->notifyFactor(c,REMOVE);
+TEST(SolverCeres, StateBlockAndFactor_RemoveFactor)
+{
+    ProblemPtr P = Problem::create("PO", 3);
+    auto solver_ptr = std::make_shared<SolverCeres>(P);
+
+    // Create State block
+    auto sb_ptr = createStateBlock();
+
+    // Create Factor
+    auto fac_ptr = createFactor(sb_ptr);
+
+    // notify stateblock
+    P->notifyStateBlock(sb_ptr,ADD);
+
+    // notify factor
+    P->notifyFactor(fac_ptr,ADD);
+
+    // check notifications
+    Notification notif;
+    EXPECT_TRUE(P->getStateBlockNotification(sb_ptr, notif));
+    EXPECT_EQ(ADD, notif);
+    EXPECT_TRUE(P->getFactorNotification(fac_ptr, notif));
+    EXPECT_EQ(ADD, notif);
+
+    // update solver
+    solver_ptr->update();
+
+    // check notifications
+    EXPECT_EQ(P->getStateBlockNotificationMapSize(),0);
+    EXPECT_EQ(P->getFactorNotificationMapSize(), 0);
+
+    // remove state_block
+    P->notifyFactor(fac_ptr,REMOVE); // state block should be automatically stored as floating
+
+    // check notifications
+    EXPECT_TRUE(P->getFactorNotification(fac_ptr, notif));
+    EXPECT_EQ(REMOVE, notif);
+    EXPECT_EQ(P->getStateBlockNotificationMapSize(), 0);
 
     // update solver
-    solver_ceres->update();
+    solver_ptr->update();
 
-    // check factor
-    ASSERT_FALSE(solver_ceres->isFactorRegistered(c));
-    ASSERT_EQ(solver_ceres->numFactors(), 0);
+    // check notifications
+    EXPECT_EQ(P->getStateBlockNotificationMapSize(),0);
+    EXPECT_EQ(P->getFactorNotificationMapSize(), 0);
 
-    // run ceres manager check
-    ASSERT_TRUE(solver_ceres->check());
+    // checks
+    EXPECT_TRUE(solver_ptr->isStateBlockRegistered(sb_ptr));
+    EXPECT_TRUE(solver_ptr->isStateBlockFloating(sb_ptr));
+    EXPECT_FALSE(solver_ptr->isFactorRegistered(fac_ptr));
+    EXPECT_TRUE(solver_ptr->check());
 }
 
-TEST(SolverCeres, AddStateBlockLocalParam)
+TEST(SolverCeres, StateBlockAndFactor_AddRemoveStateBlock)
 {
-    ProblemPtr P = Problem::create("PO", 2);
-    SolverCeresWrapperPtr solver_ceres = std::make_shared<SolverCeresWrapper>(P);
+    ProblemPtr P = Problem::create("PO", 3);
+    auto solver_ptr = std::make_shared<SolverCeres>(P);
 
     // Create State block
-    Vector1d state; state << 1;
-    StateBlockPtr sb_ptr = std::make_shared<StateBlock>(state);
+    auto sb_ptr = createStateBlock();
 
-    // Local param
-    LocalParametrizationBasePtr local_param_ptr = std::make_shared<LocalParametrizationAngle>();
-    sb_ptr->setLocalParametrization(local_param_ptr);
+    // Create Factor
+    auto fac_ptr = createFactor(sb_ptr);
 
-    // add stateblock
+    // notify stateblock
     P->notifyStateBlock(sb_ptr,ADD);
 
+    // notify factor
+    P->notifyFactor(fac_ptr,ADD);
+
+    // check notifications
+    Notification notif;
+    EXPECT_TRUE(P->getStateBlockNotification(sb_ptr, notif));
+    EXPECT_EQ(ADD, notif);
+    EXPECT_TRUE(P->getFactorNotification(fac_ptr, notif));
+    EXPECT_EQ(ADD, notif);
+
+    // remove state_block
+    P->notifyStateBlock(sb_ptr,REMOVE); // cancells out ADD notification
+
+    // check notifications
+    EXPECT_EQ(P->getStateBlockNotificationMapSize(),0);
+    EXPECT_TRUE(P->getFactorNotification(fac_ptr, notif));
+    EXPECT_EQ(ADD, notif);
+
     // update solver
-    solver_ceres->update();
+    solver_ptr->update(); // factor ADD notification is not executed since state block involved is missing (ADD notification added)
 
-    // check stateblock
-    ASSERT_TRUE(solver_ceres->hasLocalParametrization(sb_ptr));
-    ASSERT_TRUE(solver_ceres->hasThisLocalParametrization(sb_ptr,local_param_ptr));
+    // check notifications
+    EXPECT_EQ(P->getStateBlockNotificationMapSize(),0);
+    EXPECT_TRUE(P->getFactorNotification(fac_ptr, notif));
+    EXPECT_EQ(ADD, notif);
 
-    // run ceres manager check
-    ASSERT_TRUE(solver_ceres->check());
+    // check state block
+    EXPECT_FALSE(solver_ptr->isStateBlockRegistered(sb_ptr));
+    EXPECT_FALSE(solver_ptr->isFactorRegistered(fac_ptr));
+    EXPECT_TRUE(solver_ptr->check());
 }
 
-TEST(SolverCeres, RemoveLocalParam)
+TEST(SolverCeres, StateBlockAndFactor_AddRemoveFactor)
 {
-    ProblemPtr P = Problem::create("PO", 2);
-    SolverCeresWrapperPtr solver_ceres = std::make_shared<SolverCeresWrapper>(P);
+    ProblemPtr P = Problem::create("PO", 3);
+    auto solver_ptr = std::make_shared<SolverCeres>(P);
 
     // Create State block
-    Vector1d state; state << 1;
-    StateBlockPtr sb_ptr = std::make_shared<StateBlock>(state);
+    auto sb_ptr = createStateBlock();
 
-    // Local param
-    LocalParametrizationBasePtr local_param_ptr = std::make_shared<LocalParametrizationAngle>();
-    sb_ptr->setLocalParametrization(local_param_ptr);
+    // Create Factor
+    auto fac_ptr = createFactor(sb_ptr);
 
-    // add stateblock
+    // notify stateblock
     P->notifyStateBlock(sb_ptr,ADD);
 
+    // notify factor
+    P->notifyFactor(fac_ptr,ADD);
+
+    // check notifications
+    Notification notif;
+    EXPECT_TRUE(P->getStateBlockNotification(sb_ptr, notif));
+    EXPECT_EQ(ADD, notif);
+    EXPECT_TRUE(P->getFactorNotification(fac_ptr, notif));
+    EXPECT_EQ(ADD, notif);
+
+    // remove state_block
+    P->notifyFactor(fac_ptr,REMOVE); // cancells out ADD notification
+
+    // check notifications
+    EXPECT_EQ(P->getFactorNotificationMapSize(),0);
+    EXPECT_TRUE(P->getStateBlockNotification(sb_ptr, notif));
+    EXPECT_EQ(ADD, notif);
+
     // update solver
-    solver_ceres->update();
+    solver_ptr->update(); // state block should be automatically stored as floating
 
-    // Remove local param
-    sb_ptr->removeLocalParametrization();
+    // check notifications
+    EXPECT_EQ(P->getStateBlockNotificationMapSize(),0);
+    EXPECT_EQ(P->getFactorNotificationMapSize(), 0);
+
+    // checks
+    EXPECT_TRUE(solver_ptr->isStateBlockRegistered(sb_ptr));
+    EXPECT_TRUE(solver_ptr->isStateBlockFloating(sb_ptr));
+    EXPECT_FALSE(solver_ptr->isFactorRegistered(fac_ptr));
+    EXPECT_TRUE(solver_ptr->check());
+}
+
+TEST(SolverCeres, StateBlockAndFactor_DoubleRemoveStateBlock)
+{
+    ProblemPtr P = Problem::create("PO", 3);
+    auto solver_ptr = std::make_shared<SolverCeres>(P);
+
+    // Create State block
+    auto sb_ptr = createStateBlock();
+
+    // Create Factor
+    auto fac_ptr = createFactor(sb_ptr);
+
+    // notify stateblock
+    P->notifyStateBlock(sb_ptr,ADD);
+
+    // notify factor
+    P->notifyFactor(fac_ptr,ADD);
+
+    // check notifications
+    Notification notif;
+    EXPECT_TRUE(P->getStateBlockNotification(sb_ptr, notif));
+    EXPECT_EQ(ADD, notif);
+    EXPECT_TRUE(P->getFactorNotification(fac_ptr, notif));
+    EXPECT_EQ(ADD, notif);
+
+    // remove state_block
+    P->notifyStateBlock(sb_ptr,REMOVE); // cancells out the ADD
+
+    // check notifications
+    EXPECT_EQ(P->getStateBlockNotificationMapSize(),0);
+    EXPECT_TRUE(P->getFactorNotification(fac_ptr, notif));
+    EXPECT_EQ(ADD, notif);
 
     // update solver
-    solver_ceres->update();
+    solver_ptr->update(); // factor ADD is posponed
 
-    // check stateblock
-    ASSERT_FALSE(solver_ceres->hasLocalParametrization(sb_ptr));
+    // check notifications
+    EXPECT_EQ(P->getStateBlockNotificationMapSize(),0);
+    EXPECT_TRUE(P->getFactorNotification(fac_ptr, notif));
+    EXPECT_EQ(ADD, notif);
+
+    // remove state_block
+    P->notifyStateBlock(sb_ptr,REMOVE);
 
-    // run ceres manager check
-    ASSERT_TRUE(solver_ceres->check());
+    // check notifications
+    EXPECT_TRUE(P->getStateBlockNotification(sb_ptr, notif));
+    EXPECT_EQ(REMOVE, notif);
+    EXPECT_TRUE(P->getFactorNotification(fac_ptr, notif));
+    EXPECT_EQ(ADD, notif);
+
+    // update solver manager
+    solver_ptr->update(); // repeated REMOVE should be ignored
+
+    // check notifications
+    EXPECT_EQ(P->getStateBlockNotificationMapSize(),0);
+    EXPECT_TRUE(P->getFactorNotification(fac_ptr, notif));
+    EXPECT_EQ(ADD, notif);
+
+    // check state block
+    EXPECT_FALSE(solver_ptr->isStateBlockRegistered(sb_ptr));
+    EXPECT_FALSE(solver_ptr->isFactorRegistered(fac_ptr));
+    EXPECT_TRUE(solver_ptr->check());
 }
 
-TEST(SolverCeres, AddLocalParam)
+TEST(SolverCeres, StateBlockAndFactor_DoubleRemoveFactor)
 {
-    ProblemPtr P = Problem::create("PO", 2);
-    SolverCeresWrapperPtr solver_ceres = std::make_shared<SolverCeresWrapper>(P);
+    ProblemPtr P = Problem::create("PO", 3);
+    auto solver_ptr = std::make_shared<SolverCeres>(P);
 
     // Create State block
-    Vector1d state; state << 1;
-    StateBlockPtr sb_ptr = std::make_shared<StateBlock>(state);
+    auto sb_ptr = createStateBlock();
+
+    // Create Factor
+    auto fac_ptr = createFactor(sb_ptr);
 
-    // add stateblock
+    // notify stateblock
     P->notifyStateBlock(sb_ptr,ADD);
 
+    // notify factor
+    P->notifyFactor(fac_ptr,ADD);
+
+    // check notifications
+    Notification notif;
+    EXPECT_TRUE(P->getStateBlockNotification(sb_ptr, notif));
+    EXPECT_EQ(ADD, notif);
+    EXPECT_TRUE(P->getFactorNotification(fac_ptr, notif));
+    EXPECT_EQ(ADD, notif);
+
+    // remove state_block
+    P->notifyFactor(fac_ptr,REMOVE); // cancells out ADD
+
+    // check notifications
+    EXPECT_EQ(P->getFactorNotificationMapSize(),0);
+    EXPECT_TRUE(P->getStateBlockNotification(sb_ptr, notif));
+    EXPECT_EQ(ADD, notif);
+
     // update solver
-    solver_ceres->update();
+    solver_ptr->update(); // state block should be automatically stored as floating
 
-    // check stateblock
-    ASSERT_FALSE(solver_ceres->hasLocalParametrization(sb_ptr));
+    // check notifications
+    EXPECT_EQ(P->getStateBlockNotificationMapSize(),0);
+    EXPECT_EQ(P->getFactorNotificationMapSize(),0);
 
-    // Local param
-    LocalParametrizationBasePtr local_param_ptr = std::make_shared<LocalParametrizationAngle>();
-    sb_ptr->setLocalParametrization(local_param_ptr);
+    // remove state_block
+    P->notifyFactor(fac_ptr,REMOVE);
+
+    // check notifications
+    EXPECT_EQ(P->getStateBlockNotificationMapSize(),0);
+    EXPECT_TRUE(P->getFactorNotification(fac_ptr, notif));
+    EXPECT_EQ(REMOVE, notif);
 
     // update solver
-    solver_ceres->update();
+    solver_ptr->update(); // repeated REMOVE should be ignored
 
-    // check stateblock
-    ASSERT_TRUE(solver_ceres->hasLocalParametrization(sb_ptr));
-    ASSERT_TRUE(solver_ceres->hasThisLocalParametrization(sb_ptr,local_param_ptr));
+    // checks
+    EXPECT_TRUE(solver_ptr->isStateBlockRegistered(sb_ptr));
+    EXPECT_TRUE(solver_ptr->isStateBlockFloating(sb_ptr));
+    EXPECT_FALSE(solver_ptr->isFactorRegistered(fac_ptr));
+    EXPECT_TRUE(solver_ptr->check());
+}
+
+TEST(SolverCeres, StateBlockAndFactor_AddUpdatedStateBlock)
+{
+    ProblemPtr P = Problem::create("PO", 3);
+    auto solver_ptr = std::make_shared<SolverCeres>(P);
+
+    // Create State block
+    auto sb_ptr = createStateBlock();
+
+    // Create Factor
+    auto fac_ptr = createFactor(sb_ptr);
+
+    // Fix
+    sb_ptr->fix();
 
-    // run ceres manager check
-    ASSERT_TRUE(solver_ceres->check());
+    // Change State
+    sb_ptr->setState(2*sb_ptr->getState());
+
+    // Check flags have been set true
+    EXPECT_TRUE(sb_ptr->fixUpdated());
+    EXPECT_TRUE(sb_ptr->stateUpdated());
+
+    // == When an ADD is notified: a ADD notification should be stored ==
+
+    // notify state block
+    P->notifyStateBlock(sb_ptr,ADD);
+
+    // notify factor
+    P->notifyFactor(fac_ptr,ADD);
+
+    // check notifications
+    Notification notif;
+    EXPECT_TRUE(P->getStateBlockNotification(sb_ptr, notif));
+    EXPECT_EQ(ADD, notif);
+    EXPECT_TRUE(P->getFactorNotification(fac_ptr, notif));
+    EXPECT_EQ(ADD, notif);
+
+    // == Insert OTHER notifications ==
+
+    // Set State --> FLAG
+    sb_ptr->setState(2*sb_ptr->getState());
+
+    // Fix --> FLAG
+    sb_ptr->unfix();
+    // Check flag has been set true
+    EXPECT_TRUE(sb_ptr->fixUpdated());
+
+    EXPECT_EQ(P->getStateBlockNotificationMapSize(),1); // No new notifications (fix and set state are flags in sb)
+
+    // == consume empties the notification map ==
+    solver_ptr->update(); // it calls P->consumeStateBlockNotificationMap();
+    EXPECT_EQ(P->getStateBlockNotificationMapSize(),0);
+    // Check flags have been reset
+    EXPECT_FALSE(sb_ptr->fixUpdated());
+    EXPECT_FALSE(sb_ptr->stateUpdated());
+
+    // == When an REMOVE is notified: a REMOVE notification should be stored ==
+
+    // remove state_block
+    P->notifyStateBlock(sb_ptr,REMOVE);
+
+    EXPECT_EQ(P->getStateBlockNotificationMapSize(),1);
+    EXPECT_TRUE(P->getStateBlockNotification(sb_ptr, notif));
+    EXPECT_EQ(notif, REMOVE);
+
+    // == REMOVE + ADD: notification map should be empty ==
+    P->notifyStateBlock(sb_ptr,ADD);
+    EXPECT_EQ(P->getStateBlockNotificationMapSize(),0);
+
+    // == UPDATES should clear the list of notifications ==
+    // notify state block
+    P->notifyStateBlock(sb_ptr,ADD);
+
+    // update solver
+    solver_ptr->update();
+
+    EXPECT_EQ(P->getStateBlockNotificationMapSize(),0); // After solver_manager->update, notifications should be empty
+
+    // == ADD + REMOVE: notification map should be empty ==
+    P->notifyStateBlock(sb_ptr,ADD);
+    P->notifyStateBlock(sb_ptr,REMOVE);
+    EXPECT_EQ(P->getStateBlockNotificationMapSize(),0);
 }
 
-TEST(SolverCeres, FactorsRemoveLocalParam)
+////////////////////////////////////////////////////////
+// ONLY FACTOR
+TEST(SolverCeres, OnlyFactor_Add)
 {
     ProblemPtr P = Problem::create("PO", 3);
-    SolverCeresWrapperPtr solver_ceres = std::make_shared<SolverCeresWrapper>(P);
+    auto solver_ptr = std::make_shared<SolverCeres>(P);
 
-    // Create (and add) 2 factors quaternion
-    FrameBasePtr                    F = P->emplaceKeyFrame(0, P->stateZero() );
-    auto C = CaptureBase::emplace<CaptureVoid>(F, 0, nullptr);
-    auto f = FeatureBase::emplace<FeatureBase>(C, "FeatureOdom2d", Vector3d::Zero(), Matrix3d::Identity());
-    FactorQuaternionAbsolutePtr c1 = FactorBase::emplace<FactorQuaternionAbsolute>(f, f, F->getO(),nullptr,false);
-    FactorQuaternionAbsolutePtr c2 = FactorBase::emplace<FactorQuaternionAbsolute>(f, f, F->getO(),nullptr,false);
+    // Create State block
+    auto sb_ptr = createStateBlock();
+
+    // Create Factor
+    auto fac_ptr = createFactor(sb_ptr);
+
+    // notify factor (state block has not been notified)
+    P->notifyFactor(fac_ptr,ADD);
+
+    // check notifications
+    Notification notif;
+    EXPECT_EQ(P->getStateBlockNotificationMapSize(),0);
+    EXPECT_TRUE(P->getFactorNotification(fac_ptr, notif));
+    EXPECT_EQ(ADD, notif);
 
     // update solver
-    solver_ceres->update();
+    solver_ptr->update(); // factor ADD should be posponed (in the notification list again)
 
-    // check local param
-    ASSERT_TRUE(solver_ceres->hasLocalParametrization(F->getO()));
-    ASSERT_TRUE(solver_ceres->hasThisLocalParametrization(F->getO(),F->getO()->getLocalParametrization()));
+    // check notifications
+    EXPECT_EQ(P->getStateBlockNotificationMapSize(),0);
+    EXPECT_TRUE(P->getFactorNotification(fac_ptr, notif));
+    EXPECT_EQ(ADD, notif);
 
-    // check factor
-    ASSERT_TRUE(solver_ceres->isFactorRegistered(c1));
-    ASSERT_TRUE(solver_ceres->isFactorRegistered(c2));
-    ASSERT_EQ(solver_ceres->numFactors(), 2);
+    // checks
+    EXPECT_FALSE(solver_ptr->isStateBlockRegistered(sb_ptr));
+    EXPECT_FALSE(solver_ptr->isFactorRegistered(fac_ptr));
+    EXPECT_TRUE(solver_ptr->check());
+}
 
-    // remove local param
-    F->getO()->removeLocalParametrization();
+TEST(SolverCeres, OnlyFactor_Remove)
+{
+    ProblemPtr P = Problem::create("PO", 3);
+    auto solver_ptr = std::make_shared<SolverCeres>(P);
+
+    // Create State block
+    auto sb_ptr = createStateBlock();
+
+    // Create Factor
+    auto fac_ptr = createFactor(sb_ptr);
+
+    // notify factor (state block has not been notified)
+    P->notifyFactor(fac_ptr,ADD);
+
+    // check notifications
+    Notification notif;
+    EXPECT_EQ(P->getStateBlockNotificationMapSize(),0);
+    EXPECT_TRUE(P->getFactorNotification(fac_ptr, notif));
+    EXPECT_EQ(ADD, notif);
 
     // update solver
-    solver_ceres->update();
+    solver_ptr->update(); // ADD factor should be posponed (in the notification list again)
+
+    // check notifications
+    EXPECT_EQ(P->getStateBlockNotificationMapSize(),0);
+    EXPECT_TRUE(P->getFactorNotification(fac_ptr, notif));
+    EXPECT_EQ(ADD, notif);
 
-    // check local param
-    ASSERT_FALSE(solver_ceres->hasLocalParametrization(F->getO()));
+    // notify factor
+    P->notifyFactor(fac_ptr,REMOVE);
 
-    // check factor
-    ASSERT_TRUE(solver_ceres->isFactorRegistered(c1));
-    ASSERT_TRUE(solver_ceres->isFactorRegistered(c2));
-    ASSERT_EQ(solver_ceres->numFactors(), 2);
+    // check notifications
+    EXPECT_EQ(P->getStateBlockNotificationMapSize(),0);
+    EXPECT_EQ(P->getFactorNotificationMapSize(),0);
 
-    // run ceres manager check
-    ASSERT_TRUE(solver_ceres->check());
+    // update solver
+    solver_ptr->update(); // nothing to update
+
+    // check notifications
+    EXPECT_EQ(P->getStateBlockNotificationMapSize(),0);
+    EXPECT_EQ(P->getFactorNotificationMapSize(),0);
+
+    // checks
+    EXPECT_FALSE(solver_ptr->isStateBlockRegistered(sb_ptr));
+    EXPECT_FALSE(solver_ptr->isFactorRegistered(fac_ptr));
+    EXPECT_TRUE(solver_ptr->check());
 }
 
-TEST(SolverCeres, FactorsUpdateLocalParam)
+TEST(SolverCeres, OnlyFactor_AddRemove)
 {
     ProblemPtr P = Problem::create("PO", 3);
-    SolverCeresWrapperPtr solver_ceres = std::make_shared<SolverCeresWrapper>(P);
+    auto solver_ptr = std::make_shared<SolverCeres>(P);
 
-    // Create (and add) 2 factors quaternion
-    FrameBasePtr                    F = P->emplaceKeyFrame(0, P->stateZero() );
-    auto C = CaptureBase::emplace<CaptureVoid>(F, 0, nullptr);
-    auto f = FeatureBase::emplace<FeatureBase>(C, "FeatureOdom2d", Vector3d::Zero(), Matrix3d::Identity());
-    FactorQuaternionAbsolutePtr c1 = FactorBase::emplace<FactorQuaternionAbsolute>(f, f, F->getO(),nullptr,false);
-    FactorQuaternionAbsolutePtr c2 = FactorBase::emplace<FactorQuaternionAbsolute>(f, f, F->getO(),nullptr,false);
+    // Create State block
+    auto sb_ptr = createStateBlock();
 
-    // update solver
-    solver_ceres->update();
+    // Create Factor
+    auto fac_ptr = createFactor(sb_ptr);
+
+    // notify factor (state block has not been notified)
+    P->notifyFactor(fac_ptr,ADD);
 
-    // check local param
-    ASSERT_TRUE(solver_ceres->hasLocalParametrization(F->getO()));
-    ASSERT_TRUE(solver_ceres->hasThisLocalParametrization(F->getO(),F->getO()->getLocalParametrization()));
+    // check notifications
+    Notification notif;
+    EXPECT_EQ(P->getStateBlockNotificationMapSize(),0);
+    EXPECT_TRUE(P->getFactorNotification(fac_ptr, notif));
+    EXPECT_EQ(ADD, notif);
 
-    // check factor
-    ASSERT_TRUE(solver_ceres->isFactorRegistered(c1));
-    ASSERT_TRUE(solver_ceres->isFactorRegistered(c2));
-    ASSERT_EQ(solver_ceres->numFactors(), 2);
+    // notify factor
+    P->notifyFactor(fac_ptr,REMOVE);
 
-    // remove local param
-    LocalParametrizationBasePtr local_param_ptr = std::make_shared<LocalParametrizationQuaternionGlobal>();
-    F->getO()->setLocalParametrization(local_param_ptr);
+    // check notifications
+    EXPECT_EQ(P->getStateBlockNotificationMapSize(),0);
+    EXPECT_EQ(P->getFactorNotificationMapSize(),0);
 
     // update solver
-    solver_ceres->update();
+    solver_ptr->update(); // nothing to update
 
-    // check local param
-    ASSERT_TRUE(solver_ceres->hasLocalParametrization(F->getO()));
-    ASSERT_TRUE(solver_ceres->hasThisLocalParametrization(F->getO(),local_param_ptr));
+    // check notifications
+    EXPECT_EQ(P->getStateBlockNotificationMapSize(),0);
+    EXPECT_EQ(P->getFactorNotificationMapSize(),0);
 
-    // check factor
-    ASSERT_TRUE(solver_ceres->isFactorRegistered(c1));
-    ASSERT_TRUE(solver_ceres->isFactorRegistered(c2));
-    ASSERT_EQ(solver_ceres->numFactors(), 2);
+    // checks
+    EXPECT_FALSE(solver_ptr->isStateBlockRegistered(sb_ptr));
+    EXPECT_FALSE(solver_ptr->isFactorRegistered(fac_ptr));
+    EXPECT_TRUE(solver_ptr->check());
+}
+
+////////////////////////////////////////////////////////
+// MULTITHREADING
+
+TEST(SolverCeres, MultiThreadingTruncatedNotifications)
+{
+    double Dt = 5.0;
+    ProblemPtr P = Problem::create("PO", 2);
+    auto solver_ptr = std::make_shared<SolverCeres>(P);
 
-    // run ceres manager check
-    ASSERT_TRUE(solver_ceres->check());
+    // loop updating (without sleep)
+    std::thread t([&](){
+        auto start_t = std::chrono::high_resolution_clock::now();
+        while (true)
+        {
+            solver_ptr->update();
+            ASSERT_TRUE(solver_ptr->check());
+            if (std::chrono::duration_cast<std::chrono::duration<double>>(std::chrono::high_resolution_clock::now() - start_t).count() > Dt)
+                break;
+        }});
+
+    // loop emplacing and removing frames (window of 10 KF)
+    auto start = std::chrono::high_resolution_clock::now();
+    TimeStamp ts(0);
+    while (true)
+    {
+        // Emplace Frame, Capture, feature and factor pose 2d
+        FrameBasePtr        F = P->emplaceKeyFrame(ts, P->stateZero());
+        auto C = CaptureBase::emplace<CaptureVoid>(F, ts, nullptr);
+        auto f = FeatureBase::emplace<FeatureBase>(C, "FeaturePose2d", Vector3d::Zero(), Matrix3d::Identity());
+        auto c = FactorBase::emplace<FactorPose2d>(f, f, nullptr, false);
+
+        ts += 1.0;
+
+        if (P->getTrajectory()->getFrameMap().size() > 10)
+            (*P->getTrajectory()->begin())->remove();
+
+        if (std::chrono::duration_cast<std::chrono::duration<double>>(std::chrono::high_resolution_clock::now() - start).count() > Dt)
+            break;
+    }
+
+    t.join();
 }
 
 int main(int argc, char **argv)
diff --git a/test/gtest_solver_manager.cpp b/test/gtest_solver_manager.cpp
index 30bf42ca390c4488c5227be99a2c59a5a1cb98c3..5226e125d79e059b29fbbfc3a432ce72452ef43c 100644
--- a/test/gtest_solver_manager.cpp
+++ b/test/gtest_solver_manager.cpp
@@ -13,8 +13,8 @@
 #include "core/state_block/state_block.h"
 #include "core/capture/capture_void.h"
 #include "core/factor/factor_pose_2d.h"
-#include "core/state_block/local_parametrization_base.h"
-#include "core/state_block/local_parametrization_angle.h"
+#include "core/factor/factor_block_absolute.h"
+#include "core/state_block/local_parametrization_quaternion.h"
 #include "dummy/solver_manager_dummy.h"
 
 #include <iostream>
@@ -23,546 +23,1508 @@
 using namespace wolf;
 using namespace Eigen;
 
+/*
+ * Following tests are the same as in gtest_solver_ceres.cpp
+ * (modifications should be applied to both tests)
+ */
+
+StateBlockPtr createStateBlock()
+{
+    Vector4d state; state << 1, 0, 0, 0;
+    return std::make_shared<StateBlock>(state);
+}
+
+FactorBasePtr createFactor(StateBlockPtr sb_ptr)
+{
+    return std::make_shared<FactorBlockAbsolute>(std::make_shared<FeatureBase>("Dummy",
+                                                                               VectorXd::Zero(sb_ptr->getSize()),
+                                                                               MatrixXd::Identity(sb_ptr->getSize(),sb_ptr->getSize())),
+                                                 sb_ptr,
+                                                 nullptr,
+                                                 false);
+}
+
 TEST(SolverManager, Create)
 {
-    ProblemPtr P = Problem::create("PO", 2);
-    SolverManagerDummyPtr solver_manager_ptr = std::make_shared<SolverManagerDummy>(P);
+    ProblemPtr P = Problem::create("PO", 3);
+    auto solver_ptr = std::make_shared<SolverManagerDummy>(P);
 
-    // check double pointers to branches
-    ASSERT_EQ(P, solver_manager_ptr->getProblem());
+    // check pointers
+    EXPECT_EQ(P, solver_ptr->getProblem());
+
+    // run solver check
+    EXPECT_TRUE(solver_ptr->check());
 }
 
-TEST(SolverManager, AddStateBlock)
+////////////////////////////////////////////////////////
+// FLOATING STATE BLOCKS
+TEST(SolverManager, FloatingStateBlock_Add)
 {
-    ProblemPtr P = Problem::create("PO", 2);
-    SolverManagerDummyPtr solver_manager_ptr = std::make_shared<SolverManagerDummy>(P);
+    ProblemPtr P = Problem::create("PO", 3);
+    auto solver_ptr = std::make_shared<SolverManagerDummy>(P);
 
     // Create State block
-    Vector2d state; state << 1, 2;
-    StateBlockPtr sb_ptr = std::make_shared<StateBlock>(state);
+    auto sb_ptr = createStateBlock();
 
-    // add stateblock
+    // notify stateblock
     P->notifyStateBlock(sb_ptr,ADD);
 
+    // check notifications
+    Notification notif;
+    EXPECT_TRUE(P->getStateBlockNotification(sb_ptr, notif));
+    EXPECT_EQ(ADD, notif);
+    EXPECT_EQ(P->getFactorNotificationMapSize(), 0);
+
     // update solver
-    solver_manager_ptr->update();
+    solver_ptr->update();
+
+    // check notifications
+    EXPECT_EQ(P->getStateBlockNotificationMapSize(), 0);
+    EXPECT_EQ(P->getFactorNotificationMapSize(), 0);
 
     // check stateblock
-    ASSERT_TRUE(solver_manager_ptr->isStateBlockRegistered(sb_ptr));
+    EXPECT_TRUE(solver_ptr->isStateBlockRegistered(sb_ptr));
+    EXPECT_TRUE(solver_ptr->isStateBlockFloating(sb_ptr));
+    EXPECT_TRUE(solver_ptr->check());
 }
 
-TEST(SolverManager, DoubleAddStateBlock)
+TEST(SolverManager, FloatingStateBlock_DoubleAdd)
 {
-    ProblemPtr P = Problem::create("PO", 2);
-    SolverManagerDummyPtr solver_manager_ptr = std::make_shared<SolverManagerDummy>(P);
+    ProblemPtr P = Problem::create("PO", 3);
+    auto solver_ptr = std::make_shared<SolverManagerDummy>(P);
 
     // Create State block
-    Vector2d state; state << 1, 2;
-    StateBlockPtr sb_ptr = std::make_shared<StateBlock>(state);
+    auto sb_ptr = createStateBlock();
 
-    // add stateblock
+    // notify stateblock
     P->notifyStateBlock(sb_ptr,ADD);
 
+    // check notifications
+    Notification notif;
+    EXPECT_TRUE(P->getStateBlockNotification(sb_ptr, notif));
+    EXPECT_EQ(ADD, notif);
+    EXPECT_EQ(P->getFactorNotificationMapSize(), 0);
+
     // update solver
-    solver_manager_ptr->update();
+    solver_ptr->update();
+
+    // check notifications
+    EXPECT_EQ(P->getStateBlockNotificationMapSize(), 0);
+    EXPECT_EQ(P->getFactorNotificationMapSize(), 0);
 
-    // add stateblock again
+    // notify stateblock again
     P->notifyStateBlock(sb_ptr,ADD);
 
+    // check notifications
+    EXPECT_TRUE(P->getStateBlockNotification(sb_ptr, notif));
+    EXPECT_EQ(ADD, notif);
+    EXPECT_EQ(P->getFactorNotificationMapSize(), 0);
+
     // update solver
-    solver_manager_ptr->update();
+    solver_ptr->update();
+
+    // check notifications
+    EXPECT_EQ(P->getStateBlockNotificationMapSize(), 0);
+    EXPECT_EQ(P->getFactorNotificationMapSize(), 0);
 
     // check stateblock
-    ASSERT_TRUE(solver_manager_ptr->isStateBlockRegistered(sb_ptr));
+    EXPECT_TRUE(solver_ptr->isStateBlockRegistered(sb_ptr));
+    EXPECT_TRUE(solver_ptr->isStateBlockFloating(sb_ptr));
+    EXPECT_TRUE(solver_ptr->check());
 }
 
-TEST(SolverManager, UpdateStateBlock)
+TEST(SolverManager, FloatingStateBlock_AddFix)
 {
-    ProblemPtr P = Problem::create("PO", 2);
-    SolverManagerDummyPtr solver_manager_ptr = std::make_shared<SolverManagerDummy>(P);
+    ProblemPtr P = Problem::create("PO", 3);
+    auto solver_ptr = std::make_shared<SolverManagerDummy>(P);
 
     // Create State block
-    Vector2d state; state << 1, 2;
-    StateBlockPtr sb_ptr = std::make_shared<StateBlock>(state);
+    auto sb_ptr = createStateBlock();
 
-    // add stateblock
+    // notify stateblock
     P->notifyStateBlock(sb_ptr,ADD);
 
+    // check notifications
+    Notification notif;
+    EXPECT_TRUE(P->getStateBlockNotification(sb_ptr, notif));
+    EXPECT_EQ(ADD, notif);
+    EXPECT_EQ(P->getFactorNotificationMapSize(), 0);
+
     // check flags
-    ASSERT_FALSE(sb_ptr->stateUpdated());
-    ASSERT_FALSE(sb_ptr->fixUpdated());
-    ASSERT_FALSE(sb_ptr->localParamUpdated());
+    EXPECT_FALSE(sb_ptr->stateUpdated());
+    EXPECT_FALSE(sb_ptr->fixUpdated());
+    EXPECT_FALSE(sb_ptr->localParamUpdated());
 
     // update solver
-    solver_manager_ptr->update();
+    solver_ptr->update();
+
+    // check notifications
+    EXPECT_EQ(P->getStateBlockNotificationMapSize(), 0);
+    EXPECT_EQ(P->getFactorNotificationMapSize(), 0);
 
     // check flags
-    ASSERT_FALSE(sb_ptr->stateUpdated());
-    ASSERT_FALSE(sb_ptr->fixUpdated());
-    ASSERT_FALSE(sb_ptr->localParamUpdated());
+    EXPECT_FALSE(sb_ptr->stateUpdated());
+    EXPECT_FALSE(sb_ptr->fixUpdated());
+    EXPECT_FALSE(sb_ptr->localParamUpdated());
 
     // check stateblock unfixed
-    ASSERT_FALSE(solver_manager_ptr->isStateBlockFixed(sb_ptr));
+    EXPECT_FALSE(solver_ptr->isStateBlockFixed(sb_ptr));
+    EXPECT_TRUE(solver_ptr->isStateBlockFloating(sb_ptr));
+    EXPECT_TRUE(solver_ptr->check());
 
     // Fix frame
     sb_ptr->fix();
 
+    // check notifications
+    EXPECT_EQ(P->getStateBlockNotificationMapSize(), 0);
+    EXPECT_EQ(P->getFactorNotificationMapSize(), 0);
+
     // check flags
-    ASSERT_FALSE(sb_ptr->stateUpdated());
-    ASSERT_TRUE(sb_ptr->fixUpdated());
-    ASSERT_FALSE(sb_ptr->localParamUpdated());
+    EXPECT_FALSE(sb_ptr->stateUpdated());
+    EXPECT_TRUE(sb_ptr->fixUpdated());
+    EXPECT_FALSE(sb_ptr->localParamUpdated());
 
     // update solver manager
-    solver_manager_ptr->update();
+    solver_ptr->update();
+
+    // check notifications
+    EXPECT_EQ(P->getStateBlockNotificationMapSize(), 0);
+    EXPECT_EQ(P->getFactorNotificationMapSize(), 0);
 
     // check flags
-    ASSERT_FALSE(sb_ptr->stateUpdated());
-    ASSERT_FALSE(sb_ptr->fixUpdated());
-    ASSERT_FALSE(sb_ptr->localParamUpdated());
+    EXPECT_FALSE(sb_ptr->stateUpdated());
+    EXPECT_FALSE(sb_ptr->fixUpdated());
+    EXPECT_FALSE(sb_ptr->localParamUpdated());
 
     // check stateblock fixed
-    ASSERT_TRUE(solver_manager_ptr->isStateBlockFixed(sb_ptr));
+    EXPECT_TRUE(solver_ptr->isStateBlockFixed(sb_ptr));
+    EXPECT_TRUE(solver_ptr->isStateBlockFloating(sb_ptr));
+    EXPECT_TRUE(solver_ptr->check());
 }
 
-TEST(SolverManager, AddUpdateStateBlock)
+TEST(SolverManager, FloatingStateBlock_AddFixed)
 {
-    ProblemPtr P = Problem::create("PO", 2);
-    SolverManagerDummyPtr solver_manager_ptr = std::make_shared<SolverManagerDummy>(P);
+    ProblemPtr P = Problem::create("PO", 3);
+    auto solver_ptr = std::make_shared<SolverManagerDummy>(P);
 
     // Create State block
-    Vector2d state; state << 1, 2;
-    StateBlockPtr sb_ptr = std::make_shared<StateBlock>(state);
+    auto sb_ptr = createStateBlock();
 
-    // add stateblock
+    // notify stateblock
     P->notifyStateBlock(sb_ptr,ADD);
 
+    // check notifications
+    Notification notif;
+    EXPECT_TRUE(P->getStateBlockNotification(sb_ptr, notif));
+    EXPECT_EQ(ADD, notif);
+    EXPECT_EQ(P->getFactorNotificationMapSize(), 0);
+
     // check flags
-    ASSERT_FALSE(sb_ptr->stateUpdated());
-    ASSERT_FALSE(sb_ptr->fixUpdated());
-    ASSERT_FALSE(sb_ptr->localParamUpdated());
+    EXPECT_FALSE(sb_ptr->stateUpdated());
+    EXPECT_FALSE(sb_ptr->fixUpdated());
+    EXPECT_FALSE(sb_ptr->localParamUpdated());
 
     // Fix state block
     sb_ptr->fix();
 
     // check flags
-    ASSERT_FALSE(sb_ptr->stateUpdated());
-    ASSERT_TRUE(sb_ptr->fixUpdated());
-    ASSERT_FALSE(sb_ptr->localParamUpdated());
+    EXPECT_FALSE(sb_ptr->stateUpdated());
+    EXPECT_TRUE(sb_ptr->fixUpdated());
+    EXPECT_FALSE(sb_ptr->localParamUpdated());
 
     // update solver manager
-    solver_manager_ptr->update();
+    solver_ptr->update();
+
+    // check notifications
+    EXPECT_EQ(P->getStateBlockNotificationMapSize(), 0);
+    EXPECT_EQ(P->getFactorNotificationMapSize(), 0);
 
     // check flags
-    ASSERT_FALSE(sb_ptr->stateUpdated());
-    ASSERT_FALSE(sb_ptr->fixUpdated());
-    ASSERT_FALSE(sb_ptr->localParamUpdated());
+    EXPECT_FALSE(sb_ptr->stateUpdated());
+    EXPECT_FALSE(sb_ptr->fixUpdated());
+    EXPECT_FALSE(sb_ptr->localParamUpdated());
 
     // check stateblock fixed
-    ASSERT_TRUE(solver_manager_ptr->isStateBlockRegistered(sb_ptr));
-    ASSERT_TRUE(solver_manager_ptr->isStateBlockFixed(sb_ptr));
+    EXPECT_TRUE(solver_ptr->isStateBlockRegistered(sb_ptr));
+    EXPECT_TRUE(solver_ptr->isStateBlockFixed(sb_ptr));
+    EXPECT_TRUE(solver_ptr->isStateBlockFloating(sb_ptr));
+    EXPECT_TRUE(solver_ptr->check());
 }
 
-TEST(SolverManager, AddUpdateLocalParamStateBlock)
+TEST(SolverManager, FloatingStateBlock_AddUpdateLocalParam)
 {
-    ProblemPtr P = Problem::create("PO", 2);
-    SolverManagerDummyPtr solver_manager_ptr = std::make_shared<SolverManagerDummy>(P);
+    ProblemPtr P = Problem::create("PO", 3);
+    auto solver_ptr = std::make_shared<SolverManagerDummy>(P);
 
     // Create State block
-    Vector2d state; state << 1, 2;
-    StateBlockPtr sb_ptr = std::make_shared<StateBlock>(state);
+    auto sb_ptr = createStateBlock();
 
-    // add stateblock
+    // notify stateblock
     P->notifyStateBlock(sb_ptr,ADD);
 
+    // check notifications
+    Notification notif;
+    EXPECT_TRUE(P->getStateBlockNotification(sb_ptr, notif));
+    EXPECT_EQ(ADD, notif);
+    EXPECT_EQ(P->getFactorNotificationMapSize(), 0);
+
     // check flags
-    ASSERT_FALSE(sb_ptr->stateUpdated());
-    ASSERT_FALSE(sb_ptr->fixUpdated());
-    ASSERT_FALSE(sb_ptr->localParamUpdated());
+    EXPECT_FALSE(sb_ptr->stateUpdated());
+    EXPECT_FALSE(sb_ptr->fixUpdated());
+    EXPECT_FALSE(sb_ptr->localParamUpdated());
 
     // Local param
-    LocalParametrizationBasePtr local_ptr = std::make_shared<LocalParametrizationAngle>();
+    LocalParametrizationBasePtr local_ptr = std::make_shared<LocalParametrizationQuaternionLocal>();
     sb_ptr->setLocalParametrization(local_ptr);
 
     // Fix state block
     sb_ptr->fix();
 
     // check flags
-    ASSERT_FALSE(sb_ptr->stateUpdated());
-    ASSERT_TRUE(sb_ptr->fixUpdated());
-    ASSERT_TRUE(sb_ptr->localParamUpdated());
+    EXPECT_FALSE(sb_ptr->stateUpdated());
+    EXPECT_TRUE(sb_ptr->fixUpdated());
+    EXPECT_TRUE(sb_ptr->localParamUpdated());
+    solver_ptr->update();
+
+    // check notifications
+    EXPECT_EQ(P->getStateBlockNotificationMapSize(), 0);
+    EXPECT_EQ(P->getFactorNotificationMapSize(), 0);
 
     // update solver manager
-    solver_manager_ptr->update();
+    solver_ptr->update();
+    solver_ptr->update();
+
+    // check notifications
+    EXPECT_EQ(P->getStateBlockNotificationMapSize(), 0);
+    EXPECT_EQ(P->getFactorNotificationMapSize(), 0);
 
     // check flags
-    ASSERT_FALSE(sb_ptr->stateUpdated());
-    ASSERT_FALSE(sb_ptr->fixUpdated());
-    ASSERT_FALSE(sb_ptr->localParamUpdated());
+    EXPECT_FALSE(sb_ptr->stateUpdated());
+    EXPECT_FALSE(sb_ptr->fixUpdated());
+    EXPECT_FALSE(sb_ptr->localParamUpdated());
 
     // check stateblock fixed
-    ASSERT_TRUE(solver_manager_ptr->isStateBlockRegistered(sb_ptr));
-    ASSERT_TRUE(solver_manager_ptr->isStateBlockFixed(sb_ptr));
-    ASSERT_TRUE(solver_manager_ptr->hasThisLocalParametrization(sb_ptr,local_ptr));
+    EXPECT_TRUE(solver_ptr->isStateBlockFixed(sb_ptr));
+    EXPECT_TRUE(solver_ptr->hasThisLocalParametrization(sb_ptr,local_ptr));
+    EXPECT_TRUE(solver_ptr->isStateBlockRegistered(sb_ptr));
+    EXPECT_TRUE(solver_ptr->isStateBlockFloating(sb_ptr));
+    EXPECT_TRUE(solver_ptr->check());
 }
 
-TEST(SolverManager, AddLocalParamRemoveLocalParamStateBlock)
+TEST(SolverManager, FloatingStateBlock_AddLocalParamRemoveLocalParam)
 {
-    ProblemPtr P = Problem::create("PO", 2);
-    SolverManagerDummyPtr solver_manager_ptr = std::make_shared<SolverManagerDummy>(P);
+    ProblemPtr P = Problem::create("PO", 3);
+    auto solver_ptr = std::make_shared<SolverManagerDummy>(P);
 
     // Create State block
-    Vector2d state; state << 1, 2;
-    StateBlockPtr sb_ptr = std::make_shared<StateBlock>(state);
+    auto sb_ptr = createStateBlock();
 
     // Local param
-    LocalParametrizationBasePtr local_ptr = std::make_shared<LocalParametrizationAngle>();
+    LocalParametrizationBasePtr local_ptr = std::make_shared<LocalParametrizationQuaternionLocal>();
     sb_ptr->setLocalParametrization(local_ptr);
 
     // check flags
-    ASSERT_FALSE(sb_ptr->stateUpdated());
-    ASSERT_FALSE(sb_ptr->fixUpdated());
-    ASSERT_TRUE(sb_ptr->localParamUpdated());
+    EXPECT_FALSE(sb_ptr->stateUpdated());
+    EXPECT_FALSE(sb_ptr->fixUpdated());
+    EXPECT_TRUE(sb_ptr->localParamUpdated());
 
-    // add stateblock
+    // notify stateblock
     P->notifyStateBlock(sb_ptr,ADD);
 
+    // check notifications
+    Notification notif;
+    EXPECT_TRUE(P->getStateBlockNotification(sb_ptr, notif));
+    EXPECT_EQ(ADD, notif);
+    EXPECT_EQ(P->getFactorNotificationMapSize(), 0);
+
     // update solver manager
-    solver_manager_ptr->update();
+    solver_ptr->update();
+
+    // check notifications
+    EXPECT_EQ(P->getStateBlockNotificationMapSize(), 0);
+    EXPECT_EQ(P->getFactorNotificationMapSize(), 0);
 
     // check stateblock localparam
-    ASSERT_TRUE(solver_manager_ptr->hasThisLocalParametrization(sb_ptr,local_ptr));
+    EXPECT_TRUE(solver_ptr->hasThisLocalParametrization(sb_ptr,local_ptr));
 
     // check flags
-    ASSERT_FALSE(sb_ptr->stateUpdated());
-    ASSERT_FALSE(sb_ptr->fixUpdated());
-    ASSERT_FALSE(sb_ptr->localParamUpdated());
+    EXPECT_FALSE(sb_ptr->stateUpdated());
+    EXPECT_FALSE(sb_ptr->fixUpdated());
+    EXPECT_FALSE(sb_ptr->localParamUpdated());
 
     // Remove local param
     sb_ptr->removeLocalParametrization();
 
     // check flags
-    ASSERT_FALSE(sb_ptr->stateUpdated());
-    ASSERT_FALSE(sb_ptr->fixUpdated());
-    ASSERT_TRUE(sb_ptr->localParamUpdated());
+    EXPECT_FALSE(sb_ptr->stateUpdated());
+    EXPECT_FALSE(sb_ptr->fixUpdated());
+    EXPECT_TRUE(sb_ptr->localParamUpdated());
 
     // update solver manager
-    solver_manager_ptr->update();
+    solver_ptr->update();
+
+    // check notifications
+    EXPECT_EQ(P->getStateBlockNotificationMapSize(), 0);
+    EXPECT_EQ(P->getFactorNotificationMapSize(), 0);
 
     // check stateblock localparam
-    ASSERT_FALSE(solver_manager_ptr->hasLocalParametrization(sb_ptr));
+    EXPECT_FALSE(solver_ptr->hasLocalParametrization(sb_ptr));
+    EXPECT_TRUE(solver_ptr->isStateBlockRegistered(sb_ptr));
+    EXPECT_TRUE(solver_ptr->isStateBlockFloating(sb_ptr));
+    EXPECT_TRUE(solver_ptr->check());
 }
 
-TEST(SolverManager, RemoveStateBlock)
+TEST(SolverManager, FloatingStateBlock_Remove)
 {
-    ProblemPtr P = Problem::create("PO", 2);
-    SolverManagerDummyPtr solver_manager_ptr = std::make_shared<SolverManagerDummy>(P);
+    ProblemPtr P = Problem::create("PO", 3);
+    auto solver_ptr = std::make_shared<SolverManagerDummy>(P);
 
     // Create State block
-    Vector2d state; state << 1, 2;
-    StateBlockPtr sb_ptr = std::make_shared<StateBlock>(state);
+    auto sb_ptr = createStateBlock();
 
-    // add stateblock
+    // notify stateblock
     P->notifyStateBlock(sb_ptr,ADD);
 
+    // check notifications
+    Notification notif;
+    EXPECT_TRUE(P->getStateBlockNotification(sb_ptr, notif));
+    EXPECT_EQ(ADD, notif);
+    EXPECT_EQ(P->getFactorNotificationMapSize(), 0);
+
     // update solver
-    solver_manager_ptr->update();
+    solver_ptr->update();
+
+    // check notifications
+    EXPECT_EQ(P->getStateBlockNotificationMapSize(), 0);
+    EXPECT_EQ(P->getFactorNotificationMapSize(), 0);
 
     // remove state_block
     P->notifyStateBlock(sb_ptr,REMOVE);
 
+    // check notifications
+    EXPECT_TRUE(P->getStateBlockNotification(sb_ptr, notif));
+    EXPECT_EQ(REMOVE, notif);
+    EXPECT_EQ(P->getFactorNotificationMapSize(), 0);
+
     // update solver
-    solver_manager_ptr->update();
+    solver_ptr->update();
+
+    // check notifications
+    EXPECT_EQ(P->getStateBlockNotificationMapSize(), 0);
+    EXPECT_EQ(P->getFactorNotificationMapSize(), 0);
 
     // check stateblock
-    ASSERT_FALSE(solver_manager_ptr->isStateBlockRegistered(sb_ptr));
+    EXPECT_FALSE(solver_ptr->isStateBlockRegistered(sb_ptr));
+    EXPECT_TRUE(solver_ptr->check());
 }
 
-TEST(SolverManager, AddRemoveStateBlock)
+TEST(SolverManager, FloatingStateBlock_AddRemove)
 {
-    ProblemPtr P = Problem::create("PO", 2);
-    SolverManagerDummyPtr solver_manager_ptr = std::make_shared<SolverManagerDummy>(P);
+    ProblemPtr P = Problem::create("PO", 3);
+    auto solver_ptr = std::make_shared<SolverManagerDummy>(P);
 
     // Create State block
-    Vector2d state; state << 1, 2;
-    StateBlockPtr sb_ptr = std::make_shared<StateBlock>(state);
+    auto sb_ptr = createStateBlock();
 
-    // add stateblock
+    // notify stateblock
     P->notifyStateBlock(sb_ptr,ADD);
 
+    // check notifications
+    Notification notif;
+    EXPECT_TRUE(P->getStateBlockNotification(sb_ptr, notif));
+    EXPECT_EQ(ADD, notif);
+    EXPECT_EQ(P->getFactorNotificationMapSize(), 0);
+
     // remove state_block
-    P->notifyStateBlock(sb_ptr,REMOVE);
+    P->notifyStateBlock(sb_ptr,REMOVE); // should cancel out the ADD
+
+    // check notifications
+    EXPECT_EQ(P->getStateBlockNotificationMapSize(), 0);
+    EXPECT_EQ(P->getFactorNotificationMapSize(), 0);
 
     // update solver
-    solver_manager_ptr->update();
+    solver_ptr->update();
+
+    // check notifications
+    EXPECT_EQ(P->getStateBlockNotificationMapSize(), 0);
+    EXPECT_EQ(P->getFactorNotificationMapSize(), 0);
 
     // check state block
-    ASSERT_FALSE(solver_manager_ptr->isStateBlockRegistered(sb_ptr));
+    EXPECT_FALSE(solver_ptr->isStateBlockRegistered(sb_ptr));
+    EXPECT_TRUE(solver_ptr->check());
 }
 
-TEST(SolverManager, RemoveUpdateStateBlock)
+TEST(SolverManager, FloatingStateBlock_AddRemoveAdd)
 {
-    ProblemPtr P = Problem::create("PO", 2);
-    SolverManagerDummyPtr solver_manager_ptr = std::make_shared<SolverManagerDummy>(P);
+    ProblemPtr P = Problem::create("PO", 3);
+    auto solver_ptr = std::make_shared<SolverManagerDummy>(P);
 
     // Create State block
-    Vector2d state; state << 1, 2;
-    StateBlockPtr sb_ptr = std::make_shared<StateBlock>(state);
+    auto sb_ptr = createStateBlock();
 
-    // add state_block
+    // notify stateblock
     P->notifyStateBlock(sb_ptr,ADD);
 
+    // check notifications
+    Notification notif;
+    EXPECT_TRUE(P->getStateBlockNotification(sb_ptr, notif));
+    EXPECT_EQ(ADD, notif);
+    EXPECT_EQ(P->getFactorNotificationMapSize(), 0);
+
     // remove state_block
-    P->notifyStateBlock(sb_ptr,REMOVE);
+    P->notifyStateBlock(sb_ptr,REMOVE); // should cancell out the ADD
+
+    // check notifications
+    EXPECT_EQ(P->getStateBlockNotificationMapSize(), 0);
+    EXPECT_EQ(P->getFactorNotificationMapSize(), 0);
+
+    // notify stateblock
+    P->notifyStateBlock(sb_ptr,ADD); // again ADD in notification list
+
+    // check notifications
+    EXPECT_TRUE(P->getStateBlockNotification(sb_ptr, notif));
+    EXPECT_EQ(ADD, notif);
+    EXPECT_EQ(P->getFactorNotificationMapSize(), 0);
 
     // update solver
-    solver_manager_ptr->update();
+    solver_ptr->update();
+
+    // check notifications
+    EXPECT_EQ(P->getStateBlockNotificationMapSize(), 0);
+    EXPECT_EQ(P->getFactorNotificationMapSize(), 0);
+
+    // check state block
+    EXPECT_TRUE(solver_ptr->isStateBlockRegistered(sb_ptr));
+    EXPECT_TRUE(solver_ptr->check());
 }
 
-TEST(SolverManager, DoubleRemoveStateBlock)
+TEST(SolverManager, FloatingStateBlock_DoubleRemove)
 {
-    ProblemPtr P = Problem::create("PO", 2);
-    SolverManagerDummyPtr solver_manager_ptr = std::make_shared<SolverManagerDummy>(P);
+    ProblemPtr P = Problem::create("PO", 3);
+    auto solver_ptr = std::make_shared<SolverManagerDummy>(P);
 
     // Create State block
-    Vector2d state; state << 1, 2;
-    StateBlockPtr sb_ptr = std::make_shared<StateBlock>(state);
+    auto sb_ptr = createStateBlock();
 
-    // add stateblock
+    // notify stateblock
     P->notifyStateBlock(sb_ptr,ADD);
 
+    // update solver
+    solver_ptr->update();
+
     // remove state_block
     P->notifyStateBlock(sb_ptr,REMOVE);
 
     // update solver
-    solver_manager_ptr->update();
+    solver_ptr->update();
 
     // remove state_block
     P->notifyStateBlock(sb_ptr,REMOVE);
 
+    // check notifications
+    Notification notif;
+    EXPECT_TRUE(P->getStateBlockNotification(sb_ptr, notif));
+    EXPECT_EQ(REMOVE, notif);
+    EXPECT_EQ(P->getFactorNotificationMapSize(), 0);
+
     // update solver manager
-    solver_manager_ptr->update();
+    solver_ptr->update();
+
+    // check notifications
+    EXPECT_EQ(P->getStateBlockNotificationMapSize(), 0);
+    EXPECT_EQ(P->getFactorNotificationMapSize(), 0);
+
+    // checks
+    EXPECT_TRUE(solver_ptr->check());
 }
 
-TEST(SolverManager, AddUpdatedStateBlock)
+TEST(SolverManager, FloatingStateBlock_AddUpdated)
 {
-    ProblemPtr P = Problem::create("PO", 2);
-    SolverManagerDummyPtr solver_manager_ptr = std::make_shared<SolverManagerDummy>(P);
+    ProblemPtr P = Problem::create("PO", 3);
+    auto solver_ptr = std::make_shared<SolverManagerDummy>(P);
 
     // Create State block
-    Vector2d state; state << 1, 2;
-    StateBlockPtr sb_ptr = std::make_shared<StateBlock>(state);
+    auto sb_ptr = createStateBlock();
 
     // Fix
     sb_ptr->fix();
 
     // Set State
-    Vector2d state_2 = 2*state;
-    sb_ptr->setState(state_2);
+    sb_ptr->setState(2*sb_ptr->getState());
 
     // Check flags have been set true
-    ASSERT_TRUE(sb_ptr->fixUpdated());
-    ASSERT_TRUE(sb_ptr->stateUpdated());
+    EXPECT_TRUE(sb_ptr->fixUpdated());
+    EXPECT_TRUE(sb_ptr->stateUpdated());
 
     // == When an ADD is notified: a ADD notification should be stored ==
 
-    // add state_block
+    // notify state block
     P->notifyStateBlock(sb_ptr,ADD);
 
+    // check notifications
+    // check notifications
     Notification notif;
-    ASSERT_EQ(P->getStateBlockNotificationMapSize(),1);
-    ASSERT_TRUE(P->getStateBlockNotification(sb_ptr, notif));
-    ASSERT_EQ(notif, ADD);
+    EXPECT_EQ(P->getStateBlockNotificationMapSize(),1);
+    EXPECT_TRUE(P->getStateBlockNotification(sb_ptr, notif));
+    EXPECT_EQ(notif, ADD);
 
     // == Insert OTHER notifications ==
 
     // Set State --> FLAG
-    state_2 = 2*state;
-    sb_ptr->setState(state_2);
+    sb_ptr->setState(2*sb_ptr->getState());
 
     // Fix --> FLAG
     sb_ptr->unfix();
     // Check flag has been set true
-    ASSERT_TRUE(sb_ptr->fixUpdated());
+    EXPECT_TRUE(sb_ptr->fixUpdated());
 
-    ASSERT_EQ(P->getStateBlockNotificationMapSize(),1); // No new notifications (fix and set state are flags in sb)
+    EXPECT_EQ(P->getStateBlockNotificationMapSize(),1); // No new notifications (fix and set state are flags in sb)
 
     // == consume empties the notification map ==
-    solver_manager_ptr->update(); // it calls P->consumeStateBlockNotificationMap();
-    ASSERT_EQ(P->getStateBlockNotificationMapSize(),0);
+    solver_ptr->update(); // it calls P->consumeStateBlockNotificationMap();
+    EXPECT_EQ(P->getStateBlockNotificationMapSize(),0);
     // Check flags have been reset
-    ASSERT_FALSE(sb_ptr->fixUpdated());
-    ASSERT_FALSE(sb_ptr->stateUpdated());
+    EXPECT_FALSE(sb_ptr->fixUpdated());
+    EXPECT_FALSE(sb_ptr->stateUpdated());
 
     // == When an REMOVE is notified: a REMOVE notification should be stored ==
 
     // remove state_block
     P->notifyStateBlock(sb_ptr,REMOVE);
 
-    ASSERT_EQ(P->getStateBlockNotificationMapSize(),1);
-    ASSERT_TRUE(P->getStateBlockNotification(sb_ptr, notif));
-    ASSERT_EQ(notif, REMOVE);
+    // check notifications
+    EXPECT_EQ(P->getStateBlockNotificationMapSize(),1);
+    EXPECT_TRUE(P->getStateBlockNotification(sb_ptr, notif));
+    EXPECT_EQ(notif, REMOVE);
 
     // == REMOVE + ADD: notification map should be empty ==
     P->notifyStateBlock(sb_ptr,ADD);
-    ASSERT_EQ(P->getStateBlockNotificationMapSize(),0);
+    EXPECT_EQ(P->getStateBlockNotificationMapSize(),0);
 
     // == UPDATES should clear the list of notifications ==
-    // add state_block
+    // notify state block
     P->notifyStateBlock(sb_ptr,ADD);
 
     // update solver
-    solver_manager_ptr->update();
+    solver_ptr->update();
 
-    ASSERT_EQ(P->getStateBlockNotificationMapSize(),0); // After solver_manager->update, notifications should be empty
+    // check notifications
+    EXPECT_EQ(P->getStateBlockNotificationMapSize(),0); // After solver_manager->update, notifications should be empty
+    EXPECT_EQ(P->getFactorNotificationMapSize(), 0);
 
     // == ADD + REMOVE: notification map should be empty ==
     P->notifyStateBlock(sb_ptr,ADD);
     P->notifyStateBlock(sb_ptr,REMOVE);
-    ASSERT_EQ(P->getStateBlockNotificationMapSize(),0);
+    EXPECT_EQ(P->getStateBlockNotificationMapSize(),0);
 }
 
-TEST(SolverManager, AddFactor)
+////////////////////////////////////////////////////////
+// STATE BLOCKS AND FACTOR
+TEST(SolverManager, StateBlockAndFactor_Add)
 {
-    ProblemPtr P = Problem::create("PO", 2);
-    SolverManagerDummyPtr solver_manager_ptr = std::make_shared<SolverManagerDummy>(P);
+    ProblemPtr P = Problem::create("PO", 3);
+    auto solver_ptr = std::make_shared<SolverManagerDummy>(P);
 
     // Create State block
-    Vector2d state; state << 1, 2;
-    StateBlockPtr sb_ptr = std::make_shared<StateBlock>(state);
+    auto sb_ptr = createStateBlock();
+
+    // Create Factor
+    auto fac_ptr = createFactor(sb_ptr);
 
-    // Create (and add) factor point 2d
-    FrameBasePtr        F = P->emplaceKeyFrame(0, P->stateZero() );
-    auto C = CaptureBase::emplace<CaptureVoid>(F, 0, nullptr);
-    auto f = FeatureBase::emplace<FeatureBase>(C, "FeatureOdom2d", Vector3d::Zero(), Matrix3d::Identity());
-    auto c = FactorBase::emplace<FactorPose2d>(f, f, nullptr, false);
+    // notify stateblock (floating for the moment)
+    P->notifyStateBlock(sb_ptr,ADD);
 
-    // notification
+    // check notifications
     Notification notif;
-    ASSERT_TRUE(P->getFactorNotification(c,notif));
-    ASSERT_EQ(notif, ADD);
+    EXPECT_TRUE(P->getStateBlockNotification(sb_ptr, notif));
+    EXPECT_EQ(ADD, notif);
+    EXPECT_EQ(P->getFactorNotificationMapSize(), 0);
+
+    // update solver
+    solver_ptr->update();
+
+    // checks
+    EXPECT_TRUE(solver_ptr->isStateBlockRegistered(sb_ptr));
+    EXPECT_TRUE(solver_ptr->isStateBlockFloating(sb_ptr));
+
+    // notify factor (state block now not floating)
+    P->notifyFactor(fac_ptr,ADD);
+
+    // check notifications
+    EXPECT_TRUE(P->getFactorNotification(fac_ptr, notif));
+    EXPECT_EQ(ADD, notif);
+    EXPECT_EQ(P->getStateBlockNotificationMapSize(), 0);
 
     // update solver
-    solver_manager_ptr->update();
+    solver_ptr->update();
+
+    // check notifications
+    EXPECT_EQ(P->getStateBlockNotificationMapSize(),0);
+    EXPECT_EQ(P->getFactorNotificationMapSize(), 0);
 
-    // check factor
-    ASSERT_TRUE(solver_manager_ptr->isFactorRegistered(c));
+    // checks
+    EXPECT_TRUE(solver_ptr->isStateBlockRegistered(sb_ptr));
+    EXPECT_FALSE(solver_ptr->isStateBlockFloating(sb_ptr));
+    EXPECT_TRUE(solver_ptr->isFactorRegistered(fac_ptr));
+    EXPECT_TRUE(solver_ptr->check());
 }
 
-TEST(SolverManager, RemoveFactor)
+TEST(SolverManager, StateBlockAndFactor_DoubleAdd)
 {
-    ProblemPtr P = Problem::create("PO", 2);
-    SolverManagerDummyPtr solver_manager_ptr = std::make_shared<SolverManagerDummy>(P);
+    ProblemPtr P = Problem::create("PO", 3);
+    auto solver_ptr = std::make_shared<SolverManagerDummy>(P);
 
     // Create State block
-    Vector2d state; state << 1, 2;
-    StateBlockPtr sb_ptr = std::make_shared<StateBlock>(state);
+    auto sb_ptr = createStateBlock();
+
+    // Create Factor
+    auto fac_ptr = createFactor(sb_ptr);
 
-    // Create (and add) factor point 2d
-    FrameBasePtr        F = P->emplaceKeyFrame(0, P->stateZero() );
-    auto C = CaptureBase::emplace<CaptureVoid>(F, 0, nullptr);
-    auto f = FeatureBase::emplace<FeatureBase>(C, "FeatureOdom2d", Vector3d::Zero(), Matrix3d::Identity());
-    auto c = FactorBase::emplace<FactorPose2d>(f, f, nullptr, false);
+    // notify stateblock
+    P->notifyStateBlock(sb_ptr,ADD);
+
+    // notify factor
+    P->notifyFactor(fac_ptr,ADD);
+
+    // check notifications
+    Notification notif;
+    EXPECT_TRUE(P->getStateBlockNotification(sb_ptr, notif));
+    EXPECT_EQ(ADD, notif);
+    EXPECT_TRUE(P->getFactorNotification(fac_ptr, notif));
+    EXPECT_EQ(ADD, notif);
 
     // update solver
-    solver_manager_ptr->update();
+    solver_ptr->update();
+    solver_ptr->update();
+
+    // check notifications
+    EXPECT_EQ(P->getStateBlockNotificationMapSize(),0);
+    EXPECT_EQ(P->getFactorNotificationMapSize(), 0);
+
+    // notify stateblock again
+    P->notifyStateBlock(sb_ptr,ADD);
+
+    // notify factor
+    P->notifyFactor(fac_ptr,ADD);
+
+    // check notifications
+    EXPECT_TRUE(P->getStateBlockNotification(sb_ptr, notif));
+    EXPECT_EQ(ADD, notif);
+    EXPECT_TRUE(P->getFactorNotification(fac_ptr, notif));
+    EXPECT_EQ(ADD, notif);
+
+    // update solver
+    solver_ptr->update();
+
+    // check notifications
+    EXPECT_EQ(P->getStateBlockNotificationMapSize(),0);
+    EXPECT_EQ(P->getFactorNotificationMapSize(), 0);
+
+    // check stateblock
+    EXPECT_TRUE(solver_ptr->isStateBlockRegistered(sb_ptr));
+    EXPECT_FALSE(solver_ptr->isStateBlockFloating(sb_ptr));
+    EXPECT_TRUE(solver_ptr->isFactorRegistered(fac_ptr));
+    EXPECT_TRUE(solver_ptr->check());
+}
+
+TEST(SolverManager, StateBlockAndFactor_Fix)
+{
+    ProblemPtr P = Problem::create("PO", 3);
+    auto solver_ptr = std::make_shared<SolverManagerDummy>(P);
+
+    // Create State block
+    auto sb_ptr = createStateBlock();
 
-    // add factor
-    P->notifyFactor(c,REMOVE);
+    // Create Factor
+    auto fac_ptr = createFactor(sb_ptr);
 
-    // notification
+    // notify stateblock
+    P->notifyStateBlock(sb_ptr,ADD);
+
+    // notify factor
+    P->notifyFactor(fac_ptr,ADD);
+
+    // check notifications
     Notification notif;
-    ASSERT_TRUE(P->getFactorNotification(c,notif));
-    ASSERT_EQ(notif, REMOVE);
+    EXPECT_TRUE(P->getStateBlockNotification(sb_ptr, notif));
+    EXPECT_EQ(ADD, notif);
+    EXPECT_TRUE(P->getFactorNotification(fac_ptr, notif));
+    EXPECT_EQ(ADD, notif);
+
+    // check flags
+    EXPECT_FALSE(sb_ptr->stateUpdated());
+    EXPECT_FALSE(sb_ptr->fixUpdated());
+    EXPECT_FALSE(sb_ptr->localParamUpdated());
 
     // update solver
-    solver_manager_ptr->update();
+    solver_ptr->update();
+
+    // check notifications
+    EXPECT_EQ(P->getStateBlockNotificationMapSize(),0);
+    EXPECT_EQ(P->getFactorNotificationMapSize(), 0);
+
+    // check flags
+    EXPECT_FALSE(sb_ptr->stateUpdated());
+    EXPECT_FALSE(sb_ptr->fixUpdated());
+    EXPECT_FALSE(sb_ptr->localParamUpdated());
+
+    // check stateblock unfixed
+    EXPECT_FALSE(solver_ptr->isStateBlockFixed(sb_ptr));
+    EXPECT_TRUE(solver_ptr->check());
+
+    // Fix frame
+    sb_ptr->fix();
 
-    // check factor
-    ASSERT_FALSE(solver_manager_ptr->isFactorRegistered(c));
+    // check flags
+    EXPECT_FALSE(sb_ptr->stateUpdated());
+    EXPECT_TRUE(sb_ptr->fixUpdated());
+    EXPECT_FALSE(sb_ptr->localParamUpdated());
+
+    // check notifications
+    EXPECT_EQ(P->getStateBlockNotificationMapSize(),0);
+    EXPECT_EQ(P->getFactorNotificationMapSize(), 0);
+
+    // update solver manager
+    solver_ptr->update();
+
+    // check notifications
+    EXPECT_EQ(P->getStateBlockNotificationMapSize(),0);
+    EXPECT_EQ(P->getFactorNotificationMapSize(), 0);
+
+    // check flags
+    EXPECT_FALSE(sb_ptr->stateUpdated());
+    EXPECT_FALSE(sb_ptr->fixUpdated());
+    EXPECT_FALSE(sb_ptr->localParamUpdated());
+
+    // check stateblock fixed
+    EXPECT_TRUE(solver_ptr->isStateBlockFixed(sb_ptr));
+    EXPECT_TRUE(solver_ptr->check());
 }
 
-TEST(SolverManager, AddRemoveFactor)
+TEST(SolverManager, StateBlockAndFactor_AddFixed)
 {
-    ProblemPtr P = Problem::create("PO", 2);
-    SolverManagerDummyPtr solver_manager_ptr = std::make_shared<SolverManagerDummy>(P);
+    ProblemPtr P = Problem::create("PO", 3);
+    auto solver_ptr = std::make_shared<SolverManagerDummy>(P);
+
+    // Create State block
+    auto sb_ptr = createStateBlock();
+
+    // Create Factor
+    auto fac_ptr = createFactor(sb_ptr);
+
+    // notify stateblock
+    P->notifyStateBlock(sb_ptr,ADD);
+
+    // notify factor
+    P->notifyFactor(fac_ptr,ADD);
+
+    // check notifications
+    Notification notif;
+    EXPECT_TRUE(P->getStateBlockNotification(sb_ptr, notif));
+    EXPECT_EQ(ADD, notif);
+    EXPECT_TRUE(P->getFactorNotification(fac_ptr, notif));
+    EXPECT_EQ(ADD, notif);
+
+    // check flags
+    EXPECT_FALSE(sb_ptr->stateUpdated());
+    EXPECT_FALSE(sb_ptr->fixUpdated());
+    EXPECT_FALSE(sb_ptr->localParamUpdated());
+
+    // Fix state block
+    sb_ptr->fix();
+
+    // check flags
+    EXPECT_FALSE(sb_ptr->stateUpdated());
+    EXPECT_TRUE(sb_ptr->fixUpdated());
+    EXPECT_FALSE(sb_ptr->localParamUpdated());
+
+    // update solver manager
+    solver_ptr->update();
+
+    // check notifications
+    EXPECT_EQ(P->getStateBlockNotificationMapSize(),0);
+    EXPECT_EQ(P->getFactorNotificationMapSize(), 0);
+
+    // check flags
+    EXPECT_FALSE(sb_ptr->stateUpdated());
+    EXPECT_FALSE(sb_ptr->fixUpdated());
+    EXPECT_FALSE(sb_ptr->localParamUpdated());
+
+    // check stateblock fixed
+    EXPECT_TRUE(solver_ptr->isStateBlockRegistered(sb_ptr));
+    EXPECT_TRUE(solver_ptr->isStateBlockFixed(sb_ptr));
+    EXPECT_TRUE(solver_ptr->check());
+}
+
+TEST(SolverManager, StateBlockAndFactor_UpdateLocalParam)
+{
+    ProblemPtr P = Problem::create("PO", 3);
+    auto solver_ptr = std::make_shared<SolverManagerDummy>(P);
+
+    // Create State block
+    auto sb_ptr = createStateBlock();
+
+    // Create Factor
+    auto fac_ptr = createFactor(sb_ptr);
+
+    // notify stateblock
+    P->notifyStateBlock(sb_ptr,ADD);
+
+    // notify factor
+    P->notifyFactor(fac_ptr,ADD);
+
+    // check notifications
+    Notification notif;
+    EXPECT_TRUE(P->getStateBlockNotification(sb_ptr, notif));
+    EXPECT_EQ(ADD, notif);
+    EXPECT_TRUE(P->getFactorNotification(fac_ptr, notif));
+    EXPECT_EQ(ADD, notif);
+
+    // check flags
+    EXPECT_FALSE(sb_ptr->stateUpdated());
+    EXPECT_FALSE(sb_ptr->fixUpdated());
+    EXPECT_FALSE(sb_ptr->localParamUpdated());
+
+    // Local param
+    LocalParametrizationBasePtr local_ptr = std::make_shared<LocalParametrizationQuaternionLocal>();
+    sb_ptr->setLocalParametrization(local_ptr);
+
+    // Fix state block
+    sb_ptr->fix();
+
+    // check flags
+    EXPECT_FALSE(sb_ptr->stateUpdated());
+    EXPECT_TRUE(sb_ptr->fixUpdated());
+    EXPECT_TRUE(sb_ptr->localParamUpdated());
+
+    // update solver manager
+    solver_ptr->update();
+
+    // check notifications
+    EXPECT_EQ(P->getStateBlockNotificationMapSize(),0);
+    EXPECT_EQ(P->getFactorNotificationMapSize(), 0);
+
+    // check flags
+    EXPECT_FALSE(sb_ptr->stateUpdated());
+    EXPECT_FALSE(sb_ptr->fixUpdated());
+    EXPECT_FALSE(sb_ptr->localParamUpdated());
+
+    // check stateblock fixed
+    EXPECT_TRUE(solver_ptr->isStateBlockRegistered(sb_ptr));
+    EXPECT_TRUE(solver_ptr->isStateBlockFixed(sb_ptr));
+    EXPECT_TRUE(solver_ptr->hasThisLocalParametrization(sb_ptr,local_ptr));
+    EXPECT_TRUE(solver_ptr->check());
+}
+
+TEST(SolverManager, StateBlockAndFactor_AddLocalParamRemoveLocalParam)
+{
+    ProblemPtr P = Problem::create("PO", 3);
+    auto solver_ptr = std::make_shared<SolverManagerDummy>(P);
+
+    // Create State block
+    auto sb_ptr = createStateBlock();
+
+    // Create Factor
+    auto fac_ptr = createFactor(sb_ptr);
+
+    // Local param
+    LocalParametrizationBasePtr local_ptr = std::make_shared<LocalParametrizationQuaternionLocal>();
+    sb_ptr->setLocalParametrization(local_ptr);
+
+    // check flags
+    EXPECT_FALSE(sb_ptr->stateUpdated());
+    EXPECT_FALSE(sb_ptr->fixUpdated());
+    EXPECT_TRUE(sb_ptr->localParamUpdated());
+
+    // notify stateblock
+    P->notifyStateBlock(sb_ptr,ADD);
+
+    // notify factor
+    P->notifyFactor(fac_ptr,ADD);
+
+    // check notifications
+    Notification notif;
+    EXPECT_TRUE(P->getStateBlockNotification(sb_ptr, notif));
+    EXPECT_EQ(ADD, notif);
+    EXPECT_TRUE(P->getFactorNotification(fac_ptr, notif));
+    EXPECT_EQ(ADD, notif);
+
+    // update solver manager
+    solver_ptr->update();
+
+    // check notifications
+    EXPECT_EQ(P->getStateBlockNotificationMapSize(),0);
+    EXPECT_EQ(P->getFactorNotificationMapSize(), 0);
+
+    // check solver
+    EXPECT_TRUE(solver_ptr->isStateBlockRegistered(sb_ptr));
+    EXPECT_TRUE(solver_ptr->hasLocalParametrization(sb_ptr));
+    EXPECT_TRUE(solver_ptr->hasThisLocalParametrization(sb_ptr,local_ptr));
+    EXPECT_TRUE(solver_ptr->check());
+
+    // check flags
+    EXPECT_FALSE(sb_ptr->stateUpdated());
+    EXPECT_FALSE(sb_ptr->fixUpdated());
+    EXPECT_FALSE(sb_ptr->localParamUpdated());
+
+    // Remove local param
+    sb_ptr->removeLocalParametrization();
+
+    // check flags
+    EXPECT_FALSE(sb_ptr->stateUpdated());
+    EXPECT_FALSE(sb_ptr->fixUpdated());
+    EXPECT_TRUE(sb_ptr->localParamUpdated());
+
+    // update solver manager
+    solver_ptr->update();
+
+    // check solver
+    EXPECT_TRUE(solver_ptr->isStateBlockRegistered(sb_ptr));
+    EXPECT_FALSE(solver_ptr->hasLocalParametrization(sb_ptr));
+    EXPECT_TRUE(solver_ptr->check());
+}
+
+TEST(SolverManager, StateBlockAndFactor_RemoveStateBlock)
+{
+    ProblemPtr P = Problem::create("PO", 3);
+    auto solver_ptr = std::make_shared<SolverManagerDummy>(P);
 
     // Create State block
-    Vector2d state; state << 1, 2;
-    StateBlockPtr sb_ptr = std::make_shared<StateBlock>(state);
+    auto sb_ptr = createStateBlock();
+
+    // Create Factor
+    auto fac_ptr = createFactor(sb_ptr);
 
-    // Create (and add) factor point 2d
-    FrameBasePtr        F = P->emplaceKeyFrame(0, P->stateZero() );
+    // notify stateblock
+    P->notifyStateBlock(sb_ptr,ADD);
 
-    auto C = CaptureBase::emplace<CaptureVoid>(F, 0, nullptr);
-    auto f = FeatureBase::emplace<FeatureBase>(C, "FeatureOdom2d", Vector3d::Zero(), Matrix3d::Identity());
-    auto c = FactorBase::emplace<FactorPose2d>(f, f, nullptr, false);
+    // notify factor
+    P->notifyFactor(fac_ptr,ADD);
 
-    // notification
+    // check notifications
     Notification notif;
-    ASSERT_TRUE(P->getFactorNotification(c,notif));
-    ASSERT_EQ(notif, ADD);
+    EXPECT_TRUE(P->getStateBlockNotification(sb_ptr, notif));
+    EXPECT_EQ(ADD, notif);
+    EXPECT_TRUE(P->getFactorNotification(fac_ptr, notif));
+    EXPECT_EQ(ADD, notif);
 
-    // add factor
-    P->notifyFactor(c,REMOVE);
+    // update solver
+    solver_ptr->update();
+
+    // check notifications
+    EXPECT_EQ(P->getStateBlockNotificationMapSize(),0);
+    EXPECT_EQ(P->getFactorNotificationMapSize(), 0);
+
+    // remove state_block
+    P->notifyStateBlock(sb_ptr,REMOVE);
 
-    // notification
-    ASSERT_EQ(P->getFactorNotificationMapSize(), 0); // ADD+REMOVE cancels out
-    ASSERT_FALSE(P->getFactorNotification(c, notif)); // ADD+REMOVE cancels out
+    // check notifications
+    EXPECT_TRUE(P->getStateBlockNotification(sb_ptr, notif));
+    EXPECT_EQ(REMOVE, notif);
+    EXPECT_EQ(P->getFactorNotificationMapSize(), 0);
 
     // update solver
-    solver_manager_ptr->update();
+    solver_ptr->update(); // there is a factor involved, removal posponed (REMOVE in notification list)
+
+    // check notifications
+    EXPECT_TRUE(P->getStateBlockNotification(sb_ptr, notif));
+    EXPECT_EQ(REMOVE, notif);
+    EXPECT_EQ(P->getFactorNotificationMapSize(), 0);
 
-    // check factor
-    ASSERT_FALSE(solver_manager_ptr->isFactorRegistered(c));
+    // checks
+    EXPECT_TRUE(solver_ptr->isStateBlockRegistered(sb_ptr));
+    EXPECT_TRUE(solver_ptr->isFactorRegistered(fac_ptr));
+    EXPECT_TRUE(solver_ptr->check());
 }
 
-TEST(SolverManager, DoubleRemoveFactor)
+TEST(SolverManager, StateBlockAndFactor_RemoveFactor)
 {
-    ProblemPtr P = Problem::create("PO", 2);
-    SolverManagerDummyPtr solver_manager_ptr = std::make_shared<SolverManagerDummy>(P);
+    ProblemPtr P = Problem::create("PO", 3);
+    auto solver_ptr = std::make_shared<SolverManagerDummy>(P);
+
+    // Create State block
+    auto sb_ptr = createStateBlock();
+
+    // Create Factor
+    auto fac_ptr = createFactor(sb_ptr);
+
+    // notify stateblock
+    P->notifyStateBlock(sb_ptr,ADD);
+
+    // notify factor
+    P->notifyFactor(fac_ptr,ADD);
+
+    // check notifications
+    Notification notif;
+    EXPECT_TRUE(P->getStateBlockNotification(sb_ptr, notif));
+    EXPECT_EQ(ADD, notif);
+    EXPECT_TRUE(P->getFactorNotification(fac_ptr, notif));
+    EXPECT_EQ(ADD, notif);
+
+    // update solver
+    solver_ptr->update();
+
+    // check notifications
+    EXPECT_EQ(P->getStateBlockNotificationMapSize(),0);
+    EXPECT_EQ(P->getFactorNotificationMapSize(), 0);
+
+    // remove state_block
+    P->notifyFactor(fac_ptr,REMOVE); // state block should be automatically stored as floating
+
+    // check notifications
+    EXPECT_TRUE(P->getFactorNotification(fac_ptr, notif));
+    EXPECT_EQ(REMOVE, notif);
+    EXPECT_EQ(P->getStateBlockNotificationMapSize(), 0);
+
+    // update solver
+    solver_ptr->update();
+
+    // check notifications
+    EXPECT_EQ(P->getStateBlockNotificationMapSize(),0);
+    EXPECT_EQ(P->getFactorNotificationMapSize(), 0);
+
+    // checks
+    EXPECT_TRUE(solver_ptr->isStateBlockRegistered(sb_ptr));
+    EXPECT_TRUE(solver_ptr->isStateBlockFloating(sb_ptr));
+    EXPECT_FALSE(solver_ptr->isFactorRegistered(fac_ptr));
+    EXPECT_TRUE(solver_ptr->check());
+}
+
+TEST(SolverManager, StateBlockAndFactor_AddRemoveStateBlock)
+{
+    ProblemPtr P = Problem::create("PO", 3);
+    auto solver_ptr = std::make_shared<SolverManagerDummy>(P);
+
+    // Create State block
+    auto sb_ptr = createStateBlock();
+
+    // Create Factor
+    auto fac_ptr = createFactor(sb_ptr);
+
+    // notify stateblock
+    P->notifyStateBlock(sb_ptr,ADD);
+
+    // notify factor
+    P->notifyFactor(fac_ptr,ADD);
+
+    // check notifications
+    Notification notif;
+    EXPECT_TRUE(P->getStateBlockNotification(sb_ptr, notif));
+    EXPECT_EQ(ADD, notif);
+    EXPECT_TRUE(P->getFactorNotification(fac_ptr, notif));
+    EXPECT_EQ(ADD, notif);
+
+    // remove state_block
+    P->notifyStateBlock(sb_ptr,REMOVE); // cancells out ADD notification
+
+    // check notifications
+    EXPECT_EQ(P->getStateBlockNotificationMapSize(),0);
+    EXPECT_TRUE(P->getFactorNotification(fac_ptr, notif));
+    EXPECT_EQ(ADD, notif);
+
+    // update solver
+    solver_ptr->update(); // factor ADD notification is not executed since state block involved is missing (ADD notification added)
+
+    // check notifications
+    EXPECT_EQ(P->getStateBlockNotificationMapSize(),0);
+    EXPECT_TRUE(P->getFactorNotification(fac_ptr, notif));
+    EXPECT_EQ(ADD, notif);
+
+    // check state block
+    EXPECT_FALSE(solver_ptr->isStateBlockRegistered(sb_ptr));
+    EXPECT_FALSE(solver_ptr->isFactorRegistered(fac_ptr));
+    EXPECT_TRUE(solver_ptr->check());
+}
+
+TEST(SolverManager, StateBlockAndFactor_AddRemoveFactor)
+{
+    ProblemPtr P = Problem::create("PO", 3);
+    auto solver_ptr = std::make_shared<SolverManagerDummy>(P);
+
+    // Create State block
+    auto sb_ptr = createStateBlock();
+
+    // Create Factor
+    auto fac_ptr = createFactor(sb_ptr);
+
+    // notify stateblock
+    P->notifyStateBlock(sb_ptr,ADD);
+
+    // notify factor
+    P->notifyFactor(fac_ptr,ADD);
+
+    // check notifications
+    Notification notif;
+    EXPECT_TRUE(P->getStateBlockNotification(sb_ptr, notif));
+    EXPECT_EQ(ADD, notif);
+    EXPECT_TRUE(P->getFactorNotification(fac_ptr, notif));
+    EXPECT_EQ(ADD, notif);
+
+    // remove state_block
+    P->notifyFactor(fac_ptr,REMOVE); // cancells out ADD notification
+
+    // check notifications
+    EXPECT_EQ(P->getFactorNotificationMapSize(),0);
+    EXPECT_TRUE(P->getStateBlockNotification(sb_ptr, notif));
+    EXPECT_EQ(ADD, notif);
+
+    // update solver
+    solver_ptr->update(); // state block should be automatically stored as floating
+
+    // check notifications
+    EXPECT_EQ(P->getStateBlockNotificationMapSize(),0);
+    EXPECT_EQ(P->getFactorNotificationMapSize(), 0);
+
+    // checks
+    EXPECT_TRUE(solver_ptr->isStateBlockRegistered(sb_ptr));
+    EXPECT_TRUE(solver_ptr->isStateBlockFloating(sb_ptr));
+    EXPECT_FALSE(solver_ptr->isFactorRegistered(fac_ptr));
+    EXPECT_TRUE(solver_ptr->check());
+}
+
+TEST(SolverManager, StateBlockAndFactor_DoubleRemoveStateBlock)
+{
+    ProblemPtr P = Problem::create("PO", 3);
+    auto solver_ptr = std::make_shared<SolverManagerDummy>(P);
+
+    // Create State block
+    auto sb_ptr = createStateBlock();
+
+    // Create Factor
+    auto fac_ptr = createFactor(sb_ptr);
+
+    // notify stateblock
+    P->notifyStateBlock(sb_ptr,ADD);
+
+    // notify factor
+    P->notifyFactor(fac_ptr,ADD);
+
+    // check notifications
+    Notification notif;
+    EXPECT_TRUE(P->getStateBlockNotification(sb_ptr, notif));
+    EXPECT_EQ(ADD, notif);
+    EXPECT_TRUE(P->getFactorNotification(fac_ptr, notif));
+    EXPECT_EQ(ADD, notif);
+
+    // remove state_block
+    P->notifyStateBlock(sb_ptr,REMOVE); // cancells out the ADD
+
+    // check notifications
+    EXPECT_EQ(P->getStateBlockNotificationMapSize(),0);
+    EXPECT_TRUE(P->getFactorNotification(fac_ptr, notif));
+    EXPECT_EQ(ADD, notif);
+
+    // update solver
+    solver_ptr->update(); // factor ADD is posponed
+
+    // check notifications
+    EXPECT_EQ(P->getStateBlockNotificationMapSize(),0);
+    EXPECT_TRUE(P->getFactorNotification(fac_ptr, notif));
+    EXPECT_EQ(ADD, notif);
+
+    // remove state_block
+    P->notifyStateBlock(sb_ptr,REMOVE);
+
+    // check notifications
+    EXPECT_TRUE(P->getStateBlockNotification(sb_ptr, notif));
+    EXPECT_EQ(REMOVE, notif);
+    EXPECT_TRUE(P->getFactorNotification(fac_ptr, notif));
+    EXPECT_EQ(ADD, notif);
+
+    // update solver manager
+    solver_ptr->update(); // repeated REMOVE should be ignored
+
+    // check notifications
+    EXPECT_EQ(P->getStateBlockNotificationMapSize(),0);
+    EXPECT_TRUE(P->getFactorNotification(fac_ptr, notif));
+    EXPECT_EQ(ADD, notif);
+
+    // check state block
+    EXPECT_FALSE(solver_ptr->isStateBlockRegistered(sb_ptr));
+    EXPECT_FALSE(solver_ptr->isFactorRegistered(fac_ptr));
+    EXPECT_TRUE(solver_ptr->check());
+}
+
+TEST(SolverManager, StateBlockAndFactor_DoubleRemoveFactor)
+{
+    ProblemPtr P = Problem::create("PO", 3);
+    auto solver_ptr = std::make_shared<SolverManagerDummy>(P);
+
+    // Create State block
+    auto sb_ptr = createStateBlock();
+
+    // Create Factor
+    auto fac_ptr = createFactor(sb_ptr);
+
+    // notify stateblock
+    P->notifyStateBlock(sb_ptr,ADD);
+
+    // notify factor
+    P->notifyFactor(fac_ptr,ADD);
+
+    // check notifications
+    Notification notif;
+    EXPECT_TRUE(P->getStateBlockNotification(sb_ptr, notif));
+    EXPECT_EQ(ADD, notif);
+    EXPECT_TRUE(P->getFactorNotification(fac_ptr, notif));
+    EXPECT_EQ(ADD, notif);
+
+    // remove state_block
+    P->notifyFactor(fac_ptr,REMOVE); // cancells out ADD
+
+    // check notifications
+    EXPECT_EQ(P->getFactorNotificationMapSize(),0);
+    EXPECT_TRUE(P->getStateBlockNotification(sb_ptr, notif));
+    EXPECT_EQ(ADD, notif);
+
+    // update solver
+    solver_ptr->update(); // state block should be automatically stored as floating
+
+    // check notifications
+    EXPECT_EQ(P->getStateBlockNotificationMapSize(),0);
+    EXPECT_EQ(P->getFactorNotificationMapSize(),0);
+
+    // remove state_block
+    P->notifyFactor(fac_ptr,REMOVE);
+
+    // check notifications
+    EXPECT_EQ(P->getStateBlockNotificationMapSize(),0);
+    EXPECT_TRUE(P->getFactorNotification(fac_ptr, notif));
+    EXPECT_EQ(REMOVE, notif);
+
+    // update solver
+    solver_ptr->update(); // repeated REMOVE should be ignored
+
+    // checks
+    EXPECT_TRUE(solver_ptr->isStateBlockRegistered(sb_ptr));
+    EXPECT_TRUE(solver_ptr->isStateBlockFloating(sb_ptr));
+    EXPECT_FALSE(solver_ptr->isFactorRegistered(fac_ptr));
+    EXPECT_TRUE(solver_ptr->check());
+}
+
+TEST(SolverManager, StateBlockAndFactor_AddUpdatedStateBlock)
+{
+    ProblemPtr P = Problem::create("PO", 3);
+    auto solver_ptr = std::make_shared<SolverManagerDummy>(P);
 
     // Create State block
-    Vector2d state; state << 1, 2;
-    StateBlockPtr sb_ptr = std::make_shared<StateBlock>(state);
+    auto sb_ptr = createStateBlock();
 
-    // Create (and add) factor point 2d
-    FrameBasePtr        F = P->emplaceKeyFrame(TimeStamp(0), P->stateZero() );
+    // Create Factor
+    auto fac_ptr = createFactor(sb_ptr);
 
-    auto C = CaptureBase::emplace<CaptureVoid>(F, 0, nullptr);
-    auto f = FeatureBase::emplace<FeatureBase>(C, "FeatureOdom2d", Vector3d::Zero(), Matrix3d::Identity());
-    auto c = FactorBase::emplace<FactorPose2d>(f, f, nullptr, false);
+    // Fix
+    sb_ptr->fix();
+
+    // Change State
+    sb_ptr->setState(2*sb_ptr->getState());
+
+    // Check flags have been set true
+    EXPECT_TRUE(sb_ptr->fixUpdated());
+    EXPECT_TRUE(sb_ptr->stateUpdated());
+
+    // == When an ADD is notified: a ADD notification should be stored ==
+
+    // notify state block
+    P->notifyStateBlock(sb_ptr,ADD);
+
+    // notify factor
+    P->notifyFactor(fac_ptr,ADD);
+
+    // check notifications
+    Notification notif;
+    EXPECT_TRUE(P->getStateBlockNotification(sb_ptr, notif));
+    EXPECT_EQ(ADD, notif);
+    EXPECT_TRUE(P->getFactorNotification(fac_ptr, notif));
+    EXPECT_EQ(ADD, notif);
+
+    // == Insert OTHER notifications ==
+
+    // Set State --> FLAG
+    sb_ptr->setState(2*sb_ptr->getState());
+
+    // Fix --> FLAG
+    sb_ptr->unfix();
+    // Check flag has been set true
+    EXPECT_TRUE(sb_ptr->fixUpdated());
+
+    EXPECT_EQ(P->getStateBlockNotificationMapSize(),1); // No new notifications (fix and set state are flags in sb)
+
+    // == consume empties the notification map ==
+    solver_ptr->update(); // it calls P->consumeStateBlockNotificationMap();
+    EXPECT_EQ(P->getStateBlockNotificationMapSize(),0);
+    // Check flags have been reset
+    EXPECT_FALSE(sb_ptr->fixUpdated());
+    EXPECT_FALSE(sb_ptr->stateUpdated());
+
+    // == When an REMOVE is notified: a REMOVE notification should be stored ==
+
+    // remove state_block
+    P->notifyStateBlock(sb_ptr,REMOVE);
+
+    EXPECT_EQ(P->getStateBlockNotificationMapSize(),1);
+    EXPECT_TRUE(P->getStateBlockNotification(sb_ptr, notif));
+    EXPECT_EQ(notif, REMOVE);
+
+    // == REMOVE + ADD: notification map should be empty ==
+    P->notifyStateBlock(sb_ptr,ADD);
+    EXPECT_EQ(P->getStateBlockNotificationMapSize(),0);
+
+    // == UPDATES should clear the list of notifications ==
+    // notify state block
+    P->notifyStateBlock(sb_ptr,ADD);
+
+    // update solver
+    solver_ptr->update();
+
+    EXPECT_EQ(P->getStateBlockNotificationMapSize(),0); // After solver_manager->update, notifications should be empty
+
+    // == ADD + REMOVE: notification map should be empty ==
+    P->notifyStateBlock(sb_ptr,ADD);
+    P->notifyStateBlock(sb_ptr,REMOVE);
+    EXPECT_EQ(P->getStateBlockNotificationMapSize(),0);
+}
+
+////////////////////////////////////////////////////////
+// ONLY FACTOR
+TEST(SolverManager, OnlyFactor_Add)
+{
+    ProblemPtr P = Problem::create("PO", 3);
+    auto solver_ptr = std::make_shared<SolverManagerDummy>(P);
+
+    // Create State block
+    auto sb_ptr = createStateBlock();
+
+    // Create Factor
+    auto fac_ptr = createFactor(sb_ptr);
+
+    // notify factor (state block has not been notified)
+    P->notifyFactor(fac_ptr,ADD);
+
+    // check notifications
+    Notification notif;
+    EXPECT_EQ(P->getStateBlockNotificationMapSize(),0);
+    EXPECT_TRUE(P->getFactorNotification(fac_ptr, notif));
+    EXPECT_EQ(ADD, notif);
+
+    // update solver
+    solver_ptr->update(); // factor ADD should be posponed (in the notification list again)
+
+    // check notifications
+    EXPECT_EQ(P->getStateBlockNotificationMapSize(),0);
+    EXPECT_TRUE(P->getFactorNotification(fac_ptr, notif));
+    EXPECT_EQ(ADD, notif);
+
+    // checks
+    EXPECT_FALSE(solver_ptr->isStateBlockRegistered(sb_ptr));
+    EXPECT_FALSE(solver_ptr->isFactorRegistered(fac_ptr));
+    EXPECT_TRUE(solver_ptr->check());
+}
+
+TEST(SolverManager, OnlyFactor_Remove)
+{
+    ProblemPtr P = Problem::create("PO", 3);
+    auto solver_ptr = std::make_shared<SolverManagerDummy>(P);
+
+    // Create State block
+    auto sb_ptr = createStateBlock();
+
+    // Create Factor
+    auto fac_ptr = createFactor(sb_ptr);
+
+    // notify factor (state block has not been notified)
+    P->notifyFactor(fac_ptr,ADD);
+
+    // check notifications
+    Notification notif;
+    EXPECT_EQ(P->getStateBlockNotificationMapSize(),0);
+    EXPECT_TRUE(P->getFactorNotification(fac_ptr, notif));
+    EXPECT_EQ(ADD, notif);
 
     // update solver
-    solver_manager_ptr->update();
+    solver_ptr->update(); // ADD factor should be posponed (in the notification list again)
+
+    // check notifications
+    EXPECT_EQ(P->getStateBlockNotificationMapSize(),0);
+    EXPECT_TRUE(P->getFactorNotification(fac_ptr, notif));
+    EXPECT_EQ(ADD, notif);
 
-    // remove factor
-    P->notifyFactor(c,REMOVE);
+    // notify factor
+    P->notifyFactor(fac_ptr,REMOVE);
+
+    // check notifications
+    EXPECT_EQ(P->getStateBlockNotificationMapSize(),0);
+    EXPECT_EQ(P->getFactorNotificationMapSize(),0);
 
     // update solver
-    solver_manager_ptr->update();
+    solver_ptr->update(); // nothing to update
+
+    // check notifications
+    EXPECT_EQ(P->getStateBlockNotificationMapSize(),0);
+    EXPECT_EQ(P->getFactorNotificationMapSize(),0);
 
-    // remove factor
-    P->notifyFactor(c,REMOVE);
+    // checks
+    EXPECT_FALSE(solver_ptr->isStateBlockRegistered(sb_ptr));
+    EXPECT_FALSE(solver_ptr->isFactorRegistered(fac_ptr));
+    EXPECT_TRUE(solver_ptr->check());
+}
+
+TEST(SolverManager, OnlyFactor_AddRemove)
+{
+    ProblemPtr P = Problem::create("PO", 3);
+    auto solver_ptr = std::make_shared<SolverManagerDummy>(P);
+
+    // Create State block
+    auto sb_ptr = createStateBlock();
+
+    // Create Factor
+    auto fac_ptr = createFactor(sb_ptr);
+
+    // notify factor (state block has not been notified)
+    P->notifyFactor(fac_ptr,ADD);
+
+    // check notifications
+    Notification notif;
+    EXPECT_EQ(P->getStateBlockNotificationMapSize(),0);
+    EXPECT_TRUE(P->getFactorNotification(fac_ptr, notif));
+    EXPECT_EQ(ADD, notif);
+
+    // notify factor
+    P->notifyFactor(fac_ptr,REMOVE);
+
+    // check notifications
+    EXPECT_EQ(P->getStateBlockNotificationMapSize(),0);
+    EXPECT_EQ(P->getFactorNotificationMapSize(),0);
 
     // update solver
-    solver_manager_ptr->update();
+    solver_ptr->update(); // nothing to update
+
+    // check notifications
+    EXPECT_EQ(P->getStateBlockNotificationMapSize(),0);
+    EXPECT_EQ(P->getFactorNotificationMapSize(),0);
 
-    // check factor
-    ASSERT_FALSE(solver_manager_ptr->isFactorRegistered(c));
+    // checks
+    EXPECT_FALSE(solver_ptr->isStateBlockRegistered(sb_ptr));
+    EXPECT_FALSE(solver_ptr->isFactorRegistered(fac_ptr));
+    EXPECT_TRUE(solver_ptr->check());
 }
 
+////////////////////////////////////////////////////////
+// MULTITHREADING
+
 TEST(SolverManager, MultiThreadingTruncatedNotifications)
 {
     double Dt = 5.0;
     ProblemPtr P = Problem::create("PO", 2);
-    SolverManagerDummyPtr solver_manager_ptr = std::make_shared<SolverManagerDummy>(P);
+    auto solver_ptr = std::make_shared<SolverManagerDummy>(P);
 
     // loop updating (without sleep)
     std::thread t([&](){
         auto start_t = std::chrono::high_resolution_clock::now();
         while (true)
         {
-            solver_manager_ptr->update();
+            solver_ptr->update();
+            ASSERT_TRUE(solver_ptr->check());
             if (std::chrono::duration_cast<std::chrono::duration<double>>(std::chrono::high_resolution_clock::now() - start_t).count() > Dt)
                 break;
         }});