diff --git a/source/RobotAPI/components/units/RobotUnit/NJointControllers/NJointTaskSpaceImpedanceController.cpp b/source/RobotAPI/components/units/RobotUnit/NJointControllers/NJointTaskSpaceImpedanceController.cpp
index d2824cc6d313c9c6f727b104eda0db0a6b99f560..eba7eca3c78e4cc7ceddd079edd058bd1a4ec76c 100644
--- a/source/RobotAPI/components/units/RobotUnit/NJointControllers/NJointTaskSpaceImpedanceController.cpp
+++ b/source/RobotAPI/components/units/RobotUnit/NJointControllers/NJointTaskSpaceImpedanceController.cpp
@@ -19,17 +19,133 @@
  * @copyright  http://www.gnu.org/licenses/gpl-2.0.txt
  *             GNU General Public License
  */
-
-#include "NJointTaskSpaceImpedanceController.h"
+#include <boost/algorithm/clamp.hpp>
 
 #include <SimoxUtility/math/convert/mat4f_to_pos.h>
 #include <SimoxUtility/math/convert/mat4f_to_quat.h>
+#include <SimoxUtility/math/compare/is_equal.h>
 
 #include <VirtualRobot/MathTools.h>
 
+#include "NJointTaskSpaceImpedanceController.h"
 
 using namespace armarx;
 
