diff --git a/include/core/factor/factor_block_absolute.h b/include/core/factor/factor_block_absolute.h
index 70712879e117b2c54285499756eee5f1c9f322b8..b6fbaced76b9a47f34ee4fe27c29cc18a93b74e3 100644
--- a/include/core/factor/factor_block_absolute.h
+++ b/include/core/factor/factor_block_absolute.h
@@ -43,43 +43,15 @@ class FactorBlockAbsolute : public FactorAnalytic
 
     public:
 
-        /** \brief Constructor
-         *
-         * \param _sb_ptr the constrained state block
-         *
-         */
-        FactorBlockAbsolute(FeatureBasePtr _feature_ptr,
-                            StateBlockPtr _sb_ptr,
-                            ProcessorBasePtr _processor_ptr,
-                            bool _apply_loss_function,
-                            FactorStatus _status = FAC_ACTIVE) :
-            FactorAnalytic("FactorBlockAbsolute",
-                           TOP_ABS,
-                           _feature_ptr,
-                           nullptr,
-                           nullptr,
-                           nullptr,
-                           nullptr,
-                           _processor_ptr,
-                           _apply_loss_function,
-                           _status,
-                           _sb_ptr),
-            sb_size_(_sb_ptr->getSize()),
-            sb_constrained_start_(0),
-            sb_constrained_size_(sb_size_),
-            is_angle_(std::dynamic_pointer_cast<StateAngle>(_sb_ptr))
-        {
-            assert(sb_constrained_size_+sb_constrained_start_ <= sb_size_);
-
-            // precompute Jacobian (Identity)
-            J_ = Eigen::MatrixXd::Identity(sb_constrained_size_, sb_size_);
-        }
-
         /** \brief Constructor for segment of state block
          *
+         * \param _feature_ptr the feature where the factor is emplaced
          * \param _sb_ptr the constrained state block
          * \param _start_idx the index of the first state element that is constrained
-         * \param _start_idx the size of the state segment that is constrained, -1 = all the
+         * \param _size the size of the state segment that is constrained, -1 = all the
+         * \param _processor_ptr processor that created the factor
+         * \param _apply_loss_function if the factor should have loss function
+         * \param _status factor status
          *
          */
         FactorBlockAbsolute(FeatureBasePtr _feature_ptr,
@@ -105,7 +77,9 @@ class FactorBlockAbsolute : public FactorAnalytic
             sb_constrained_size_(_size == -1 ? sb_size_ : _size),
             is_angle_(std::dynamic_pointer_cast<StateAngle>(_sb_ptr))
         {
+            assert(_sb_ptr->getLocalSize() == _sb_ptr->getSize());
             assert(sb_constrained_size_+sb_constrained_start_ <= sb_size_);
+            assert(sb_constrained_size_ > 0);
 
             // precompute Jacobian (Identity)
             if (sb_constrained_start_ == 0)
@@ -117,6 +91,30 @@ class FactorBlockAbsolute : public FactorAnalytic
             }
         }
 
