diff --git a/include/core/state_block/local_parametrization_base.h b/include/core/state_block/local_parametrization_base.h
index 32599d9dc72a556c06f9ade7df6339f38cc7c8cf..14f2ce38f1dd55b6571884710eb7ed7b7640f985 100644
--- a/include/core/state_block/local_parametrization_base.h
+++ b/include/core/state_block/local_parametrization_base.h
@@ -12,8 +12,6 @@
 
 namespace wolf {
 
-//WOLF_PTR_TYPEDEFS(LocalParametrizationBase);
-
 class LocalParametrizationBase{
     protected:
         unsigned int global_size_;
@@ -22,13 +20,17 @@ class LocalParametrizationBase{
         LocalParametrizationBase(unsigned int _global_size, unsigned int _local_size);
         virtual ~LocalParametrizationBase();
 
+        bool         plus(const Eigen::VectorXd& _x,
+                          const Eigen::VectorXd& _delta,
+                          Eigen::VectorXd&       _x_plus_delta) const;
         virtual bool plus(Eigen::Map<const Eigen::VectorXd>& _x,
                           Eigen::Map<const Eigen::VectorXd>& _delta,
-                          Eigen::Map<Eigen::VectorXd>& _x_plus_delta) const = 0;
-        virtual bool computeJacobian(Eigen::Map<const Eigen::VectorXd>& _x, Eigen::Map<Eigen::MatrixRowXd>& _jacobian) const = 0;
+                          Eigen::Map<Eigen::VectorXd>&       _x_plus_delta) const = 0;
+        virtual bool computeJacobian(Eigen::Map<const Eigen::VectorXd>& _x,
+                                     Eigen::Map<Eigen::MatrixRowXd>& _jacobian) const = 0;
         virtual bool minus(Eigen::Map<const Eigen::VectorXd>& _x1,
                            Eigen::Map<const Eigen::VectorXd>& _x2,
-                           Eigen::Map<Eigen::VectorXd>& _x2_minus_x1) = 0;
+                           Eigen::Map<Eigen::VectorXd>&       _x2_minus_x1) = 0;
 
         unsigned int getLocalSize() const;
         unsigned int getGlobalSize() const;
diff --git a/include/core/state_block/state_block.h b/include/core/state_block/state_block.h
index ab3bb7147f3c81f57a3436216412274394acc04a..99e15bd20351c1dcb61f4d373a842b7ea492d5d6 100644
--- a/include/core/state_block/state_block.h
+++ b/include/core/state_block/state_block.h
@@ -150,13 +150,7 @@ public:
          */
         void perturb(double amplitude = 0.1);
 
-        /** \brief Add this state_block to the problem
-         **/
-        //void addToProblem(ProblemPtr _problem_ptr);
-
-        /** \brief Remove this state_block from the problem
-         **/
-        //void removeFromProblem(ProblemPtr _problem_ptr);
+        void plus(const Eigen::VectorXd& _dv);
 };
 
 } // namespace wolf
diff --git a/src/state_block/has_state_blocks.cpp b/src/state_block/has_state_blocks.cpp
index 59270a335c9a75bb362e23614e3fb886dc4e880d..7bdd6b48842ed91257b308d82ae836d4ab2cee82 100644
--- a/src/state_block/has_state_blocks.cpp
+++ b/src/state_block/has_state_blocks.cpp
@@ -78,4 +78,16 @@ void HasStateBlocks::perturb(double amplitude)
     }
 }
 
+void HasStateBlocks::plus(const VectorComposite& _dx)
+{
+    for (const auto& pair_key_sb : state_block_map_)
+    {
+        auto& sb = pair_key_sb.second;
+        auto& dv = _dx.at(pair_key_sb.first);
+
+        sb->plus(dv);
+    }
+}
+
+
 }
diff --git a/src/state_block/local_parametrization_base.cpp b/src/state_block/local_parametrization_base.cpp
index f46a93f9c488d0b899e94df156f3faff04a63554..aee3f704126bf4ba81e9658b3c337ded088c78a5 100644
--- a/src/state_block/local_parametrization_base.cpp
+++ b/src/state_block/local_parametrization_base.cpp
@@ -22,3 +22,14 @@ unsigned int LocalParametrizationBase::getGlobalSize() const
 }
 
 } // namespace wolf
+
+bool wolf::LocalParametrizationBase::plus(const Eigen::VectorXd &_x,
+                                          const Eigen::VectorXd &_delta,
+                                          Eigen::VectorXd &_x_plus_delta) const
+{
+    Eigen::Map<const Eigen::VectorXd> x(_x.data(), _x.size());
+    Eigen::Map<const Eigen::VectorXd> delta(_delta.data(), _delta.size());
+    Eigen::Map<Eigen::VectorXd> x_plus_delta(_x_plus_delta.data(), _x_plus_delta.size());
+
+    return plus(x, delta, x_plus_delta);
+}
diff --git a/src/state_block/state_block.cpp b/src/state_block/state_block.cpp
index 783a56a5e8cb52fe0ae79e2ad14ca4b50976a48c..94f2dbfb8d92cdad7ec1aa2de7bb8197facfeb94 100644
--- a/src/state_block/state_block.cpp
+++ b/src/state_block/state_block.cpp
@@ -26,31 +26,22 @@ void StateBlock::setFixed(bool _fixed)
     fixed_.store(_fixed);
 }
 