+
+int CartesianImpedanceController::bufferSize() const
+{
+    return targetJointTorques.size();
+}
+void CartesianImpedanceController::initialize(const VirtualRobot::RobotNodeSetPtr& rns)
+{
+    ARMARX_CHECK_NOT_NULL(rns);
+    tcp = rns->getTCP();
+    ARMARX_CHECK_NOT_NULL(tcp);
+    ik.reset(new VirtualRobot::DifferentialIK(rns, rns->getRobot()->getRootNode(), VirtualRobot::JacobiProvider::eSVDDamped));
+
+    const auto size = rns->getSize();
+    qpos.resize(size);
+    qvel.resize(size);
+    tcptwist.resize(size);
+    nullqerror.resize(size);
+    nullspaceTorque.resize(size);
+    targetJointTorques.resize(size);
+
+    I = Eigen::MatrixXf::Identity(size, size);
+}
+const Eigen::VectorXf& CartesianImpedanceController::run(
+    const NJointTaskSpaceImpedanceControllerControlData& cfg,
+    std::vector<const SensorValue1DoFActuatorTorque*> torqueSensors,
+    std::vector<const SensorValue1DoFActuatorVelocity*> velocitySensors,
+    std::vector<const SensorValue1DoFActuatorPosition*> positionSensors
+)
+{
+    ARMARX_CHECK_EXPRESSION(simox::math::is_equal(bufferSize(), cfg.Knull.size())); ///TODO move this to core
+    ARMARX_CHECK_EXPRESSION(simox::math::is_equal(bufferSize(), cfg.Dnull.size()));
+    ARMARX_CHECK_EXPRESSION(simox::math::is_equal(bufferSize(), cfg.desiredJointPosition.size()));
+    ARMARX_CHECK_GREATER_EQUAL(cfg.torqueLimit, 0);
+
+    ARMARX_CHECK_EXPRESSION(simox::math::is_equal(bufferSize(), torqueSensors.size()));
+    ARMARX_CHECK_EXPRESSION(simox::math::is_equal(bufferSize(), velocitySensors.size()));
+    ARMARX_CHECK_EXPRESSION(simox::math::is_equal(bufferSize(), positionSensors.size()));
+
+    const Eigen::MatrixXf jacobi = ik->getJacobianMatrix(tcp, VirtualRobot::IKSolver::CartesianSelection::All); ///TODO output param version
+    ARMARX_CHECK_EXPRESSION(simox::math::is_equal(bufferSize(), jacobi.cols()));
+    ARMARX_CHECK_EXPRESSION(simox::math::is_equal(6, jacobi.rows()));
+    const Eigen::MatrixXf jtpinv = ik->computePseudoInverseJacobianMatrix(jacobi.transpose(), lambda);///TODO output param version
+
+    for (size_t i = 0; i < velocitySensors.size(); ++i)
+    {
+        qpos(i) = positionSensors[i]->position;
+        qvel(i) = velocitySensors[i]->velocity;
+    }
+
+    const Eigen::Vector6f tcptwist = jacobi * qvel;
+
+    const Eigen::Vector3f currentTCPLinearVelocity
+    {
+        0.001f * tcptwist(0),
+        0.001f * tcptwist(1),
+        0.001f * tcptwist(2)
+    };
+    const Eigen::Vector3f currentTCPAngularVelocity
+    {
+        tcptwist(3),
+        tcptwist(4),
+        tcptwist(5)
+    };
+
+    const Eigen::Vector3f currentTCPPosition = tcp->getPositionInRootFrame();
+    const Eigen::Vector3f tcpForces = 0.001 * cfg.Kpos.cwiseProduct(cfg.desiredPosition - currentTCPPosition);
+    const Eigen::Vector3f tcpDesiredForce = tcpForces - cfg.Dpos.cwiseProduct(currentTCPLinearVelocity);
+
+    const Eigen::Matrix4f currentTCPPose = tcp->getPoseInRootFrame();
+    const Eigen::Matrix3f currentRotMat = currentTCPPose.block<3, 3>(0, 0);
+    const Eigen::Matrix3f desiredMat(cfg.desiredOrientation);
+    const Eigen::Matrix3f diffMat = desiredMat * currentRotMat.inverse();
+    //    const Eigen::Quaternionf cquat(currentRotMat);
+    //    const Eigen::Quaternionf diffQuaternion = desiredQuaternion * cquat.conjugate();
+    //    const Eigen::AngleAxisf angleAxis(diffQuaternion);
+
+    const Eigen::Vector3f rpy = VirtualRobot::MathTools::eigen3f2rpy(diffMat);
+    const Eigen::Vector3f tcpDesiredTorque =
+        cfg.Kori.cwiseProduct(rpy) -
+        cfg.Dori.cwiseProduct(currentTCPAngularVelocity);
+    Eigen::Vector6f tcpDesiredWrench;
+    tcpDesiredWrench <<   0.001 * tcpDesiredForce, tcpDesiredTorque;
+
+    // calculate desired joint torque
+    nullqerror = cfg.desiredJointPosition - qpos;
+
+    for (int i = 0; i < nullqerror.rows(); ++i)
+    {
+        if (fabs(nullqerror(i)) < 0.09)
+        {
+            nullqerror(i) = 0;
+        }
+    }
+    nullspaceTorque = cfg.Knull.cwiseProduct(nullqerror) - cfg.Dnull.cwiseProduct(qvel);
+
+    targetJointTorques =
+        jacobi.transpose() * tcpDesiredWrench +
+        (I - jacobi.transpose() * jtpinv) * nullspaceTorque;
+    for (int i = 0; i < targetJointTorques.size(); ++i)
+    {
+        targetJointTorques(i) = boost::algorithm::clamp(targetJointTorques(i), -cfg.torqueLimit, cfg.torqueLimit);
+    }
+    //write debug data
+    {
+        const Eigen::Quaternionf cquat(currentRotMat);
+        dbg.errorAngle = cquat.angularDistance(cfg.desiredOrientation);
+        dbg.posiError = (cfg.desiredPosition - currentTCPPosition).norm();
+        dbg.tcpDesiredForce = tcpDesiredForce;
+        dbg.tcpDesiredTorque = tcpDesiredTorque;
+    }
+
+    return targetJointTorques;
+}
+
+
 NJointControllerRegistration<NJointTaskSpaceImpedanceController> registrationControllerDSRTController("NJointTaskSpaceImpedanceController");
 
 NJointTaskSpaceImpedanceController::NJointTaskSpaceImpedanceController(const RobotUnitPtr& robotUnit, const NJointControllerConfigPtr& config, const VirtualRobot::RobotPtr&)
@@ -70,8 +186,8 @@ NJointTaskSpaceImpedanceController::NJointTaskSpaceImpedanceController(const Rob
         velocitySensors.push_back(velocitySensor);
         positionSensors.push_back(positionSensor);
     };