+        /** \brief Constructor for the whole state block
+         *
+         * \param _feature_ptr the feature where the factor is emplaced
+         * \param _sb_ptr the constrained state block
+         * \param _processor_ptr processor that created the factor
+         * \param _apply_loss_function if the factor should have loss function
+         * \param _status factor status
+         *
+         */
+        FactorBlockAbsolute(FeatureBasePtr _feature_ptr,
+                            StateBlockPtr _sb_ptr,
+                            ProcessorBasePtr _processor_ptr,
+                            bool _apply_loss_function,
+                            FactorStatus _status = FAC_ACTIVE) :
+            FactorBlockAbsolute(_feature_ptr,
+                                _sb_ptr,
+                                0, 
+                                -1,
+                                _processor_ptr,
+                                _apply_loss_function,
+                                _status)
+        {
+        }
+
         ~FactorBlockAbsolute() override = default;
 
         /** \brief Returns the residual evaluated in the states provided
@@ -137,11 +135,11 @@ class FactorBlockAbsolute : public FactorAnalytic
          *
          **/
         void evaluateJacobians(const std::vector<Eigen::Map<const Eigen::VectorXd>>& _st_vector,
-                                       std::vector<Eigen::Map<Eigen::MatrixRowXd> >& jacobians,
-                                       const std::vector<bool>& _compute_jacobian) const override;
+                               std::vector<Eigen::Map<Eigen::MatrixRowXd> >& jacobians,
+                               const std::vector<bool>& _compute_jacobian) const override;
         void evaluateJacobians(const std::vector<Eigen::Map<const Eigen::VectorXd>>& _st_vector,
-                                       std::vector<Eigen::MatrixXd>& jacobians,
-                                       const std::vector<bool>& _compute_jacobian) const override;
+                               std::vector<Eigen::MatrixXd>& jacobians,
+                               const std::vector<bool>& _compute_jacobian) const override;
 
         /** \brief Returns the pure jacobians (without measurement noise) evaluated in the state blocks values
          *
@@ -164,11 +162,17 @@ inline Eigen::VectorXd FactorBlockAbsolute::evaluateResiduals(const std::vector<
 
     // residual
     if (is_angle_)
+    {
         return getMeasurementSquareRootInformationUpper() * Eigen::Vector1d(pi2pi(_st_vector.front()(0) - getMeasurement()(0)));
+    }
     else if (sb_constrained_size_ == _st_vector.front().size())
-        return getMeasurementSquareRootInformationUpper() * _st_vector.front() - getMeasurement();
+    {
+        return getMeasurementSquareRootInformationUpper() * (_st_vector.front() - getMeasurement());
+    }
     else
+    {
         return getMeasurementSquareRootInformationUpper() * (_st_vector.front().segment(sb_constrained_start_,sb_constrained_size_) - getMeasurement());
+    }
 }
 
 inline void FactorBlockAbsolute::evaluateJacobians(const std::vector<Eigen::Map<const Eigen::VectorXd> >& _st_vector,
diff --git a/include/core/factor/factor_quaternion_absolute.h b/include/core/factor/factor_quaternion_absolute.h
index f760bd2de64e279c605b524e2c755585ead4edfd..6bae82064b5144fcf21e7c4c36d9f4757667aace 100644
--- a/include/core/factor/factor_quaternion_absolute.h
+++ b/include/core/factor/factor_quaternion_absolute.h
@@ -23,7 +23,7 @@
 
 //Wolf includes
 #include "core/factor/factor_autodiff.h"
-#include "core/state_block/local_parametrization_quaternion.h"
+#include "core/state_block/state_quaternion.h"
 #include "core/frame/frame_base.h"
 #include "core/math/rotations.h"
 
@@ -53,7 +53,7 @@ class FactorQuaternionAbsolute: public FactorAutodiff<FactorQuaternionAbsolute,3
                                                          _status,
                                                          _sb_ptr)
         {
-            //
+            assert(std::dynamic_pointer_cast<StateQuaternion>(_sb_ptr));
         }
 
         ~FactorQuaternionAbsolute() override = default;
diff --git a/schema/problem/Problem.schema b/schema/problem/Problem.schema
index effd887627b2f151d5a7bdd3ba77544584ac3ada..406421cb40f1d44ffa01462ec764b36014637fce 100644
--- a/schema/problem/Problem.schema
+++ b/schema/problem/Problem.schema
@@ -8,7 +8,7 @@ problem:
     _type: int
     _mandatory: true
     _options: [2, 3]
-    _doc: Dimension of the problem. '2' for 2D or '3' for 3D
+    _doc: "Dimension of the problem. '2' for 2D or '3' for 3D"
 map:
   _type: derived
   _base: MapBase.schema
diff --git a/schema/problem/Problem2d.schema b/schema/problem/Problem2d.schema
index ee574b2556c28567e118e26c987a95cf1874c5f7..5aa2e1d229a32a714e14ff4660ef5183117e9976 100644
--- a/schema/problem/Problem2d.schema
+++ b/schema/problem/Problem2d.schema
@@ -10,4 +10,4 @@ problem:
     _mandatory: false
     _default: 2
     _options: [2]
-    _doc: Dimension of the problem: '2' for 2D
\ No newline at end of file
+    _doc: "Dimension of the problem: '2' for 2D"
\ No newline at end of file
diff --git a/schema/problem/Problem3d.schema b/schema/problem/Problem3d.schema
index f89471756640123a7fe325a3776ce096a5e8735d..7eb62a0597e4badc1e00b7b4bb278b6f07f23e6c 100644
--- a/schema/problem/Problem3d.schema
+++ b/schema/problem/Problem3d.schema
@@ -10,4 +10,4 @@ problem:
     _mandatory: false
     _default: 3
     _options: [3]
-    _doc: Dimension of the problem: '3' for 3D
\ No newline at end of file
+    _doc: "Dimension of the problem: '3' for 3D"
\ No newline at end of file
diff --git a/schema/solver/SolverCeres.schema b/schema/solver/SolverCeres.schema
index 6310da70265e5dc2fe8beb4e43b0299ff06ddb08..ab4feb415ea6c0bb85649791aef382caa0609fee 100644
--- a/schema/solver/SolverCeres.schema
+++ b/schema/solver/SolverCeres.schema
@@ -45,7 +45,7 @@ use_nonmonotonic_steps:
   _doc: If the solver is allowed to update the solution with non-monotonic steps. Only used in LEVENBERG_MARQUARDT and DOGLEG minimizers.
 
 max_consecutive_nonmonotonic_steps:
-  _mandatory: $use_nonmonotonic_steps
+  _mandatory: false
   _type: unsigned int
-  _default: 0
+  _default: 2
   _doc: Amount of consecutive non-monotonic steps allowed. Only used in LEVENBERG_MARQUARDT and DOGLEG minimizers.
\ No newline at end of file
diff --git a/test/gtest_factor_absolute.cpp b/test/gtest_factor_absolute.cpp
index 82e17f02fd966f27b09897ceac054ad449c40025..c41dbd7bd327a60f233d44bb6b08914434e85b58 100644
--- a/test/gtest_factor_absolute.cpp
+++ b/test/gtest_factor_absolute.cpp
@@ -32,29 +32,40 @@ using namespace wolf;
 using std::cout;
 using std::endl;
 
-Vector10d pose9toPose10(Vector9d _pose9)
-{
-    return (Vector10d() << _pose9.head<3>() , v2q(_pose9.segment<3>(3)).coeffs(), _pose9.tail<3>()).finished();
-}
-
-// Input pose9 and covariance
-Vector9d pose(Vector9d::Random());
-Vector10d pose10 = pose9toPose10(pose);
-Eigen::Matrix<double, 9, 9> data_cov = 0.2 * Eigen::Matrix<double,9,9>::Identity();
-
-// perturbated priors
-Vector10d x0 = pose9toPose10(pose + Vector9d::Random()*0.25);
+int N = 10;
 
-// Problem and solver
-ProblemPtr problem_ptr = Problem::create("POV", 3);
-SolverCeres solver(problem_ptr);
+ProblemPtr problem;
+SolverCeresPtr solver;
+FrameBasePtr frm;
+CaptureBasePtr cap;
+VectorComposite pose;
+Matrix9d pose_cov = 1e-3 * Matrix9d::Identity();
 
-// Two frames
-FrameBasePtr frm0 = problem_ptr->emplaceFrame(0, problem_ptr->stateZero() );
-
-// Capture
-// auto cap0 = CaptureBase::emplace<CaptureMotion>(frm0, "IMU ABS", 0, nullptr, pose10, 10, 9, nullptr);
-auto cap0 = CaptureBase::emplace<CaptureMotion>(frm0, "IMU ABS", 0, nullptr, pose10, nullptr);
+void randomSetup(int dim)
+{
+    if (problem)
+        problem.reset();
+    if (solver)
+        solver.reset();
+    if (frm)
+        frm->remove();
+
+    // Problem and solver
+    problem = Problem::create("POV", dim);
+    solver = std::make_shared<SolverCeres>(problem);
+
+    // random pose
+    if (dim == 2)
+        pose = VectorComposite("POV", {Vector2d::Random() * 10, Vector1d::Random() * M_PI, Vector2d::Random()*2});
+    else
+        pose = VectorComposite("POV", {Vector3d::Random() * 10, Vector4d::Random().normalized(), Vector3d::Random()*2});
+
+    // frame and capture
+    frm = problem->emplaceFrame(0, pose);
+    cap = CaptureBase::emplace<CaptureBase>(frm, "ABS CAPTURE", 0);
+    
+    ASSERT_TRUE(problem->check(0));
+}
 
 ////////////////////////////////////////////////////////
 /* In the tests below, we check that FactorBlockAbsolute and FactorQuaternionAbsolute are working fine
@@ -64,72 +75,152 @@ auto cap0 = CaptureBase::emplace<CaptureMotion>(frm0, "IMU ABS", 0, nullptr, pos
 
 TEST(FactorBlockAbs, fac_block_abs_p)
 {
-    auto fea0 = FeatureBase::emplace<FeatureBase>(cap0, "POSITION", pose10.head<3>(), data_cov.topLeftCorner<3,3>());
-    FactorBase::emplace<FactorBlockAbsolute>(fea0, fea0, fea0->getFrame()->getP(), nullptr, false);
+    for (auto i = 0; i < N; i++)
+    {
+        randomSetup(3);
 
-    ASSERT_TRUE(problem_ptr->check(0));
+        auto fea = FeatureBase::emplace<FeatureBase>(cap, "POSITION", pose.at('P'), 1e-3 * Matrix3d::Identity());
+        FactorBase::emplace<FactorBlockAbsolute>(fea, fea, fea->getFrame()->getP(), nullptr, false);
 
-    // Unfix frame 0, perturb frm0
-    frm0->unfix();
-    frm0->setState(x0,"POV");
+        // Unfix and perturb frame
+        frm->unfix();
+        frm->perturb();
 
-    // solve for frm0
-    std::string brief_report = solver.solve(wolf::SolverManager::ReportVerbosity::BRIEF);
+        // solve for frm
+        std::string report = solver->solve(wolf::SolverManager::ReportVerbosity::FULL);
+        //std::cout << report << std::endl;
 
-    //only orientation is constrained
-    ASSERT_MATRIX_APPROX(frm0->getP()->getState(), pose10.head<3>(), 1e-6);
+        //only position is constrained
+        ASSERT_MATRIX_APPROX(frm->getP()->getState(), pose.at('P'), 1e-6);
+    }
 }
 
 TEST(FactorBlockAbs, fac_block_abs_p_tail2)
 {
-    auto fea0 = FeatureBase::emplace<FeatureBase>(cap0, "POSITION TAIL 2", pose10.segment<2>(1), data_cov.bottomRightCorner<2,2>());
-    FactorBase::emplace<FactorBlockAbsolute>(fea0, fea0, fea0->getFrame()->getP(),1,2, nullptr, false);
-
-    // Unfix frame 0, perturb frm0
-    frm0->unfix();
-    frm0->setState(x0,"POV");
-
-    // solve for frm0
-    std::string brief_report = solver.solve(wolf::SolverManager::ReportVerbosity::BRIEF);
-
-    //only orientation is constrained
-    ASSERT_MATRIX_APPROX(frm0->getP()->getState().tail<2>(), pose10.segment<2>(1), 1e-6);
+    for (auto i = 0; i < N; i++)
+    {
+        randomSetup(3);
+        
+        auto fea = FeatureBase::emplace<FeatureBase>(cap, "POSITION TAIL 2", pose.at('P').tail<2>(), 1e-3 * Matrix2d::Identity());
+        FactorBase::emplace<FactorBlockAbsolute>(fea, fea, fea->getFrame()->getP(),1,2, nullptr, false);
+
+        // Unfix and perturb frame
+        frm->unfix();
+        frm->perturb();
+
+        // solve for frm
+        std::string report = solver->solve(wolf::SolverManager::ReportVerbosity::FULL);
+        //std::cout << report << std::endl;
+        
+        //only position tail is constrained
+        ASSERT_MATRIX_APPROX(frm->getP()->getState().tail<2>(), pose.at('P').tail<2>(), 1e-6);
+    }
 }
 
 TEST(FactorBlockAbs, fac_block_abs_v)
 {
-    auto fea0 = FeatureBase::emplace<FeatureBase>(cap0, "FeatureVelocity", pose10.tail<3>(), data_cov.bottomRightCorner<3,3>());
-    FactorBase::emplace<FactorBlockAbsolute>(fea0, fea0, fea0->getFrame()->getV(), nullptr, false);
-
-    ASSERT_TRUE(problem_ptr->check(0));
-    
-    // Unfix frame 0, perturb frm0
-    frm0->unfix();
-    frm0->setState(x0,"POV");
-
-    // solve for frm0
-    std::string brief_report = solver.solve(wolf::SolverManager::ReportVerbosity::BRIEF);
+    for (auto i = 0; i < N; i++)
+    {
+        randomSetup(3);
+        
+        auto fea = FeatureBase::emplace<FeatureBase>(cap, "FeatureVelocity", pose.at('V'), 1e-3 * Matrix3d::Identity());
+        FactorBase::emplace<FactorBlockAbsolute>(fea, fea, fea->getFrame()->getV(), nullptr, false);
+
+        ASSERT_TRUE(problem->check(0));
+        
+        // Unfix and perturb frame
+        frm->unfix();
+        frm->perturb();
+
+        // solve for frm
+        std::string report = solver->solve(wolf::SolverManager::ReportVerbosity::FULL);
+        //std::cout << report << std::endl;
+        
+        //only velocity is constrained
+        ASSERT_MATRIX_APPROX(frm->getV()->getState(), pose.at('V'), 1e-6);
+    }
+}
 
-    //only velocity is constrained
-    ASSERT_MATRIX_APPROX(frm0->getV()->getState(), pose10.tail<3>(), 1e-6);
+TEST(FactorQuatAbs, fac_block_abs_q)
+{
+    for (auto i = 0; i < N; i++)
+    {
+        randomSetup(3);
+        
+        auto fea = FeatureBase::emplace<FeatureBase>(cap, "FeatureQuaternion", pose.at('O'), 1e-3 * Matrix3d::Identity());
+        FactorBase::emplace<FactorQuaternionAbsolute>(fea, fea, fea->getFrame()->getO(), nullptr, false);
+
+        ASSERT_TRUE(problem->check(0));
+        
+        // Unfix and perturb frame
+        frm->unfix();
+        frm->perturb();
+
+        // solve for frm
+        std::string report = solver->solve(wolf::SolverManager::ReportVerbosity::FULL);
+        //std::cout << report << std::endl;
+        
+        //only quaternion is constrained
+        ASSERT_QUATERNION_VECTOR_APPROX(frm->getO()->getState(), pose.at('O'), 1e-6);
+    }
 }
 
-TEST(FactorQuatAbs, fac_block_abs_o)
+TEST(FactorQuatAbs, fac_block_abs_angle)
 {
-    auto fea0 = FeatureBase::emplace<FeatureBase>(cap0, "FeatureQuaternion", pose10.segment<4>(3), data_cov.block<3,3>(3,3));
-    FactorBase::emplace<FactorQuaternionAbsolute>(fea0, fea0, fea0->getFrame()->getO(), nullptr, false);
+    for (auto i = 0; i < N; i++)
+    {
+        randomSetup(2);
+        
+        auto fea = FeatureBase::emplace<FeatureBase>(cap, "FeatureAngle", pose.at('O'), 1e-3 * Matrix1d::Identity());
+        FactorBase::emplace<FactorBlockAbsolute>(fea, fea, fea->getFrame()->getO(), nullptr, false);
+
+        ASSERT_TRUE(problem->check(0));
+        
+        // Unfix and perturb frame
+        frm->unfix();
+        frm->perturb();
+
+        // solve for frm
+        std::string report = solver->solve(wolf::SolverManager::ReportVerbosity::FULL);
+        //std::cout << report << std::endl;
+        
+        //only quaternion is constrained
+        ASSERT_MATRIX_APPROX(frm->getO()->getState(), pose.at('O'), 1e-6);
+    }
+}
 
-    ASSERT_TRUE(problem_ptr->check(0));
+// --------------------------- DEATH TESTS --------------------------------------
+// FactorBlockAbsolute in a StateQuaternion
+TEST(FactorBlockAbs, fac_block_wrong1)
+{
+    randomSetup(3);
     
-    // Unfix frame 0, perturb frm0
-    frm0->unfix();
-    frm0->setState(x0,"POV");
-
-    // solve for frm0
-    std::string brief_report = solver.solve(wolf::SolverManager::ReportVerbosity::BRIEF);
-
-    //only velocity is constrained
-    ASSERT_QUATERNION_VECTOR_APPROX(frm0->getO()->getState(), pose10.segment<4>(3), 1e-6);
+    auto fea = FeatureBase::emplace<FeatureBase>(cap, "QUATERNION", pose.at('O'), 1e-3 * Matrix3d::Identity());
+    ASSERT_DEATH(FactorBase::emplace<FactorBlockAbsolute>(fea, fea, fea->getFrame()->getO(), nullptr, false),"");
+}
+// FactorQuaternionAbsolute in a StateBlock
+TEST(FactorBlockAbs, fac_block_wrong2)
+{
+    randomSetup(3);
+    
+    auto fea = FeatureBase::emplace<FeatureBase>(cap, "POSITION", pose.at('P'), 1e-3 * Matrix3d::Identity());
+    ASSERT_DEATH(FactorBase::emplace<FactorQuaternionAbsolute>(fea, fea, fea->getFrame()->getP(), nullptr, false),"");
+}
+// sizes mismatch
+TEST(FactorBlockAbs, fac_block_wrong3)
+{
+    randomSetup(3);
+    
+    auto fea = FeatureBase::emplace<FeatureBase>(cap, "POSITION tail 2", pose.at('P').tail<2>(), 1e-3 * Matrix2d::Identity());
+    ASSERT_DEATH(FactorBase::emplace<FactorBlockAbsolute>(fea, fea, fea->getFrame()->getP(),2,2, nullptr, false),"");
+}
+// sizes mismatch
+TEST(FactorBlockAbs, fac_block_wrong4)
+{
+    randomSetup(2);
+    
+    auto fea = FeatureBase::emplace<FeatureBase>(cap, "ANGLE", pose.at('O'), 1e-3 * Matrix1d::Identity());
+    ASSERT_DEATH(FactorBase::emplace<FactorBlockAbsolute>(fea, fea, fea->getFrame()->getO(),0,2, nullptr, false),"");
 }
 
 int main(int argc, char **argv)