-//void StateBlock::addToProblem(ProblemPtr _problem_ptr)
-//{
-//    _problem_ptr->addStateBlock(shared_from_this());
-//}
-//
-//void StateBlock::removeFromProblem(ProblemPtr _problem_ptr)
-//{
-//    _problem_ptr->removeStateBlock(shared_from_this());
-//}
-
 void StateBlock::perturb(double amplitude)
 {
     using namespace Eigen;
     VectorXd perturbation(VectorXd::Random(getLocalSize()) * amplitude);
+    this->plus(perturbation);
+}
+
+void StateBlock::plus(const Eigen::VectorXd &_dv)
+{
     if (local_param_ptr_ == nullptr)
-        state_ += perturbation;
+        setState(getState() + _dv);
     else
     {
-        VectorXd state_perturbed(getSize());
-        // Note: LocalParametrizationBase::plus() works with Eigen::Map only. Build all necessary maps:
-        Map<const VectorXd> state_map(state_.data(), getSize());
-        Map<const VectorXd> perturbation_map(perturbation.data(), getLocalSize());
-        Map<VectorXd> state_perturbed_map(state_perturbed.data(), getSize());
-        local_param_ptr_->plus(state_map, perturbation_map, state_perturbed_map);
-        state_ = state_perturbed;
+        Eigen::VectorXd state(getSize());
+        local_param_ptr_->plus(getState(), _dv, state);
+        setState(state);
     }
 }
 
diff --git a/test/gtest_state_block.cpp b/test/gtest_state_block.cpp
index 19d9e3cf63623ef275ee5f8fc8111f4e88ece4d1..d2a1398a8e21daf05603f7810b031f98528b009e 100644
--- a/test/gtest_state_block.cpp
+++ b/test/gtest_state_block.cpp
@@ -19,6 +19,73 @@ using namespace Eigen;
 using namespace std;
 using namespace wolf;
 
+TEST(StateBlock, plus)
+{
+    Vector3d x(10,20,30);
+    StateBlock sb(x);
+
+    Vector3d dx(1,2,3);
+
+    sb.plus(dx);
+
+    WOLF_INFO("original ", x.transpose(), ", perturbed = ", sb.getState().transpose());
+
+    ASSERT_MATRIX_APPROX(x + dx , sb.getState() , 1e-20);
+}
+
+TEST(StateBlock, angle_plus)
+{
+    StateAngle sb(1.0);
+
+    Vector1d dx(0.1);
+
+    sb.plus(dx);
+
+    WOLF_INFO("original ", 1.0, ", perturbed = ", sb.getState().transpose());
+
+    ASSERT_MATRIX_APPROX(Vector1d(1.0) + dx , sb.getState() , 1e-20);
+}
+
+TEST(StateBlock, angle_plus_past_pi)
+{
+    StateAngle sb(3.14);
+
+    Vector1d dx(0.1);
+
+    sb.plus(dx);
+
+    WOLF_INFO("original ", 3.14, ", perturbed = ", sb.getState().transpose());
+
+    ASSERT_MATRIX_APPROX(Vector1d(3.14 - 2.0*M_PI) + dx , sb.getState() , 1e-20);
+}
+
+TEST(StateBlock, quaternion_plus_norm)
+{
+    Vector4d x(0.5,0.5,0.5,0.5);
+    StateQuaternion sb(x);
+    Vector3d dx(.1,.2,.3);
+
+    sb.plus(dx);
+
+    WOLF_INFO("original ", x.transpose(), ", perturbed = ", sb.getState().transpose());
+
+    ASSERT_LT((sb.getState().transpose() * x).norm() , 1.0); // quaternions are not parallel ==> not equal
+}
+
+TEST(StateBlock, quaternion_plus_trivial)
+{
+    Vector4d x(0,0,0,1);   // identity (0,0,0,1)
+    StateQuaternion sb(x);
+    Vector3d dx(M_PI,0,0); // half turn over X axis --> result quaternion is (1,0,0,0)
+
+    sb.plus(dx);
+
+    WOLF_INFO("original ", x.transpose(), ", perturbed = ", sb.getState().transpose());
+
+    ASSERT_MATRIX_APPROX(sb.getState(), Vector4d(1,0,0,0), 1e-10);
+}
+
+
 TEST(StateBlock, block_perturb)
 {
     Vector3d x(10,20,30);