-    tcp = rns->getTCP();
-    ik.reset(new VirtualRobot::DifferentialIK(rns, rns->getRobot()->getRootNode(), VirtualRobot::JacobiProvider::eSVDDamped));
+
+    controller.initialize(rns);
 
     NJointTaskSpaceImpedanceControllerControlData initData;
     initData.desiredOrientation = cfg->desiredOrientation;
@@ -92,111 +208,32 @@ NJointTaskSpaceImpedanceController::NJointTaskSpaceImpedanceController(const Rob
 
 void NJointTaskSpaceImpedanceController::rtRun(const IceUtil::Time& /*sensorValuesTimestamp*/, const IceUtil::Time& /*timeSinceLastIteration*/)
 {
-    const Eigen::MatrixXf jacobi = ik->getJacobianMatrix(tcp, VirtualRobot::IKSolver::CartesianSelection::All);
-
-    ARMARX_CHECK_EQUAL(positionSensors.size(), velocitySensors.size());
-    Eigen::VectorXf qpos;
-    Eigen::VectorXf qvel;
-    qpos.resize(positionSensors.size());
-    qvel.resize(velocitySensors.size());
-
-    const int jointDim = positionSensors.size();
-
-    for (size_t i = 0; i < velocitySensors.size(); ++i)
-    {
-        qpos(i) = positionSensors[i]->position;
-        qvel(i) = velocitySensors[i]->velocity;
-    }
-
-    const Eigen::Vector6f tcptwist = jacobi * qvel;
-
-    const Eigen::Vector3f currentTCPLinearVelocity
-    {
-        0.001f * tcptwist(0),
-        0.001f * tcptwist(1),
-        0.001f * tcptwist(2)
-    };
-    const Eigen::Vector3f currentTCPAngularVelocity
-    {
-        tcptwist(3),
-        tcptwist(4),
-        tcptwist(5)
-    };
-
     rtUpdateControlStruct();
-    const Eigen::Vector3f desiredPosition = rtGetControlStruct().desiredPosition;
-    const Eigen::Quaternionf desiredOrientation = rtGetControlStruct().desiredOrientation;
-    const Eigen::Vector3f Kpos = rtGetControlStruct().Kpos;
-    const Eigen::Vector3f Dpos = rtGetControlStruct().Dpos;
-    const Eigen::Vector3f Kori = rtGetControlStruct().Kori;
-    const Eigen::Vector3f Dori = rtGetControlStruct().Dori;
-    const Eigen::VectorXf Knull = rtGetControlStruct().Knull;
-    const Eigen::VectorXf Dnull = rtGetControlStruct().Dnull;
-
-
-    const Eigen::Vector3f currentTCPPosition = tcp->getPositionInRootFrame();
-    const Eigen::Vector3f tcpForces = 0.001 * Kpos.cwiseProduct(desiredPosition - currentTCPPosition);
-    const Eigen::Vector3f tcpDesiredForce = tcpForces - Dpos.cwiseProduct(currentTCPLinearVelocity);
-
-    const Eigen::Matrix4f currentTCPPose = tcp->getPoseInRootFrame();
-    const Eigen::Matrix3f currentRotMat = currentTCPPose.block<3, 3>(0, 0);
-    const Eigen::Matrix3f desiredMat(desiredOrientation);
-    const Eigen::Matrix3f diffMat = desiredMat * currentRotMat.inverse();
-    const Eigen::Quaternionf cquat(currentRotMat);
-    //    const Eigen::Quaternionf diffQuaternion = desiredQuaternion * cquat.conjugate();
-    //    const Eigen::AngleAxisf angleAxis(diffQuaternion);
-
-    const Eigen::Vector3f rpy = VirtualRobot::MathTools::eigen3f2rpy(diffMat);
-    const Eigen::Vector3f tcpDesiredTorque = Kori.cwiseProduct(rpy) - Dori.cwiseProduct(currentTCPAngularVelocity);
-    Eigen::Vector6f tcpDesiredWrench;
-    tcpDesiredWrench <<   0.001 * tcpDesiredForce, tcpDesiredTorque;
-
-    // calculate desired joint torque
-    const Eigen::MatrixXf I = Eigen::MatrixXf::Identity(jointDim, jointDim);
-    const float lambda = 2;
-    const Eigen::MatrixXf jtpinv = ik->computePseudoInverseJacobianMatrix(jacobi.transpose(), lambda);
-    Eigen::VectorXf nullqerror = rtGetControlStruct().desiredJointPosition - qpos;
+    const auto& jointDesiredTorques = controller.run(
+                                          rtGetControlStruct(),
+                                          torqueSensors,
+                                          velocitySensors,
+                                          positionSensors
+                                      );
+    ARMARX_CHECK_EXPRESSION(simox::math::is_equal(targets.size(), jointDesiredTorques.size()));
 
-    ARMARX_CHECK_EQUAL(static_cast<std::size_t>(nullqerror.rows()), targets.size());
-    for (int i = 0; i < nullqerror.rows(); ++i)
-    {
-        if (fabs(nullqerror(i)) < 0.09)
-        {
-            nullqerror(i) = 0;
-        }
-    }
-    const Eigen::VectorXf nullspaceTorque = Knull.cwiseProduct(nullqerror) - Dnull.cwiseProduct(qvel);
-
-    const Eigen::VectorXf jointDesiredTorques = jacobi.transpose() * tcpDesiredWrench + (I - jacobi.transpose() * jtpinv) * nullspaceTorque;
-    ARMARX_CHECK_EQUAL(static_cast<std::size_t>(jointDesiredTorques.rows()), targets.size());
-
-    const auto torqueLimit = rtGetControlStruct().torqueLimit;
     for (size_t i = 0; i < targets.size(); ++i)
     {
-        float desiredTorque = jointDesiredTorques(i);
-        desiredTorque = (desiredTorque >  torqueLimit) ? torqueLimit : desiredTorque;
-        desiredTorque = (desiredTorque < -torqueLimit) ? -torqueLimit : desiredTorque;
-        debugDataInfo.getWriteBuffer().desired_torques[jointNames[i]] = jointDesiredTorques(i);
-
-        targets.at(i)->torque = desiredTorque;
+        targets.at(i)->torque = jointDesiredTorques(i);
         if (!targets.at(i)->isValid())
         {
             targets.at(i)->torque = 0;
         }
     }
 
-
-    float errorAngle = cquat.angularDistance(desiredOrientation);
-    float posiError = (desiredPosition - currentTCPPosition).norm();
-
-    debugDataInfo.getWriteBuffer().desiredForce_x = tcpDesiredForce(0);
-    debugDataInfo.getWriteBuffer().desiredForce_y = tcpDesiredForce(1);
-    debugDataInfo.getWriteBuffer().desiredForce_z = tcpDesiredForce(2);
-    debugDataInfo.getWriteBuffer().tcpDesiredTorque_x = tcpDesiredTorque(0);
-    debugDataInfo.getWriteBuffer().tcpDesiredTorque_y = tcpDesiredTorque(1);
-    debugDataInfo.getWriteBuffer().tcpDesiredTorque_z = tcpDesiredTorque(2);
-    debugDataInfo.getWriteBuffer().quatError = errorAngle;
-    debugDataInfo.getWriteBuffer().posiError = posiError;
+    debugDataInfo.getWriteBuffer().desiredForce_x = controller.dbg.tcpDesiredForce(0);
+    debugDataInfo.getWriteBuffer().desiredForce_y = controller.dbg.tcpDesiredForce(1);
+    debugDataInfo.getWriteBuffer().desiredForce_z = controller.dbg.tcpDesiredForce(2);
+    debugDataInfo.getWriteBuffer().tcpDesiredTorque_x = controller.dbg.tcpDesiredTorque(0);
+    debugDataInfo.getWriteBuffer().tcpDesiredTorque_y = controller.dbg.tcpDesiredTorque(1);
+    debugDataInfo.getWriteBuffer().tcpDesiredTorque_z = controller.dbg.tcpDesiredTorque(2);
+    debugDataInfo.getWriteBuffer().quatError = controller.dbg.errorAngle;
+    debugDataInfo.getWriteBuffer().posiError = controller.dbg.posiError;
     debugDataInfo.commitWrite();
 
 }
diff --git a/source/RobotAPI/components/units/RobotUnit/NJointControllers/NJointTaskSpaceImpedanceController.h b/source/RobotAPI/components/units/RobotUnit/NJointControllers/NJointTaskSpaceImpedanceController.h
index fd5cea5dff98a6207ef9d28fd41faf4a98d426f4..a3cfd8c392a1bf0f30ba511773387ef08d467a97 100644
--- a/source/RobotAPI/components/units/RobotUnit/NJointControllers/NJointTaskSpaceImpedanceController.h
+++ b/source/RobotAPI/components/units/RobotUnit/NJointControllers/NJointTaskSpaceImpedanceController.h
@@ -45,7 +45,47 @@ namespace armarx
         Eigen::Vector3f Dori;
         Eigen::VectorXf Knull;
         Eigen::VectorXf Dnull;
+        Eigen::VectorXf desiredJointPosition;
+        float torqueLimit;
     };
+
+    class CartesianImpedanceController
+    {
+    private:
+        Eigen::VectorXf qpos;
+        Eigen::VectorXf qvel;
+        Eigen::VectorXf tcptwist;
+        Eigen::VectorXf nullqerror;
+        Eigen::VectorXf nullspaceTorque;
+        Eigen::VectorXf targetJointTorques;
+
+        Eigen::MatrixXf I;
+
+        VirtualRobot::DifferentialIKPtr ik;
+        VirtualRobot::RobotNodePtr tcp;
+
+        const float lambda = 2;
+    public:
+        //state for debugging
+        struct Debug
+        {
+            float errorAngle;
+            float posiError;
+            Eigen::Vector3f tcpDesiredForce;
+            Eigen::Vector3f tcpDesiredTorque;
+        };
+        Debug dbg;
+
+        int bufferSize() const;
+        void initialize(const VirtualRobot::RobotNodeSetPtr& rns);
+        const Eigen::VectorXf& run(
+            const NJointTaskSpaceImpedanceControllerControlData& cfg,
+            std::vector<const SensorValue1DoFActuatorTorque*> torqueSensors,
+            std::vector<const SensorValue1DoFActuatorVelocity*> velocitySensors,
+            std::vector<const SensorValue1DoFActuatorPosition*> positionSensors
+        );
+    };
+
     /**
     * @defgroup Library-NJointTaskSpaceImpedanceController NJointTaskSpaceImpedanceController
     * @ingroup Library-RobotUnit-NJointControllers
@@ -76,18 +116,16 @@ namespace armarx
     protected:
         void onPublish(const SensorAndControl&, const DebugDrawerInterfacePrx&, const DebugObserverInterfacePrx&) override;
 
-        void setPosition(const Ice::FloatSeq&, const Ice::Current&) override;
-        void setOrientation(const Ice::FloatSeq&, const Ice::Current&) override;
+        void setPosition(const Eigen::Vector3f&, const Ice::Current&) override;
+        void setOrientation(const Eigen::Quaternionf&, const Ice::Current&) override;
+        void setPositionOrientation(const Eigen::Vector3f& pos, const Eigen::Quaternionf& ori, const Ice::Current&) override;
+        void setPose(const Eigen::Matrix4f& mat, const Ice::Current&) override;
+
         void setImpedanceParameters(const std::string&, const Ice::FloatSeq&, const Ice::Current&);
+        void setNullspaceConfig(const Eigen::VectorXf& joint, const Eigen::VectorXf& knull, const Eigen::VectorXf& dnull, const Ice::Current&) override;
+        void setConfig(const NJointTaskSpaceImpedanceControlConfigPtr& cfg, const Ice::Current&) override;
 
     private:
-        VirtualRobot::DifferentialIKPtr ik;
-
-        Eigen::VectorXf desiredJointPosition;
-
-
-        VirtualRobot::RobotNodePtr tcp;
-
         std::vector<const SensorValue1DoFActuatorTorque*> torqueSensors;
         std::vector<const SensorValue1DoFActuatorVelocity*> velocitySensors;
         std::vector<const SensorValue1DoFActuatorPosition*> positionSensors;
@@ -121,8 +159,8 @@ namespace armarx
         };
         TripleBuffer<NJointTaskSpaceImpedanceControllerDebugInfo> debugDataInfo;
 
-        float torqueLimit;
         std::vector<std::string> jointNames;
+        CartesianImpedanceController controller;
 
 
         // NJointController interface