diff --git a/CMakeLists.txt b/CMakeLists.txt
index 5ae7be96ac49e4e245d16d978a2bdace25c0d911..6a8913998ec10b4d98a2536c4aca3dc3eb06efc5 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -20,7 +20,7 @@ set(ARMARX_ENABLE_AUTO_CODE_FORMATTING TRUE)
 armarx_project("RobotAPI")
 depends_on_armarx_package(ArmarXGui)
 
-set(ArmarX_Simox_VERSION 2.3.59)
+set(ArmarX_Simox_VERSION 2.3.64)
 option(REQUIRE_SIMOX "If enabled the Simox dependency is a required dependency" TRUE)
 
 if(REQUIRE_SIMOX)
diff --git a/source/RobotAPI/components/units/RobotUnit/CMakeLists.txt b/source/RobotAPI/components/units/RobotUnit/CMakeLists.txt
index f2d1ec328e91bd315d5f74bf0ab8879b85e112c0..d14b838fae5204870608e981e451eedc17f324f3 100644
--- a/source/RobotAPI/components/units/RobotUnit/CMakeLists.txt
+++ b/source/RobotAPI/components/units/RobotUnit/CMakeLists.txt
@@ -75,6 +75,7 @@ set(LIB_HEADERS
     util/introspection/ClassMemberInfoEntry.h
     util/introspection/ClassMemberInfo.h
     util/RtLogging.h
+    util/RtTiming.h
 
     #robot unit modules need to be added to the list below (but not here)
     RobotUnitModules/RobotUnitModuleBase.h
diff --git a/source/RobotAPI/components/units/RobotUnit/NJointControllers/NJointCartesianVelocityController.cpp b/source/RobotAPI/components/units/RobotUnit/NJointControllers/NJointCartesianVelocityController.cpp
index 7d2264e65314ffe5023cc98d9855936596d268eb..ed5405e802c16addc84980dd510345774ed63a98 100644
--- a/source/RobotAPI/components/units/RobotUnit/NJointControllers/NJointCartesianVelocityController.cpp
+++ b/source/RobotAPI/components/units/RobotUnit/NJointControllers/NJointCartesianVelocityController.cpp
@@ -312,6 +312,13 @@ namespace armarx
         writeControlStruct();
     }
 
+    void NJointCartesianVelocityController::setAvoidJointLimitsKp(float kp)
+    {
+        LockGuardType guard {controlDataMutex};
+        getWriterControlStruct().avoidJointLimitsKp = kp;
+        writeControlStruct();
+    }
+
     std::string NJointCartesianVelocityController::getNodeSetName() const
     {
         return nodeSetName;
diff --git a/source/RobotAPI/components/units/RobotUnit/NJointControllers/NJointCartesianVelocityController.h b/source/RobotAPI/components/units/RobotUnit/NJointControllers/NJointCartesianVelocityController.h
index 7c792c309119b66a07e9c13983e75c3e177eac4d..995d84fe733411d2f101f1968325f814b8a595cb 100644
--- a/source/RobotAPI/components/units/RobotUnit/NJointControllers/NJointCartesianVelocityController.h
+++ b/source/RobotAPI/components/units/RobotUnit/NJointControllers/NJointCartesianVelocityController.h
@@ -108,6 +108,7 @@ namespace armarx
 
         // for TCPControlUnit
         void setVelocities(float xVel, float yVel, float zVel, float rollVel, float pitchVel, float yawVel, VirtualRobot::IKSolver::CartesianSelection mode);
+        void setAvoidJointLimitsKp(float kp);
         std::string getNodeSetName() const;
         static ::armarx::WidgetDescription::WidgetSeq createSliders();
         WidgetDescription::HBoxLayoutPtr createJointSlidersLayout(float min, float max, float defaultValue) const;
diff --git a/source/RobotAPI/components/units/RobotUnit/NJointControllers/NJointCartesianVelocityControllerWithRamp.cpp b/source/RobotAPI/components/units/RobotUnit/NJointControllers/NJointCartesianVelocityControllerWithRamp.cpp
index f69ae7ff8721f315772428ace9ff89a3447e1abe..d02cbfc4e7720d21f1798c2896e5d43adaecd839 100644
--- a/source/RobotAPI/components/units/RobotUnit/NJointControllers/NJointCartesianVelocityControllerWithRamp.cpp
+++ b/source/RobotAPI/components/units/RobotUnit/NJointControllers/NJointCartesianVelocityControllerWithRamp.cpp
@@ -59,10 +59,12 @@ namespace armarx
             ARMARX_CHECK_EXPRESSION(filteredVelocitySensor || velocitySensor);
             if (filteredVelocitySensor)
             {
+                ARMARX_IMPORTANT << "Using filtered velocity for joint " << jointName;
                 velocitySensors.push_back(&filteredVelocitySensor->filteredvelocity);
             }
             else if (velocitySensor)
             {
+                ARMARX_IMPORTANT << "Using raw velocity for joint " << jointName;
                 velocitySensors.push_back(&velocitySensor->velocity);
             }
 
diff --git a/source/RobotAPI/components/units/RobotUnit/RobotUnitModules/RobotUnitModuleControlThread.cpp b/source/RobotAPI/components/units/RobotUnit/RobotUnitModules/RobotUnitModuleControlThread.cpp
index e641b108bf9f034d7e37a7b0e0a007e8d1d7ce9a..227e603433e7ee4e1b9ab193dfd208050294a2e9 100644
--- a/source/RobotAPI/components/units/RobotUnit/RobotUnitModules/RobotUnitModuleControlThread.cpp
+++ b/source/RobotAPI/components/units/RobotUnit/RobotUnitModules/RobotUnitModuleControlThread.cpp
@@ -275,6 +275,7 @@ namespace armarx
             {
                 if (!rtGetActivatedJointControllers().at(i)->rtIsTargetVaild())
                 {
+                    ARMARX_ERROR << "INVALID TARGET: " << rtGetControlDevices().at(i)->getDeviceName();
                     rtDeactivateAssignedNJointControllerBecauseOfError(i, false);
                     oneIsInvalid = true;
                 }
diff --git a/source/RobotAPI/components/units/RobotUnit/RobotUnitModules/RobotUnitModuleControllerManagement.cpp b/source/RobotAPI/components/units/RobotUnit/RobotUnitModules/RobotUnitModuleControllerManagement.cpp
index af602a752cb92a8c306585598287a7c06868d9c7..cae190c728f98344cac595f9ef79f9f5483ee652 100644
--- a/source/RobotAPI/components/units/RobotUnit/RobotUnitModules/RobotUnitModuleControllerManagement.cpp
+++ b/source/RobotAPI/components/units/RobotUnit/RobotUnitModules/RobotUnitModuleControllerManagement.cpp
@@ -131,7 +131,7 @@ namespace armarx
         void ControllerManagement::deleteNJointController(const NJointControllerPtr& ctrl)
         {
             throwIfInControlThread(BOOST_CURRENT_FUNCTION);
-            deleteNJointControllers({ctrl});
+            deleteNJointControllers(std::vector<NJointControllerPtr> {ctrl});
         }
 
         StringNJointControllerPrxDictionary ControllerManagement::getAllNJointControllers(const Ice::Current&) const
@@ -289,7 +289,7 @@ namespace armarx
         void ControllerManagement::activateNJointController(const NJointControllerPtr& ctrl)
         {
             throwIfInControlThread(BOOST_CURRENT_FUNCTION);
-            activateNJointControllers({ctrl});
+            activateNJointControllers(std::vector<NJointControllerPtr> {ctrl});
         }
         void ControllerManagement::activateNJointControllers(const std::vector<NJointControllerPtr>& ctrlsToActVec)
         {
@@ -388,7 +388,7 @@ namespace armarx
         void ControllerManagement::deactivateNJointController(const NJointControllerPtr& ctrl)
         {
             throwIfInControlThread(BOOST_CURRENT_FUNCTION);
-            deactivateNJointControllers({ctrl});
+            deactivateNJointControllers(std::vector<NJointControllerPtr> {ctrl});
         }
         void ControllerManagement::deactivateNJointControllers(const std::vector<NJointControllerPtr>& ctrlsDeacVec)
         {
diff --git a/source/RobotAPI/components/units/RobotUnit/RobotUnitModules/RobotUnitModuleControllerManagement.h b/source/RobotAPI/components/units/RobotUnit/RobotUnitModules/RobotUnitModuleControllerManagement.h
index 08d197d027d251d6df530cf2ba1d44f8c3367d5f..6530e53c19e35a6b9258eb8b12063ddae6ecc8a7 100644
--- a/source/RobotAPI/components/units/RobotUnit/RobotUnitModules/RobotUnitModuleControllerManagement.h
+++ b/source/RobotAPI/components/units/RobotUnit/RobotUnitModules/RobotUnitModuleControllerManagement.h
@@ -69,13 +69,13 @@ namespace armarx
              * @return A proxy to the \ref NJointController.
              * @see getAllNJointControllers
              */
-            NJointControllerInterfacePrx getNJointController(const std::string& name, const Ice::Current&) const override;
+            NJointControllerInterfacePrx getNJointController(const std::string& name, const Ice::Current& = GlobalIceCurrent) const override;
             /**
              * @brief Returns proxies to all \ref NJointController "NJointControllers"
              * @return Proxies to all \ref NJointController "NJointControllers"
              * @see getNJointController
              */
-            StringNJointControllerPrxDictionary getAllNJointControllers(const Ice::Current&) const override;
+            StringNJointControllerPrxDictionary getAllNJointControllers(const Ice::Current& = GlobalIceCurrent) const override;
 
             /**
              * @brief Returns the status of the \ref NJointController.
@@ -95,7 +95,7 @@ namespace armarx
              * @see getNJointControllerDescriptionWithStatus
              * @see getNJointControllerDescriptionsWithStatuses
              */
-            NJointControllerStatusSeq getNJointControllerStatuses(const Ice::Current&) const override;
+            NJointControllerStatusSeq getNJointControllerStatuses(const Ice::Current& = GlobalIceCurrent) const override;
 
             /**
              * @brief Returns the description of the \ref NJointController.
@@ -116,7 +116,7 @@ namespace armarx
              * @see getNJointControllerDescriptionsWithStatuses
              */
 
-            NJointControllerDescriptionSeq getNJointControllerDescriptions(const Ice::Current&) const override;
+            NJointControllerDescriptionSeq getNJointControllerDescriptions(const Ice::Current& = GlobalIceCurrent) const override;
 
             /**
              * @brief Returns the status and description of the \ref NJointController.
@@ -143,7 +143,7 @@ namespace armarx
              * @see getNJointControllerDescription
              * @see getNJointControllerDescriptions
              */
-            NJointControllerDescriptionWithStatusSeq getNJointControllerDescriptionsWithStatuses(const Ice::Current&) const override;
+            NJointControllerDescriptionWithStatusSeq getNJointControllerDescriptionsWithStatuses(const Ice::Current& = GlobalIceCurrent) const override;
 
             /**
              * @brief getNJointControllerClassDescription
@@ -156,7 +156,7 @@ namespace armarx
              * @brief getNJointControllerClassDescriptions
              * @return
              */
-            NJointControllerClassDescriptionSeq getNJointControllerClassDescriptions(const Ice::Current&) const override;
+            NJointControllerClassDescriptionSeq getNJointControllerClassDescriptions(const Ice::Current& = GlobalIceCurrent) const override;
             /**
              * @brief Loads the given lib. (calls `getArmarXManager()->loadLibFromPath(path)`)
              * @param path Path to the lib to load.
@@ -200,7 +200,7 @@ namespace armarx
              * @see nJointControllersToBeDeleted
              * @see deleteNJointControllers
              */
-            void deleteNJointController(const std::string& name, const Ice::Current&) override;
+            void deleteNJointController(const std::string& name, const Ice::Current& = GlobalIceCurrent) override;
             /**
              * @brief Queues the given \ref NJointController "NJointControllers" for deletion.
              * @param names The \ref NJointController "NJointControllers" to delete.
@@ -208,7 +208,7 @@ namespace armarx
              * @see nJointControllersToBeDeleted
              * @see deleteNJointController
              */
-            void deleteNJointControllers(const Ice::StringSeq& names, const Ice::Current&) override;
+            void deleteNJointControllers(const Ice::StringSeq& names, const Ice::Current& = GlobalIceCurrent) override;
             /**
              * @brief Queues the given \ref NJointController for deletion and deactivates it if necessary.
              * @param name The \ref NJointController to delete.
@@ -218,7 +218,7 @@ namespace armarx
              * @see deleteNJointControllers
              * @see deactivateAnddeleteNJointControllers
              */
-            void deactivateAndDeleteNJointController(const std::string& name, const Ice::Current&) override;
+            void deactivateAndDeleteNJointController(const std::string& name, const Ice::Current& = GlobalIceCurrent) override;
             /**
              * @brief Queues the given \ref NJointController "NJointControllers" for deletion and deactivates them if necessary.
              * @param names The \ref NJointController "NJointControllers" to delete.
@@ -235,26 +235,26 @@ namespace armarx
              * @param name The requested \ref NJointController.
              * @see activateNJointControllers
              */
-            void activateNJointController(const std::string& name, const Ice::Current&) override;
+            void activateNJointController(const std::string& name, const Ice::Current& = GlobalIceCurrent) override;
             /**
              * @brief Requests activation for the given \ref NJointController "NJointControllers".
              * @param names The requested \ref NJointController "NJointControllers".
              * @see activateNJointController
              */
-            void activateNJointControllers(const Ice::StringSeq& names, const Ice::Current&) override;
+            void activateNJointControllers(const Ice::StringSeq& names, const Ice::Current& = GlobalIceCurrent) override;
 
             /**
              * @brief Requests deactivation for the given \ref NJointController.
              * @param name The \ref NJointController to be deactivated.
              * @see deactivateNJointControllers
              */
-            void deactivateNJointController(const std::string& name, const Ice::Current&) override;
+            void deactivateNJointController(const std::string& name, const Ice::Current& = GlobalIceCurrent) override;
             /**
              * @brief Requests deactivation for the given \ref NJointController "NJointControllers".
              * @param names The \ref NJointController "NJointControllers" to be deactivated.
              * @see deactivateNJointController
              */
-            void deactivateNJointControllers(const Ice::StringSeq& names, const Ice::Current&) override;
+            void deactivateNJointControllers(const Ice::StringSeq& names, const Ice::Current& = GlobalIceCurrent) override;
 
             /**
              * @brief Cretes a \ref NJointController.
@@ -265,7 +265,7 @@ namespace armarx
              */
             NJointControllerInterfacePrx createNJointController(
                 const std::string& className, const std::string& instanceName,
-                const NJointControllerConfigPtr& config, const Ice::Current&) override;
+                const NJointControllerConfigPtr& config, const Ice::Current& = GlobalIceCurrent) override;
             /**
              * @brief Cretes a \ref NJointController.
              * @param className The \ref NJointController's class.
@@ -275,7 +275,7 @@ namespace armarx
              */
             NJointControllerInterfacePrx createNJointControllerFromVariantConfig(
                 const std::string& className, const std::string& instanceName,
-                const StringVariantBaseMap& variants, const Ice::Current&) override;
+                const StringVariantBaseMap& variants, const Ice::Current& = GlobalIceCurrent) override;
 
             /**
              * @brief Changes the set of requested \ref NJointController "NJointControllers" to the given set.
diff --git a/source/RobotAPI/components/units/RobotUnit/RobotUnitModules/RobotUnitModuleUnits.cpp b/source/RobotAPI/components/units/RobotUnit/RobotUnitModules/RobotUnitModuleUnits.cpp
index 992fc75721a477248d2c47496e8ea27e3ce3185b..3d71420100273fb9843222dbadc07a3ed154a9f9 100644
--- a/source/RobotAPI/components/units/RobotUnit/RobotUnitModules/RobotUnitModuleUnits.cpp
+++ b/source/RobotAPI/components/units/RobotUnit/RobotUnitModules/RobotUnitModuleUnits.cpp
@@ -444,7 +444,7 @@ namespace armarx
             auto guard = getGuard();
             throwIfStateIsNot(RobotUnitState::InitializingUnits, __FUNCTION__);
 
-            if (!getProperty<bool>("CreateTrajectoryPlayer").getValue())
+            if (!getProperty<bool>("CreateTCPControlUnit").getValue())
             {
                 return;
             }
diff --git a/source/RobotAPI/components/units/RobotUnit/Units/TCPControllerSubUnit.cpp b/source/RobotAPI/components/units/RobotUnit/Units/TCPControllerSubUnit.cpp
index 572a2e77c8433f3d20fbe7a5c8bde1dde71260d3..7ac788f054c7e51a56f1ffa8a030231bf582a311 100644
--- a/source/RobotAPI/components/units/RobotUnit/Units/TCPControllerSubUnit.cpp
+++ b/source/RobotAPI/components/units/RobotUnit/Units/TCPControllerSubUnit.cpp
@@ -24,6 +24,8 @@
 
 #include <RobotAPI/libraries/core/FramedPose.h>
 
+#include <RobotAPI/components/units/RobotUnit/NJointControllers/NJointCartesianVelocityController.h>
+
 using namespace armarx;
 
 void TCPControllerSubUnit::update(const SensorAndControl& sc, const JointAndNJointControllers& c)
@@ -31,6 +33,11 @@ void TCPControllerSubUnit::update(const SensorAndControl& sc, const JointAndNJoi
 
 }
 
+PropertyDefinitionsPtr TCPControllerSubUnit::createPropertyDefinitions()
+{
+    return PropertyDefinitionsPtr(new TCPControllerSubUnitPropertyDefinitions(getConfigIdentifier()));
+}
+
 void TCPControllerSubUnit::setup(RobotUnit* rUnit, VirtualRobot::RobotPtr robot)
 {
     ARMARX_CHECK_EXPRESSION(robot);
@@ -62,11 +69,11 @@ void TCPControllerSubUnit::setTCPVelocity(const std::string& nodeSetName, const
     }
 
     auto activeNJointControllers = robotUnit->getNJointControllersNotNull(robotUnit->getNJointControllerNames());
-    NJointTCPControllerPtr tcpController;
+    NJointCartesianVelocityControllerPtr tcpController;
     bool nodeSetAlreadyControlled = false;
     for (NJointControllerPtr controller : activeNJointControllers)
     {
-        tcpController = NJointTCPControllerPtr::dynamicCast(controller);
+        tcpController = NJointCartesianVelocityControllerPtr::dynamicCast(controller);
         if (!tcpController)
         {
             continue;
@@ -77,19 +84,6 @@ void TCPControllerSubUnit::setTCPVelocity(const std::string& nodeSetName, const
             break;
         }
     }
-
-    if (!nodeSetAlreadyControlled)
-    {
-        NJointTCPControllerConfigPtr config = new NJointTCPControllerConfig(nodeSetName, tcp);
-        NJointTCPControllerPtr ctrl = NJointTCPControllerPtr::dynamicCast(
-                                          robotUnit->createNJointController(
-                                              "NJointTCPController", this->getName() + "_" + tcp + "_" + nodeSetName,
-                                              config, true, true
-                                          )
-                                      );
-        tcpController = ctrl;
-    }
-
     robotUnit->updateVirtualRobot(coordinateTransformationRobot);
 
     float xVel = 0.f;
@@ -98,7 +92,7 @@ void TCPControllerSubUnit::setTCPVelocity(const std::string& nodeSetName, const
     float rollVel = 0.f;
     float pitchVel = 0.f;
     float yawVel = 0.f;
-    VirtualRobot::IKSolver::CartesianSelection mode = VirtualRobot::IKSolver::All;
+
 
     FramedDirectionPtr globalTransVel = FramedDirectionPtr::dynamicCast(translationVelocity);
     if (globalTransVel)
@@ -119,39 +113,90 @@ void TCPControllerSubUnit::setTCPVelocity(const std::string& nodeSetName, const
 
     }
 
+    NJointCartesianVelocityControllerMode::CartesianSelection mode = NJointCartesianVelocityControllerMode::eAll;
     bool noMode = false;
     if (globalTransVel && globalOriVel)
     {
-        mode = VirtualRobot::IKSolver::All;
+        mode = NJointCartesianVelocityControllerMode::eAll;
     }
     else if (globalTransVel && !globalOriVel)
     {
-        mode = VirtualRobot::IKSolver::Position;
+        mode = NJointCartesianVelocityControllerMode::ePosition;
     }
     else if (!globalTransVel && globalOriVel)
     {
-        mode = VirtualRobot::IKSolver::Orientation;
+        mode = NJointCartesianVelocityControllerMode::eOrientation;
     }
     else
     {
         noMode = true;
     }
+    ARMARX_DEBUG << "CartesianSelection-Mode: " << (int)mode;
+
+    auto controllerName = this->getName() + "_" + tcp + "_" + nodeSetName;
+    if (!nodeSetAlreadyControlled)
+    {
+        NJointCartesianVelocityControllerConfigPtr config = new NJointCartesianVelocityControllerConfig(nodeSetName, tcp, mode);
+        NJointCartesianVelocityControllerPtr ctrl = NJointCartesianVelocityControllerPtr::dynamicCast(
+                    robotUnit->createNJointController(
+                        "NJointCartesianVelocityController", controllerName,
+                        config, true, true
+                    )
+                );
+
+        tcpController = ctrl;
+        tcpController->setAvoidJointLimitsKp(getProperty<float>("AvoidJointLimitsKp").getValue());
+    }
+
 
-    ARMARX_DEBUG << "CartesianSelection-Mode: " << mode;
 
     // Only activate controller if at least either translationVelocity or orientaionVelocity is set
     if (!noMode)
     {
         ARMARX_CHECK_EXPRESSION(tcpController);
-        tcpController->setVelocities(xVel, yVel, zVel, rollVel, pitchVel, yawVel, mode);
+        //        ARMARX_CHECK_EXPRESSION(tcpController->getObjectScheduler());
+        tcpController->setVelocities(xVel, yVel, zVel, rollVel, pitchVel, yawVel, NJointCartesianVelocityController::ModeFromIce(mode));
+        //        if (!tcpController->getObjectScheduler()->waitForObjectStateMinimum(eManagedIceObjectStarted, 5000))
+        //        {
+        //            ARMARX_ERROR << "NJointController was not initialized after 5000ms - bailing out!";
+        //            return;
+        //        }
         if (!tcpController->isControllerActive())
         {
-            robotUnit->activateNJointController(tcpController);
+            robotUnit->activateNJointController(controllerName);
         }
     }
 }
 
 bool TCPControllerSubUnit::isRequested(const Ice::Current&)
 {
-    return true;
+    auto activeNJointControllers = robotUnit->getNJointControllersNotNull(robotUnit->getNJointControllerNames());
+    for (NJointControllerPtr controller : activeNJointControllers)
+    {
+        auto tcpController = NJointCartesianVelocityControllerPtr::dynamicCast(controller);
+        if (!tcpController)
+        {
+            return true;
+        }
+    }
+
+    return false;
+}
+
+
+void armarx::TCPControllerSubUnit::icePropertiesUpdated(const std::set<std::string>& changedProperties)
+{
+    if (changedProperties.count("AvoidJointLimitsKp") && robotUnit)
+    {
+        float avoidJointLimitsKp = getProperty<float>("AvoidJointLimitsKp").getValue();
+        auto activeNJointControllers = robotUnit->getNJointControllersNotNull(robotUnit->getNJointControllerNames());
+        for (NJointControllerPtr controller : activeNJointControllers)
+        {
+            auto tcpController = NJointCartesianVelocityControllerPtr::dynamicCast(controller);
+            if (tcpController)
+            {
+                tcpController->setAvoidJointLimitsKp(avoidJointLimitsKp);
+            }
+        }
+    }
 }
diff --git a/source/RobotAPI/components/units/RobotUnit/Units/TCPControllerSubUnit.h b/source/RobotAPI/components/units/RobotUnit/Units/TCPControllerSubUnit.h
index 2dd3c3c6f3a5a6922fe47dcd99777b40bcb08797..cd87b0fdcfb6f68f08b25098cd72536f83299c4b 100644
--- a/source/RobotAPI/components/units/RobotUnit/Units/TCPControllerSubUnit.h
+++ b/source/RobotAPI/components/units/RobotUnit/Units/TCPControllerSubUnit.h
@@ -31,6 +31,15 @@
 namespace armarx
 {
     TYPEDEF_PTRS_HANDLE(RobotUnit);
+    class TCPControllerSubUnitPropertyDefinitions : public armarx::ComponentPropertyDefinitions
+    {
+    public:
+        TCPControllerSubUnitPropertyDefinitions(std::string prefix):
+            armarx::ComponentPropertyDefinitions(prefix)
+        {
+            defineOptionalProperty<float>("AvoidJointLimitsKp", 1.f, "Proportional gain value of P-Controller for joint limit avoidance", PropertyDefinitionBase::eModifiable);
+        }
+    };
 
     TYPEDEF_PTRS_HANDLE(TCPControllerSubUnit);
     class TCPControllerSubUnit :
@@ -50,7 +59,7 @@ namespace armarx
         void update(const SensorAndControl& sc, const JointAndNJointControllers& c) override;
     private:
         //        mutable std::mutex dataMutex;
-        RobotUnit* robotUnit = NULL;
+        RobotUnit* robotUnit = nullptr;
         VirtualRobot::RobotPtr coordinateTransformationRobot;
 
         // ManagedIceObject interface
@@ -62,6 +71,9 @@ namespace armarx
             return "TCPControlUnit";
         }
 
+
+        PropertyDefinitionsPtr createPropertyDefinitions() override;
+
         // UnitResourceManagementInterface interface
     public:
         void request(const Ice::Current&) override
@@ -91,5 +103,9 @@ namespace armarx
         void reportJointCurrents(const NameValueMap&, Ice::Long, bool, const Ice::Current&) override {}
         void reportJointMotorTemperatures(const NameValueMap&, Ice::Long, bool, const Ice::Current&) override {}
         void reportJointStatuses(const NameStatusMap&, Ice::Long, bool, const Ice::Current&) override {}
+
+        // PropertyUser interface
+    public:
+        void icePropertiesUpdated(const std::set<std::string>& changedProperties) override;
     };
 }
diff --git a/source/RobotAPI/components/units/RobotUnit/util/RtTiming.h b/source/RobotAPI/components/units/RobotUnit/util/RtTiming.h
new file mode 100644
index 0000000000000000000000000000000000000000..65cf13a5717de73e70769603d6188011a8ceaa57
--- /dev/null
+++ b/source/RobotAPI/components/units/RobotUnit/util/RtTiming.h
@@ -0,0 +1,54 @@
+/*
+ * This file is part of ArmarX.
+ *
+ * Copyright (C) 2011-2017, High Performance Humanoid Technologies (H2T), Karlsruhe Institute of Technology (KIT), all rights reserved.
+ *
+ * ArmarX is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * ArmarX is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * @package    ArmarX
+ * @author     Mirko Waechter( mirko.waechter at kit dot edu)
+ * @date       2018
+ * @copyright  http://www.gnu.org/licenses/gpl-2.0.txt
+ *             GNU General Public License
+ */
+#pragma once
+
+#include <chrono>
+//#include <ArmarXCore/core/time/TimeUtil.h>
+#include "ControlThreadOutputBuffer.h"
+
+namespace armarx
+{
+    inline IceUtil::Time rtNow()
+    {
+        using namespace std::chrono;
+        auto epoch = time_point_cast<microseconds>(high_resolution_clock::now()).time_since_epoch();
+        return IceUtil::Time::microSeconds(duration_cast<milliseconds>(epoch).count());
+    }
+}
+
+#define RT_TIMING_START(name) auto name = armarx::rtNow();
+//! \ingroup VirtualTime
+//! Prints duration with comment in front of it, yet only once per second.
+#define RT_TIMING_END_COMMENT(name, comment) ARMARX_RT_LOGF_INFO("%s - duration: %.3f ms", comment, IceUtil::Time(armarx::rtNow()-name).toMilliSecondsDouble()).deactivateSpam(1);
+//! \ingroup VirtualTime
+//! Prints duration
+#define RT_TIMING_END(name) RT_TIMING_END_COMMENT(name,#name)
+//! \ingroup VirtualTime
+//! Prints duration with comment in front of it if it took longer than threshold
+#define RT_TIMING_CEND_COMMENT(name, comment, thresholdMs) if((armarx::rtNow()-name).toMilliSecondsDouble() >= thresholdMs) RT_TIMING_END_COMMENT(name, comment)
+//! \ingroup VirtualTime
+//! Prints duration if it took longer than thresholdMs
+#define RT_TIMING_CEND(name, thresholdMs) RT_TIMING_CEND_COMMENT(name, #name, thresholdMs)
+
+
diff --git a/source/RobotAPI/interface/core/FramedPoseBase.ice b/source/RobotAPI/interface/core/FramedPoseBase.ice
index 41f3d684ae1329c62a3d6ab28a774674cedc7c84..b4947429a1e360c808a896b6cf38bd8008259f87 100644
--- a/source/RobotAPI/interface/core/FramedPoseBase.ice
+++ b/source/RobotAPI/interface/core/FramedPoseBase.ice
@@ -116,5 +116,14 @@ module armarx
     };
 
 
+    /**
+    * PoseAverageFilterBase filters poses with an average filter.
+    */
+    ["cpp:virtual"]
+    class PoseAverageFilterBase extends AverageFilterBase
+    {
+
+    };
+
 };
 
diff --git a/source/RobotAPI/interface/units/RobotUnit/NJointTaskSpaceDMPController.ice b/source/RobotAPI/interface/units/RobotUnit/NJointTaskSpaceDMPController.ice
index ac949e0e7eb4aa0898ad8a0b3c5613dfcca9b962..d3d62e88d8e4bb28a2b3da115ed570abaa308c71 100644
--- a/source/RobotAPI/interface/units/RobotUnit/NJointTaskSpaceDMPController.ice
+++ b/source/RobotAPI/interface/units/RobotUnit/NJointTaskSpaceDMPController.ice
@@ -185,6 +185,8 @@ module armarx
 
         float torqueLimit;
 
+        float startReduceTorque;
+
 //        Ice::FloatSeq Kpf;
 //        Ice::FloatSeq Kif;
 //        Ice::FloatSeq DesiredForce;
@@ -212,5 +214,55 @@ module armarx
 
 
     };
+
+    class NJointTaskSpaceImpedanceDMPControllerConfig extends NJointControllerConfig
+    {
+
+        // dmp configuration
+        int kernelSize = 100;
+        string dmpMode = "MinimumJerk";
+        string dmpType = "Discrete";
+        double timeDuration;
+        string nodeSetName;
+
+        // phaseStop technique
+        double phaseL = 10;
+        double phaseK = 10;
+        double phaseDist0 = 50;
+        double phaseDist1 = 10;
+        double posToOriRatio = 100;
+
+        Ice::FloatSeq Kpos;
+        Ice::FloatSeq Dpos;
+        Ice::FloatSeq Kori;
+        Ice::FloatSeq Dori;
+
+        float Knull;
+        float Dnull;
+
+
+
+        bool useNullSpaceJointDMP;
+        Ice::FloatSeq defaultNullSpaceJointValues;
+
+        float torqueLimit;
+
+    };
+
+    interface NJointTaskSpaceImpedanceDMPControllerInterface extends NJointControllerInterface
+    {
+        void learnDMPFromFiles(Ice::StringSeq trajfiles);
+        void learnJointDMPFromFiles(string jointTrajFile);
+
+        bool isFinished();
+        void runDMP(Ice::DoubleSeq goals);
+
+        void setViaPoints(double canVal, Ice::DoubleSeq point);
+        void setGoals(Ice::DoubleSeq goals);
+
+        double getVirtualTime();
+
+    };
+
 };
 
diff --git a/source/RobotAPI/libraries/DMPController/TaskSpaceDMPController.cpp b/source/RobotAPI/libraries/DMPController/TaskSpaceDMPController.cpp
index 462493dfb858a6b15d643f44da4ddf34a5da3ed8..425a9abf8412506f0c598b4167cdce30720baee1 100644
--- a/source/RobotAPI/libraries/DMPController/TaskSpaceDMPController.cpp
+++ b/source/RobotAPI/libraries/DMPController/TaskSpaceDMPController.cpp
@@ -88,10 +88,10 @@ void TaskSpaceDMPController::flow(double deltaT, const Eigen::Matrix4f& currentP
 
     currentState = dmpPtr->calculateDirectlyVelocity(currentState, canVal / timeDuration, deltaT / timeDuration, targetPoseVec);
 
-//    for (size_t i = 0; i < 7; ++i)
-//    {
-//        targetPoseVec[i] = currentState[i].pos;
-//    }
+    //    for (size_t i = 0; i < 7; ++i)
+    //    {
+    //        targetPoseVec[i] = currentState[i].pos;
+    //    }
 
 
     if (isPhaseStopControl)
@@ -136,7 +136,11 @@ void TaskSpaceDMPController::flow(double deltaT, const Eigen::Matrix4f& currentP
 
 
     double angularChange =  angularVel0.angularDistance(oldDMPAngularVelocity);
-    if (angularVel0.w() > 0 && oldDMPAngularVelocity.w() < 0 && angularChange < 1e-2)
+    if (angularVel0.w() * oldDMPAngularVelocity.w() < 0 &&
+        angularVel0.x() * oldDMPAngularVelocity.x() < 0 &&
+        angularVel0.y() * oldDMPAngularVelocity.y() < 0 &&
+        angularVel0.z() * oldDMPAngularVelocity.z() < 0 &&
+        angularChange < 1e-2)
     {
         angularVel0.w() = - angularVel0.w();
         angularVel0.x() = - angularVel0.x();
diff --git a/source/RobotAPI/libraries/RobotAPINJointControllers/CMakeLists.txt b/source/RobotAPI/libraries/RobotAPINJointControllers/CMakeLists.txt
index bbef6320f875fb4b58c9980cbb209a4cd1c9884a..a8b163ccb60447b1d687988c9d3d365ffa3858f9 100644
--- a/source/RobotAPI/libraries/RobotAPINJointControllers/CMakeLists.txt
+++ b/source/RobotAPI/libraries/RobotAPINJointControllers/CMakeLists.txt
@@ -46,6 +46,7 @@ if (DMP_FOUND )
            DMPController/NJointTSDMPController.h
            DMPController/NJointCCDMPController.h
            DMPController/NJointBimanualCCDMPController.h
+           DMPController/NJointTaskSpaceImpedanceDMPController.h
 
            )
     list(APPEND LIB_FILES
@@ -54,7 +55,7 @@ if (DMP_FOUND )
            DMPController/NJointTSDMPController.cpp
            DMPController/NJointCCDMPController.cpp
            DMPController/NJointBimanualCCDMPController.cpp
-
+           DMPController/NJointTaskSpaceImpedanceDMPController.cpp
            )
 
     list(APPEND LIBS ${DMP_LIBRARIES} DMPController)
diff --git a/source/RobotAPI/libraries/RobotAPINJointControllers/DMPController/NJointBimanualCCDMPController.cpp b/source/RobotAPI/libraries/RobotAPINJointControllers/DMPController/NJointBimanualCCDMPController.cpp
index 2563140cbc25077ea7a71edf91f193adf40e5e54..bd4aabafd75ee1b243147281b3f692836bf7dc34 100644
--- a/source/RobotAPI/libraries/RobotAPINJointControllers/DMPController/NJointBimanualCCDMPController.cpp
+++ b/source/RobotAPI/libraries/RobotAPINJointControllers/DMPController/NJointBimanualCCDMPController.cpp
@@ -13,10 +13,18 @@ namespace armarx
         useSynchronizedRtRobot();
 
         leftRNS = rtGetRobot()->getRobotNodeSet("LeftArm");
+        leftNullSpaceCoefs.resize(leftRNS->getSize());
+        leftNullSpaceCoefs.setOnes();
+
         for (size_t i = 0; i < leftRNS->getSize(); ++i)
         {
             std::string jointName = leftRNS->getNode(i)->getName();
 
+            if (leftRNS->getNode(i)->isLimitless())
+            {
+                leftNullSpaceCoefs(i) = 0;
+            }
+
             leftJointNames.push_back(jointName);
             ControlTargetBase* ct = useControlTarget(jointName, ControlModes::Torque1DoF);
             const SensorValueBase* sv = useSensorValue(jointName);
@@ -46,9 +54,18 @@ namespace armarx
 
         };
         rightRNS = rtGetRobot()->getRobotNodeSet("RightArm");
+
+        rightNullSpaceCoefs.resize(rightRNS->getSize());
+        rightNullSpaceCoefs.setOnes();
         for (size_t i = 0; i < rightRNS->getSize(); ++i)
         {
             std::string jointName = rightRNS->getNode(i)->getName();
+
+            if (rightRNS->getNode(i)->isLimitless())
+            {
+                rightNullSpaceCoefs(i) = 0;
+            }
+
             rightJointNames.push_back(jointName);
             ControlTargetBase* ct = useControlTarget(jointName, ControlModes::Torque1DoF);
             const SensorValueBase* sv = useSensorValue(jointName);
@@ -135,6 +152,9 @@ namespace armarx
         initData.leftTargetVel.setZero();
         initData.rightTargetVel.resize(6);
         initData.rightTargetVel.setZero();
+        initData.leftTargetPose = tcpLeft->getPoseInRootFrame();
+        initData.rightTargetPose = tcpRight->getPoseInRootFrame();
+        initData.virtualTime = cfg->timeDuration;
         reinitTripleBuffer(initData);
 
         leftDesiredJointValues.resize(leftTargets.size());
@@ -159,6 +179,10 @@ namespace armarx
         leftKori << cfg->leftKori[0], cfg->leftKori[1], cfg->leftKori[2];
         leftDori << cfg->leftDori[0], cfg->leftDori[1], cfg->leftDori[2];
 
+        rightKpos << cfg->rightKpos[0], cfg->rightKpos[1], cfg->rightKpos[2];
+        rightDpos << cfg->rightDpos[0], cfg->rightDpos[1], cfg->rightDpos[2];
+        rightKori << cfg->rightKori[0], cfg->rightKori[1], cfg->rightKori[2];
+        rightDori << cfg->rightDori[0], cfg->rightDori[1], cfg->rightDori[2];
 
         knull = cfg->knull;
         dnull = cfg->dnull;
@@ -170,7 +194,8 @@ namespace armarx
         maxLinearVel = cfg->maxLinearVel;
         maxAngularVel = cfg->maxAngularVel;
 
-
+        torqueFactor = 1.0;
+        startReduceTorque = cfg->startReduceTorque;
     }
 
     std::string NJointBimanualCCDMPController::getClassName(const Ice::Current&) const
@@ -245,7 +270,7 @@ namespace armarx
         TaskSpaceDMPControllerPtr followerDMP = currentControlGroup[1];
         virtualtimer = leaderDMP->canVal;
 
-        if(virtualtimer < 1e-8)
+        if (virtualtimer < 1e-8)
         {
             finished = true;
         }
@@ -482,36 +507,36 @@ namespace armarx
 
 
 
-//        Eigen::VectorXf leftJointLimitAvoidance(leftRNS->getSize());
-//        for (size_t i = 0; i < leftRNS->getSize(); i++)
-//        {
-//            VirtualRobot::RobotNodePtr rn = leftRNS->getNode(i);
-//            if (rn->isLimitless())
-//            {
-//                leftJointLimitAvoidance(i) = 0;
-//            }
-//            else
-//            {
-//                float f = math::MathUtils::ILerp(rn->getJointLimitLo(), rn->getJointLimitHi(), rn->getJointValue());
-//                leftJointLimitAvoidance(i) = cos(f * M_PI);
-//            }
-//        }
-//        Eigen::VectorXf leftNullspaceTorque = knull * leftJointLimitAvoidance - dnull * leftqvel;
-//        Eigen::VectorXf rightJointLimitAvoidance(rightRNS->getSize());
-//        for (size_t i = 0; i < rightRNS->getSize(); i++)
-//        {
-//            VirtualRobot::RobotNodePtr rn = rightRNS->getNode(i);
-//            if (rn->isLimitless())
-//            {
-//                rightJointLimitAvoidance(i) = 0;
-//            }
-//            else
-//            {
-//                float f = math::MathUtils::ILerp(rn->getJointLimitLo(), rn->getJointLimitHi(), rn->getJointValue());
-//                rightJointLimitAvoidance(i) = cos(f * M_PI);
-//            }
-//        }
-//        Eigen::VectorXf rightNullspaceTorque = knull * rightJointLimitAvoidance - dnull * rightqvel;
+        //        Eigen::VectorXf leftJointLimitAvoidance(leftRNS->getSize());
+        //        for (size_t i = 0; i < leftRNS->getSize(); i++)
+        //        {
+        //            VirtualRobot::RobotNodePtr rn = leftRNS->getNode(i);
+        //            if (rn->isLimitless())
+        //            {
+        //                leftJointLimitAvoidance(i) = 0;
+        //            }
+        //            else
+        //            {
+        //                float f = math::MathUtils::ILerp(rn->getJointLimitLo(), rn->getJointLimitHi(), rn->getJointValue());
+        //                leftJointLimitAvoidance(i) = cos(f * M_PI);
+        //            }
+        //        }
+        //        Eigen::VectorXf leftNullspaceTorque = knull * leftJointLimitAvoidance - dnull * leftqvel;
+        //        Eigen::VectorXf rightJointLimitAvoidance(rightRNS->getSize());
+        //        for (size_t i = 0; i < rightRNS->getSize(); i++)
+        //        {
+        //            VirtualRobot::RobotNodePtr rn = rightRNS->getNode(i);
+        //            if (rn->isLimitless())
+        //            {
+        //                rightJointLimitAvoidance(i) = 0;
+        //            }
+        //            else
+        //            {
+        //                float f = math::MathUtils::ILerp(rn->getJointLimitLo(), rn->getJointLimitHi(), rn->getJointValue());
+        //                rightJointLimitAvoidance(i) = cos(f * M_PI);
+        //            }
+        //        }
+        //        Eigen::VectorXf rightNullspaceTorque = knull * rightJointLimitAvoidance - dnull * rightqvel;
 
 
         Eigen::VectorXf leftNullspaceTorque = knull * (leftDesiredJointValues - leftqpos) - dnull * leftqvel;
@@ -521,13 +546,20 @@ namespace armarx
 
         Eigen::MatrixXf jtpinvL = leftIK->computePseudoInverseJacobianMatrix(jacobiL.transpose(), lambda);
         Eigen::MatrixXf jtpinvR = rightIK->computePseudoInverseJacobianMatrix(jacobiR.transpose(), lambda);
-        Eigen::VectorXf leftJointDesiredTorques = jacobiL.transpose() * leftJointControlWrench + (I - jacobiL.transpose() * jtpinvL) * leftNullspaceTorque;
-        Eigen::VectorXf rightJointDesiredTorques = jacobiR.transpose() * rightJointControlWrench + (I - jacobiR.transpose() * jtpinvR) * rightNullspaceTorque;
+        Eigen::VectorXf leftJointDesiredTorques = jacobiL.transpose() * leftJointControlWrench + (I - jacobiL.transpose() * jtpinvL) * leftNullSpaceCoefs.cwiseProduct(leftNullspaceTorque);
+        Eigen::VectorXf rightJointDesiredTorques = jacobiR.transpose() * rightJointControlWrench + (I - jacobiR.transpose() * jtpinvR) * rightNullSpaceCoefs.cwiseProduct(rightNullspaceTorque);
+
+
+
+        if (virtualtime < startReduceTorque && startReduceTorque != 0)
+        {
+            torqueFactor -= deltaT / startReduceTorque;
+        }
 
         // torque limit
         for (size_t i = 0; i < leftTargets.size(); ++i)
         {
-            float desiredTorque = leftJointDesiredTorques(i);
+            float desiredTorque = torqueFactor * leftJointDesiredTorques(i);
 
             if (isnan(desiredTorque))
             {
@@ -537,7 +569,7 @@ namespace armarx
             desiredTorque = (desiredTorque >  torqueLimit) ? torqueLimit : desiredTorque;
             desiredTorque = (desiredTorque < -torqueLimit) ? -torqueLimit : desiredTorque;
 
-            debugDataInfo.getWriteBuffer().desired_torques[leftJointNames[i]] = leftJointDesiredTorques(i);
+            debugDataInfo.getWriteBuffer().desired_torques[leftJointNames[i]] = desiredTorque;
 
             leftTargets.at(i)->torque = desiredTorque;
         }
@@ -546,7 +578,7 @@ namespace armarx
 
         for (size_t i = 0; i < rightTargets.size(); ++i)
         {
-            float desiredTorque = rightJointDesiredTorques(i);
+            float desiredTorque = torqueFactor * rightJointDesiredTorques(i);
 
             if (isnan(desiredTorque))
             {
@@ -556,7 +588,7 @@ namespace armarx
             desiredTorque = (desiredTorque >  torqueLimit) ? torqueLimit : desiredTorque;
             desiredTorque = (desiredTorque < -torqueLimit) ? -torqueLimit : desiredTorque;
 
-            debugDataInfo.getWriteBuffer().desired_torques[rightJointNames[i]] = rightJointDesiredTorques(i);
+            debugDataInfo.getWriteBuffer().desired_torques[rightJointNames[i]] = desiredTorque;
 
             rightTargets.at(i)->torque = desiredTorque;
         }
diff --git a/source/RobotAPI/libraries/RobotAPINJointControllers/DMPController/NJointBimanualCCDMPController.h b/source/RobotAPI/libraries/RobotAPINJointControllers/DMPController/NJointBimanualCCDMPController.h
index 9b62d80f6a10a21d917143993c881df08b658c70..3402d5cc0b2426350916353f8a316fa266944166 100644
--- a/source/RobotAPI/libraries/RobotAPINJointControllers/DMPController/NJointBimanualCCDMPController.h
+++ b/source/RobotAPI/libraries/RobotAPINJointControllers/DMPController/NJointBimanualCCDMPController.h
@@ -214,14 +214,6 @@ namespace armarx
         Eigen::VectorXf leftDesiredJointValues;
         Eigen::VectorXf rightDesiredJointValues;
 
-        float KoriFollower;
-        float KposFollower;
-        float DposFollower;
-        float DoriFollower;
-
-        Eigen::VectorXf forceC_des;
-        float boxWidth;
-
         Eigen::Vector3f leftKpos;
         Eigen::Vector3f leftKori;
         Eigen::Vector3f leftDpos;
@@ -243,10 +235,17 @@ namespace armarx
         VirtualRobot::RobotNodeSetPtr leftRNS;
         VirtualRobot::RobotNodeSetPtr rightRNS;
 
+        Eigen::VectorXf leftNullSpaceCoefs;
+        Eigen::VectorXf rightNullSpaceCoefs;
+
+        float torqueFactor;
+        float startReduceTorque;
 
         float maxLinearVel;
         float maxAngularVel;
 
+
+
         // NJointBimanualCCDMPControllerInterface interface
     };
 
diff --git a/source/RobotAPI/libraries/RobotAPINJointControllers/DMPController/NJointTSDMPController.cpp b/source/RobotAPI/libraries/RobotAPINJointControllers/DMPController/NJointTSDMPController.cpp
index 4ce687e3eb4680d31dcdcda379534ade1020e833..4b0e26b6c2a55346b9619b28ca6b0bf27c11a0b0 100644
--- a/source/RobotAPI/libraries/RobotAPINJointControllers/DMPController/NJointTSDMPController.cpp
+++ b/source/RobotAPI/libraries/RobotAPINJointControllers/DMPController/NJointTSDMPController.cpp
@@ -66,7 +66,7 @@ namespace armarx
         taskSpaceDMPConfig.phaseStopParas.maxValue = cfg->phaseL;
         taskSpaceDMPConfig.phaseStopParas.slop = cfg->phaseK;
 
-        taskSpaceDMPController.reset(new TaskSpaceDMPController("default", taskSpaceDMPConfig));
+        taskSpaceDMPController.reset(new TaskSpaceDMPController("default", taskSpaceDMPConfig, false));
 
         // initialize tcp position and orientation
 
@@ -126,35 +126,35 @@ namespace armarx
 
 
         targetPose = taskSpaceDMPController->getTargetPoseMat();
-        //        std::vector<double> targetState = taskSpaceDMPController->getTargetPose();
-        //        debugOutputData.getWriteBuffer().latestTargetVelocities["x_vel"] = targetVels(0);
-        //        debugOutputData.getWriteBuffer().latestTargetVelocities["y_vel"] = targetVels(1);
-        //        debugOutputData.getWriteBuffer().latestTargetVelocities["z_vel"] = targetVels(2);
-        //        debugOutputData.getWriteBuffer().latestTargetVelocities["roll_vel"] = targetVels(3);
-        //        debugOutputData.getWriteBuffer().latestTargetVelocities["pitch_vel"] = targetVels(4);
-        //        debugOutputData.getWriteBuffer().latestTargetVelocities["yaw_vel"] = targetVels(5);
-        //        debugOutputData.getWriteBuffer().dmpTargets["dmp_x"] = targetState[0];
-        //        debugOutputData.getWriteBuffer().dmpTargets["dmp_y"] = targetState[1];
-        //        debugOutputData.getWriteBuffer().dmpTargets["dmp_z"] = targetState[2];
-        //        debugOutputData.getWriteBuffer().dmpTargets["dmp_qw"] = targetState[3];
-        //        debugOutputData.getWriteBuffer().dmpTargets["dmp_qx"] = targetState[4];
-        //        debugOutputData.getWriteBuffer().dmpTargets["dmp_qy"] = targetState[5];
-        //        debugOutputData.getWriteBuffer().dmpTargets["dmp_qz"] = targetState[6];
-        //        debugOutputData.getWriteBuffer().currentPose["currentPose_x"] = currentPose(0, 3);
-        //        debugOutputData.getWriteBuffer().currentPose["currentPose_y"] = currentPose(1, 3);
-        //        debugOutputData.getWriteBuffer().currentPose["currentPose_z"] = currentPose(2, 3);
-
-        //        VirtualRobot::MathTools::Quaternion currentQ = VirtualRobot::MathTools::eigen4f2quat(currentPose);
-        //        debugOutputData.getWriteBuffer().currentPose["currentPose_qw"] = currentQ.w;
-        //        debugOutputData.getWriteBuffer().currentPose["currentPose_qx"] = currentQ.x;
-        //        debugOutputData.getWriteBuffer().currentPose["currentPose_qy"] = currentQ.y;
-        //        debugOutputData.getWriteBuffer().currentPose["currentPose_qz"] = currentQ.z;
+        std::vector<double> targetState = taskSpaceDMPController->getTargetPose();
+        debugOutputData.getWriteBuffer().latestTargetVelocities["x_vel"] = targetVels(0);
+        debugOutputData.getWriteBuffer().latestTargetVelocities["y_vel"] = targetVels(1);
+        debugOutputData.getWriteBuffer().latestTargetVelocities["z_vel"] = targetVels(2);
+        debugOutputData.getWriteBuffer().latestTargetVelocities["roll_vel"] = targetVels(3);
+        debugOutputData.getWriteBuffer().latestTargetVelocities["pitch_vel"] = targetVels(4);
+        debugOutputData.getWriteBuffer().latestTargetVelocities["yaw_vel"] = targetVels(5);
+        debugOutputData.getWriteBuffer().dmpTargets["dmp_x"] = targetState[0];
+        debugOutputData.getWriteBuffer().dmpTargets["dmp_y"] = targetState[1];
+        debugOutputData.getWriteBuffer().dmpTargets["dmp_z"] = targetState[2];
+        debugOutputData.getWriteBuffer().dmpTargets["dmp_qw"] = targetState[3];
+        debugOutputData.getWriteBuffer().dmpTargets["dmp_qx"] = targetState[4];
+        debugOutputData.getWriteBuffer().dmpTargets["dmp_qy"] = targetState[5];
+        debugOutputData.getWriteBuffer().dmpTargets["dmp_qz"] = targetState[6];
+        debugOutputData.getWriteBuffer().currentPose["currentPose_x"] = currentPose(0, 3);
+        debugOutputData.getWriteBuffer().currentPose["currentPose_y"] = currentPose(1, 3);
+        debugOutputData.getWriteBuffer().currentPose["currentPose_z"] = currentPose(2, 3);
+
+        VirtualRobot::MathTools::Quaternion currentQ = VirtualRobot::MathTools::eigen4f2quat(currentPose);
+        debugOutputData.getWriteBuffer().currentPose["currentPose_qw"] = currentQ.w;
+        debugOutputData.getWriteBuffer().currentPose["currentPose_qx"] = currentQ.x;
+        debugOutputData.getWriteBuffer().currentPose["currentPose_qy"] = currentQ.y;
+        debugOutputData.getWriteBuffer().currentPose["currentPose_qz"] = currentQ.z;
         debugOutputData.getWriteBuffer().currentCanVal = taskSpaceDMPController->debugData.canVal;
-        //        debugOutputData.getWriteBuffer().mpcFactor =  taskSpaceDMPController->debugData.mpcFactor;
-        //        debugOutputData.getWriteBuffer().error = taskSpaceDMPController->debugData.poseError;
-        //        debugOutputData.getWriteBuffer().posError = taskSpaceDMPController->debugData.posiError;
-        //        debugOutputData.getWriteBuffer().oriError = taskSpaceDMPController->debugData.oriError;
-        //        debugOutputData.getWriteBuffer().deltaT = deltaT;
+        debugOutputData.getWriteBuffer().mpcFactor =  taskSpaceDMPController->debugData.mpcFactor;
+        debugOutputData.getWriteBuffer().error = taskSpaceDMPController->debugData.poseError;
+        debugOutputData.getWriteBuffer().posError = taskSpaceDMPController->debugData.posiError;
+        debugOutputData.getWriteBuffer().oriError = taskSpaceDMPController->debugData.oriError;
+        debugOutputData.getWriteBuffer().deltaT = deltaT;
 
         debugOutputData.commitWrite();
 
@@ -200,6 +200,7 @@ namespace armarx
         rtTargetVel.resize(6);
         rtTargetVel.block<3, 1>(0, 0) = KpF * (targetPose.block<3, 1>(0, 3) - currentPose.block<3, 1>(0, 3)) + DpF * (targetVel.block<3, 1>(0, 0) - tcptwist.block<3, 1>(0, 0));
         rtTargetVel.block<3, 1>(3, 0) = KoF * errorRPY + DoF * (targetVel.block<3, 1>(3, 0) - tcptwist.block<3, 1>(3, 0));
+        //        rtTargetVel = targetVel;
 
 
         float normLinearVelocity = rtTargetVel.block<3, 1>(0, 0).norm();
@@ -380,40 +381,40 @@ namespace armarx
     {
         std::string datafieldName = debugName;
         StringVariantBaseMap datafields;
-        //        auto values = debugOutputData.getUpToDateReadBuffer().latestTargetVelocities;
-        //        for (auto& pair : values)
-        //        {
-        //            datafieldName = pair.first  + "_" + debugName;
-        //            datafields[datafieldName] = new Variant(pair.second);
-        //        }
-
-        //        auto dmpTargets = debugOutputData.getUpToDateReadBuffer().dmpTargets;
-        //        for (auto& pair : dmpTargets)
-        //        {
-        //            datafieldName = pair.first  + "_" + debugName;
-        //            datafields[datafieldName] = new Variant(pair.second);
-        //        }
-
-        //        auto currentPose = debugOutputData.getUpToDateReadBuffer().currentPose;
-        //        for (auto& pair : currentPose)
-        //        {
-        //            datafieldName = pair.first + "_" + debugName;
-        //            datafields[datafieldName] = new Variant(pair.second);
-        //        }
+        auto values = debugOutputData.getUpToDateReadBuffer().latestTargetVelocities;
+        for (auto& pair : values)
+        {
+            datafieldName = pair.first  + "_" + debugName;
+            datafields[datafieldName] = new Variant(pair.second);
+        }
+
+        auto dmpTargets = debugOutputData.getUpToDateReadBuffer().dmpTargets;
+        for (auto& pair : dmpTargets)
+        {
+            datafieldName = pair.first  + "_" + debugName;
+            datafields[datafieldName] = new Variant(pair.second);
+        }
+
+        auto currentPose = debugOutputData.getUpToDateReadBuffer().currentPose;
+        for (auto& pair : currentPose)
+        {
+            datafieldName = pair.first + "_" + debugName;
+            datafields[datafieldName] = new Variant(pair.second);
+        }
 
         datafieldName = "canVal_" + debugName;
         datafields[datafieldName] = new Variant(debugOutputData.getUpToDateReadBuffer().currentCanVal);
-        //        datafieldName = "mpcFactor_" + debugName;
-        //        datafields[datafieldName] = new Variant(debugOutputData.getUpToDateReadBuffer().mpcFactor);
-        //        datafieldName = "error_" + debugName;
-        //        datafields[datafieldName] = new Variant(debugOutputData.getUpToDateReadBuffer().error);
-        //        datafieldName = "posError_" + debugName;
-        //        datafields[datafieldName] = new Variant(debugOutputData.getUpToDateReadBuffer().posError);
-        //        datafieldName = "oriError_" + debugName;
-        //        datafields[datafieldName] = new Variant(debugOutputData.getUpToDateReadBuffer().oriError);
-        //        datafieldName = "deltaT_" + debugName;
-        //        datafields[datafieldName] = new Variant(debugOutputData.getUpToDateReadBuffer().deltaT);
-        //        datafieldName = "DMPController_" + debugName;
+        datafieldName = "mpcFactor_" + debugName;
+        datafields[datafieldName] = new Variant(debugOutputData.getUpToDateReadBuffer().mpcFactor);
+        datafieldName = "error_" + debugName;
+        datafields[datafieldName] = new Variant(debugOutputData.getUpToDateReadBuffer().error);
+        datafieldName = "posError_" + debugName;
+        datafields[datafieldName] = new Variant(debugOutputData.getUpToDateReadBuffer().posError);
+        datafieldName = "oriError_" + debugName;
+        datafields[datafieldName] = new Variant(debugOutputData.getUpToDateReadBuffer().oriError);
+        datafieldName = "deltaT_" + debugName;
+        datafields[datafieldName] = new Variant(debugOutputData.getUpToDateReadBuffer().deltaT);
+        datafieldName = "DMPController_" + debugName;
 
         debugObs->setDebugChannel(datafieldName, datafields);
     }
diff --git a/source/RobotAPI/libraries/RobotAPINJointControllers/DMPController/NJointTaskSpaceDMPController.cpp b/source/RobotAPI/libraries/RobotAPINJointControllers/DMPController/NJointTaskSpaceDMPController.cpp
deleted file mode 100644
index 0b3858033b0d6b34ae858d1379b34cdc7ccebef8..0000000000000000000000000000000000000000
--- a/source/RobotAPI/libraries/RobotAPINJointControllers/DMPController/NJointTaskSpaceDMPController.cpp
+++ /dev/null
@@ -1,453 +0,0 @@
-#include "NJointTaskSpaceDMPController.h"
-
-namespace armarx
-{
-    NJointControllerRegistration<NJointTaskSpaceDMPController> registrationControllerNJointTaskSpaceDMPController("NJointTaskSpaceDMPController");
-
-    NJointTaskSpaceDMPController::NJointTaskSpaceDMPController(const RobotUnitPtr& robotUnit, const armarx::NJointControllerConfigPtr& config, const VirtualRobot::RobotPtr&)
-    {
-        useSynchronizedRtRobot();
-        cfg = NJointTaskSpaceDMPControllerConfigPtr::dynamicCast(config);
-        ARMARX_CHECK_EXPRESSION(!cfg->nodeSetName.empty());
-        VirtualRobot::RobotNodeSetPtr rns = rtGetRobot()->getRobotNodeSet(cfg->nodeSetName);
-
-        ARMARX_CHECK_EXPRESSION_W_HINT(rns, cfg->nodeSetName);
-        for (size_t i = 0; i < rns->getSize(); ++i)
-        {
-            std::string jointName = rns->getNode(i)->getName();
-            ControlTargetBase* ct = useControlTarget(jointName, ControlModes::Velocity1DoF);
-            const SensorValueBase* sv = useSensorValue(jointName);
-            targets.push_back(ct->asA<ControlTarget1DoFActuatorVelocity>());
-
-            const SensorValue1DoFActuatorTorque* torqueSensor = sv->asA<SensorValue1DoFActuatorTorque>();
-            const SensorValue1DoFGravityTorque* gravityTorqueSensor = sv->asA<SensorValue1DoFGravityTorque>();
-            if (!torqueSensor)
-            {
-                ARMARX_WARNING << "No Torque sensor available for " << jointName;
-            }
-            if (!gravityTorqueSensor)
-            {
-                ARMARX_WARNING << "No Gravity Torque sensor available for " << jointName;
-            }
-
-            torqueSensors.push_back(torqueSensor);
-            gravityTorqueSensors.push_back(gravityTorqueSensor);
-        };
-
-        tcp = (cfg->tcpName.empty()) ? rns->getTCP() : rtGetRobot()->getRobotNode(cfg->tcpName);
-        ARMARX_CHECK_EXPRESSION_W_HINT(tcp, cfg->tcpName);
-
-        // set tcp controller
-        tcpController.reset(new CartesianVelocityController(rns, tcp));
-        nodeSetName = cfg->nodeSetName;
-        torquePIDs.resize(tcpController->rns->getSize(), pidController());
-
-
-        NJointTaskSpaceDMPControllerControlData initData;
-        initData.nullspaceJointVelocities.resize(tcpController->rns->getSize(), 0);
-        initData.torqueKp.resize(tcpController->rns->getSize(), 0);
-        initData.torqueKd.resize(tcpController->rns->getSize(), 0);
-        initData.mode = ModeFromIce(cfg->mode);
-
-        // set DMP
-        dmpPtr.reset(new UMIDMP(cfg->kernelSize, cfg->DMPKd, cfg->baseMode, cfg->tau));
-        timeDuration = cfg->timeDuration;
-        canVal = timeDuration;
-        finished = false;
-
-        initData.dmpPtr = dmpPtr;
-        initData.isStart = false;
-        reinitTripleBuffer(initData);
-
-
-        isDisturbance = false;
-        phaseL = cfg->phaseL;
-        phaseK = cfg->phaseK;
-        phaseDist0 = cfg->phaseDist0;
-        phaseDist1 = cfg->phaseDist1;
-        phaseKpPos = cfg->phaseKpPos;
-        phaseKpOri = cfg->phaseKpOri;
-
-        // initialize tcp position and orientation
-        Eigen::Matrix4f pose = tcp->getPoseInRootFrame();
-        tcpPosition(0) = pose(0, 3);
-        tcpPosition(1) = pose(1, 3);
-        tcpPosition(2) = pose(2, 3);
-
-        tcpOrientation = VirtualRobot::MathTools::eigen4f2rpy(pose);
-
-        posToOriRatio = cfg->posToOriRatio;
-    }
-
-    std::string NJointTaskSpaceDMPController::getClassName(const Ice::Current&) const
-    {
-        return "NJointTaskSpaceDMPController";
-    }
-
-    void NJointTaskSpaceDMPController::rtRun(const IceUtil::Time& sensorValuesTimestamp, const IceUtil::Time& timeSinceLastIteration)
-    {
-        if (rtGetControlStruct().isStart && !finished)
-        {
-            UMIDMPPtr dmpPtr = rtGetControlStruct().dmpPtr;
-
-            // DMP controller
-            Eigen::Matrix4f pose = tcp->getPoseInRootFrame();
-            Eigen::Vector3f currPosition;
-            Eigen::Vector3f currOrientation = VirtualRobot::MathTools::eigen4f2rpy(pose);
-            currPosition(0) = pose(0, 3);
-            currPosition(1) = pose(1, 3);
-            currPosition(2) = pose(2, 3);
-
-            double deltaT = timeSinceLastIteration.toSecondsDouble();
-            double dmpDeltaT = deltaT / timeDuration;
-
-            Eigen::Vector3f posVel;
-            Eigen::Vector3f oriVel;
-
-            if (deltaT == 0)
-            {
-                posVel << 0, 0 , 0;
-                oriVel << 0, 0 , 0;
-            }
-            else
-            {
-                posVel = (currPosition - tcpPosition) / deltaT;
-                oriVel = (currOrientation - tcpOrientation) / deltaT;
-            }
-
-            tcpPosition = currPosition;
-            tcpOrientation = currOrientation;
-
-            double phaseStop = 0;
-            double error = 0;
-            currentState.clear();
-
-            double posError = 0;
-            double oriError = 0;
-            for (size_t i = 0; i < 3; i++)
-            {
-                DMP::DMPState currentPos;
-                currentPos.pos = tcpPosition(i);
-                currentPos.vel = posVel(i) * timeDuration;
-                currentState.push_back(currentPos);
-
-                posError += pow(currentPos.pos - targetState[i], 2);
-            }
-
-            for (size_t i = 0; i < 3; i++)
-            {
-                DMP::DMPState currentPos;
-                currentPos.pos = tcpOrientation(i);
-                currentPos.vel = oriVel(i) * timeDuration;
-                currentState.push_back(currentPos);
-
-                oriError += pow(currentPos.pos - targetState[i + 3], 2);
-            }
-
-
-            error = sqrt(posError + posToOriRatio * oriError);
-
-            double phaseDist;
-            if (isDisturbance)
-            {
-                phaseDist = phaseDist1;
-            }
-            else
-            {
-                phaseDist = phaseDist0;
-            }
-
-            phaseStop = phaseL / (1 + exp(-phaseK * (error - phaseDist)));
-            double mpcFactor = 1 - (phaseStop / phaseL);
-
-            if (mpcFactor < 0.1)
-            {
-                isDisturbance = true;
-            }
-
-            if (mpcFactor > 0.9)
-            {
-                isDisturbance = false;
-            }
-
-
-            double tau = dmpPtr->getTemporalFactor();
-            canVal -= 1 / tau * deltaT * 1 / (1 + phaseStop) ;
-            currentState = dmpPtr->calculateDirectlyVelocity(currentState, canVal / timeDuration, dmpDeltaT, targetState);
-
-            if (canVal < 1e-8)
-            {
-                finished = true;
-            }
-
-            // cartesian velocity controller
-            Eigen::VectorXf x;
-            auto mode = rtGetControlStruct().mode;
-
-            double vel0, vel1;
-            if (mode == VirtualRobot::IKSolver::All)
-            {
-                x.resize(6);
-
-                for (size_t i = 0; i < 3; i++)
-                {
-                    vel0 = currentState[i].vel / timeDuration;
-                    vel1 = phaseKpPos * (targetState[i] - tcpPosition[i]);
-                    x(i) = mpcFactor * vel0 + (1 - mpcFactor) * vel1;
-
-                }
-                for (size_t i = 0; i < 3; i++)
-                {
-                    vel0 = currentState[i + 3].vel / timeDuration;
-                    vel1 = phaseKpOri * (targetState[i + 3] - tcpOrientation[i]);
-                    x(i + 3) = mpcFactor * vel0 + (1 - mpcFactor) * vel1;
-                }
-
-                debugOutputData.getWriteBuffer().latestTargetVelocities["x_vel"] = x(0);
-                debugOutputData.getWriteBuffer().latestTargetVelocities["y_vel"] = x(1);
-                debugOutputData.getWriteBuffer().latestTargetVelocities["z_vel"] = x(2);
-                debugOutputData.getWriteBuffer().latestTargetVelocities["r_vel"] = x(3);
-                debugOutputData.getWriteBuffer().latestTargetVelocities["p_vel"] = x(4);
-                debugOutputData.getWriteBuffer().latestTargetVelocities["y_vel"] = x(5);
-                debugOutputData.getWriteBuffer().currentCanVal = canVal;
-                debugOutputData.getWriteBuffer().mpcFactor = mpcFactor;
-                debugOutputData.commitWrite();
-
-            }
-            else if (mode == VirtualRobot::IKSolver::Position)
-            {
-                x.resize(3);
-
-                for (size_t i = 0; i < 3; i++)
-                {
-                    vel0 = currentState[i].vel / timeDuration;
-                    vel1 = phaseKpPos * (targetState[i] - tcpPosition[i]);
-                    x(i) = mpcFactor * vel0 + (1 - mpcFactor) * vel1;
-                }
-
-                debugOutputData.getWriteBuffer().latestTargetVelocities["x_vel"] = x(0);
-                debugOutputData.getWriteBuffer().latestTargetVelocities["y_vel"] = x(1);
-                debugOutputData.getWriteBuffer().latestTargetVelocities["z_vel"] = x(2);
-                debugOutputData.getWriteBuffer().currentCanVal = canVal;
-                debugOutputData.getWriteBuffer().mpcFactor = mpcFactor;
-                debugOutputData.commitWrite();
-            }
-            else if (mode == VirtualRobot::IKSolver::Orientation)
-            {
-                x.resize(3);
-
-                for (size_t i = 0; i < 3; i++)
-                {
-                    vel0 = currentState[i + 3].vel / timeDuration;
-                    vel1 = phaseKpOri * (targetState[i + 3] - tcpOrientation[i]);
-                    x(i) = mpcFactor * vel0 + (1 - mpcFactor) * vel1;
-                }
-
-                debugOutputData.getWriteBuffer().latestTargetVelocities["r_vel"] = x(3);
-                debugOutputData.getWriteBuffer().latestTargetVelocities["p_vel"] = x(4);
-                debugOutputData.getWriteBuffer().latestTargetVelocities["y_vel"] = x(5);
-                debugOutputData.getWriteBuffer().currentCanVal = canVal;
-                debugOutputData.getWriteBuffer().mpcFactor = mpcFactor;
-                debugOutputData.commitWrite();
-            }
-            else
-            {
-                // No mode has been set
-                return;
-            }
-
-
-            Eigen::VectorXf jnv = Eigen::VectorXf::Zero(tcpController->rns->getSize());
-            float jointLimitAvoidanceKp = rtGetControlStruct().avoidJointLimitsKp;
-            if (jointLimitAvoidanceKp > 0)
-            {
-                jnv += jointLimitAvoidanceKp * tcpController->calculateJointLimitAvoidance();
-            }
-            for (size_t i = 0; i < tcpController->rns->getSize(); i++)
-            {
-                jnv(i) += rtGetControlStruct().nullspaceJointVelocities.at(i);
-                if (torqueSensors.at(i) && gravityTorqueSensors.at(i) && rtGetControlStruct().torqueKp.at(i) != 0)
-                {
-                    torquePIDs.at(i).Kp = rtGetControlStruct().torqueKp.at(i);
-                    torquePIDs.at(i).Kd = rtGetControlStruct().torqueKd.at(i);
-                    jnv(i) += torquePIDs.at(i).update(timeSinceLastIteration.toSecondsDouble(), torqueSensors.at(i)->torque - gravityTorqueSensors.at(i)->gravityTorque);
-                    //jnv(i) += rtGetControlStruct().torqueKp.at(i) * (torqueSensors.at(i)->torque - gravityTorqueSensors.at(i)->gravityTorque);
-                }
-                else
-                {
-                    torquePIDs.at(i).lastError = 0;
-                }
-            }
-
-            Eigen::VectorXf jointTargetVelocities = tcpController->calculate(x, jnv, mode);
-
-            for (size_t i = 0; i < targets.size(); ++i)
-            {
-                targets.at(i)->velocity = jointTargetVelocities(i);
-            }
-        }
-        else
-        {
-            for (size_t i = 0; i < targets.size(); ++i)
-            {
-                targets.at(i)->velocity = 0;
-            }
-        }
-    }
-
-
-    void NJointTaskSpaceDMPController::learnDMPFromFiles(const Ice::StringSeq& fileNames, const Ice::Current&)
-    {
-        DMP::Vec<DMP::SampledTrajectoryV2 > trajs;
-
-        DMP::DVec ratios;
-        for (size_t i = 0; i < fileNames.size(); ++i)
-        {
-            DMP::SampledTrajectoryV2 traj;
-            traj.readFromCSVFile(fileNames.at(i));
-            traj = DMP::SampledTrajectoryV2::normalizeTimestamps(traj, 0, 1);
-            trajs.push_back(traj);
-
-            if (i == 0)
-            {
-                ratios.push_back(1.0);
-            }
-            else
-            {
-                ratios.push_back(0.0);
-            }
-        }
-
-        dmpPtr->learnFromTrajectories(trajs);
-        dmpPtr->setOneStepMPC(true);
-        dmpPtr->styleParas = dmpPtr->getStyleParasWithRatio(ratios);
-
-        ARMARX_INFO << "Learned DMP ... ";
-    }
-
-    void NJointTaskSpaceDMPController::setViaPoints(Ice::Double u, const Ice::DoubleSeq& viapoint, const Ice::Current&)
-    {
-        ViaPoint viaPoint(u, viapoint);
-        dmpPtr->setViaPoint(viaPoint);
-
-        LockGuardType guard {controlDataMutex};
-        getWriterControlStruct().dmpPtr = dmpPtr;
-        writeControlStruct();
-    }
-
-
-    void NJointTaskSpaceDMPController::setGoals(const Ice::DoubleSeq& goals, const Ice::Current& ice)
-    {
-        setViaPoints(dmpPtr->getUMin(), goals, ice);
-    }
-
-    void NJointTaskSpaceDMPController::setControllerTarget(Ice::Float avoidJointLimitsKp, NJointTaskSpaceDMPControllerMode::CartesianSelection mode, const Ice::Current&)
-    {
-        LockGuardType guard {controlDataMutex};
-        getWriterControlStruct().avoidJointLimitsKp = avoidJointLimitsKp;
-        getWriterControlStruct().mode = ModeFromIce(mode);
-        writeControlStruct();
-    }
-
-    VirtualRobot::IKSolver::CartesianSelection NJointTaskSpaceDMPController::ModeFromIce(const NJointTaskSpaceDMPControllerMode::CartesianSelection mode)
-    {
-        if (mode == NJointTaskSpaceDMPControllerMode::CartesianSelection::ePosition)
-        {
-            return VirtualRobot::IKSolver::CartesianSelection::Position;
-        }
-        if (mode == NJointTaskSpaceDMPControllerMode::CartesianSelection::eOrientation)
-        {
-            return VirtualRobot::IKSolver::CartesianSelection::Orientation;
-        }
-        if (mode == NJointTaskSpaceDMPControllerMode::CartesianSelection::eAll)
-        {
-            return VirtualRobot::IKSolver::CartesianSelection::All;
-        }
-        ARMARX_ERROR_S << "invalid mode " << mode;
-        return (VirtualRobot::IKSolver::CartesianSelection)0;
-    }
-
-    void NJointTaskSpaceDMPController::onPublish(const SensorAndControl&, const DebugDrawerInterfacePrx&, const DebugObserverInterfacePrx& debugObs)
-    {
-        StringVariantBaseMap datafields;
-        auto values = debugOutputData.getUpToDateReadBuffer().latestTargetVelocities;
-        for (auto& pair : values)
-        {
-            datafields[pair.first] = new Variant(pair.second);
-        }
-
-        datafields["canVal"] = new Variant(debugOutputData.getUpToDateReadBuffer().currentCanVal);
-        datafields["mpcFactor"] = new Variant(debugOutputData.getUpToDateReadBuffer().mpcFactor);
-        debugObs->setDebugChannel("latestDMPTargetVelocities", datafields);
-    }
-
-
-    void NJointTaskSpaceDMPController::setTorqueKp(const StringFloatDictionary& torqueKp, const Ice::Current&)
-    {
-        LockGuardType guard {controlDataMutex};
-        for (size_t i = 0; i < tcpController->rns->getSize(); i++)
-        {
-            getWriterControlStruct().torqueKp.at(i) = torqueKp.at(tcpController->rns->getNode(i)->getName());
-        }
-        writeControlStruct();
-    }
-
-    void NJointTaskSpaceDMPController::setNullspaceJointVelocities(const StringFloatDictionary& nullspaceJointVelocities, const Ice::Current&)
-    {
-        LockGuardType guard {controlDataMutex};
-        for (size_t i = 0; i < tcpController->rns->getSize(); i++)
-        {
-            getWriterControlStruct().nullspaceJointVelocities.at(i) = nullspaceJointVelocities.at(tcpController->rns->getNode(i)->getName());
-        }
-        writeControlStruct();
-    }
-
-    void NJointTaskSpaceDMPController::runDMP(const Ice::DoubleSeq&  goals, double tau, const Ice::Current&)
-    {
-        currentState.clear();
-        targetState.clear();
-        for (size_t i = 0; i < 3; i++)
-        {
-            DMP::DMPState currentPos;
-            currentPos.pos = tcpPosition(i);
-            currentPos.vel = 0;
-            currentState.push_back(currentPos);
-            targetState.push_back(currentPos.pos);
-        }
-        for (size_t i = 0; i < 3; i++)
-        {
-            DMP::DMPState currentPos;
-            currentPos.pos = tcpOrientation(i);
-            currentPos.vel = 0;
-            currentState.push_back(currentPos);
-            targetState.push_back(currentPos.pos);
-        }
-        dmpPtr->prepareExecution(goals, currentState, 1,  tau);
-        finished = false;
-        dmpPtr->setTemporalFactor(tau);
-
-        LockGuardType guard {controlDataMutex};
-        getWriterControlStruct().dmpPtr = dmpPtr;
-        getWriterControlStruct().isStart = true;
-        writeControlStruct();
-
-    }
-
-    void NJointTaskSpaceDMPController::setTemporalFactor(double tau, const Ice::Current&)
-    {
-        dmpPtr->setTemporalFactor(tau);
-        LockGuardType guard {controlDataMutex};
-        getWriterControlStruct().dmpPtr = dmpPtr;
-        writeControlStruct();
-    }
-
-    void NJointTaskSpaceDMPController::rtPreActivateController()
-    {
-    }
-
-    void NJointTaskSpaceDMPController::rtPostDeactivateController()
-    {
-
-    }
-
-}
diff --git a/source/RobotAPI/libraries/RobotAPINJointControllers/DMPController/NJointTaskSpaceDMPController.h b/source/RobotAPI/libraries/RobotAPINJointControllers/DMPController/NJointTaskSpaceDMPController.h
deleted file mode 100644
index e3bb4412951d30c4d2e22209cf67cdb5140863f0..0000000000000000000000000000000000000000
--- a/source/RobotAPI/libraries/RobotAPINJointControllers/DMPController/NJointTaskSpaceDMPController.h
+++ /dev/null
@@ -1,141 +0,0 @@
-
-#pragma once
-
-#include <RobotAPI/components/units/RobotUnit/NJointControllers/NJointController.h>
-#include <VirtualRobot/Robot.h>
-#include <RobotAPI/components/units/RobotUnit/RobotUnit.h>
-#include <RobotAPI/components/units/RobotUnit/ControlTargets/ControlTarget1DoFActuator.h>
-#include <RobotAPI/components/units/RobotUnit/SensorValues/SensorValue1DoFActuator.h>
-#include <VirtualRobot/IK/DifferentialIK.h>
-#include <dmp/representation/dmp/umidmp.h>
-#include <RobotAPI/interface/units/RobotUnit/NJointTaskSpaceDMPController.h>
-#include <RobotAPI/libraries/core/CartesianVelocityController.h>
-
-
-using namespace DMP;
-namespace armarx
-{
-
-
-    TYPEDEF_PTRS_HANDLE(NJointTaskSpaceDMPController);
-    TYPEDEF_PTRS_HANDLE(NJointTaskSpaceDMPControllerControlData);
-
-    typedef std::pair<double, DVec > ViaPoint;
-    typedef std::vector<ViaPoint > ViaPointsSet;
-    class NJointTaskSpaceDMPControllerControlData
-    {
-    public:
-        // dmp control data
-        UMIDMPPtr dmpPtr;
-        bool isStart;
-
-        // cartesian velocity control data
-        std::vector<float> nullspaceJointVelocities;
-        float avoidJointLimitsKp = 0;
-        std::vector<float> torqueKp;
-        std::vector<float> torqueKd;
-        VirtualRobot::IKSolver::CartesianSelection mode = VirtualRobot::IKSolver::All;
-    };
-
-    class pidController
-    {
-    public:
-        float Kp = 0, Kd = 0;
-        float lastError = 0;
-        float update(float dt, float error)
-        {
-            float derivative = (error - lastError) / dt;
-            float retVal = Kp * error + Kd * derivative;
-            lastError = error;
-            return retVal;
-        }
-    };
-
-    class NJointTaskSpaceDMPController :
-        public NJointControllerWithTripleBuffer<NJointTaskSpaceDMPControllerControlData>,
-        public NJointTaskSpaceDMPControllerInterface
-    {
-    public:
-        using ConfigPtrT = NJointTaskSpaceDMPControllerConfigPtr;
-        NJointTaskSpaceDMPController(const RobotUnitPtr& robotUnit, const NJointControllerConfigPtr& config, const VirtualRobot::RobotPtr&);
-
-        // NJointControllerInterface interface
-        std::string getClassName(const Ice::Current&) const;
-
-        // NJointController interface
-
-        void rtRun(const IceUtil::Time& sensorValuesTimestamp, const IceUtil::Time& timeSinceLastIteration);
-
-        // NJointTaskSpaceDMPControllerInterface interface
-        void learnDMPFromFiles(const Ice::StringSeq& fileNames, const Ice::Current&);
-        bool isFinished(const Ice::Current&)
-        {
-            return finished;
-        }
-
-        void runDMP(const Ice::DoubleSeq& goals, Ice::Double tau, const Ice::Current&);
-        void setTemporalFactor(Ice::Double tau, const Ice::Current&);
-        void setViaPoints(Ice::Double u, const Ice::DoubleSeq& viapoint, const Ice::Current&);
-
-        void setGoals(const Ice::DoubleSeq& goals, const Ice::Current&);
-
-        void setControllerTarget(Ice::Float avoidJointLimitsKp, NJointTaskSpaceDMPControllerMode::CartesianSelection mode, const Ice::Current&);
-        void setTorqueKp(const StringFloatDictionary& torqueKp, const Ice::Current&);
-        void setNullspaceJointVelocities(const StringFloatDictionary& nullspaceJointVelocities, const Ice::Current&);
-    protected:
-        void rtPreActivateController() override;
-        void rtPostDeactivateController() override;
-        VirtualRobot::IKSolver::CartesianSelection ModeFromIce(const NJointTaskSpaceDMPControllerMode::CartesianSelection mode);
-        virtual void onPublish(const SensorAndControl&, const DebugDrawerInterfacePrx&, const DebugObserverInterfacePrx&);
-
-    private:
-        struct DebugBufferData
-        {
-            StringFloatDictionary latestTargetVelocities;
-            double currentCanVal;
-            double mpcFactor;
-        };
-
-        TripleBuffer<DebugBufferData> debugOutputData;
-
-
-        std::vector<const SensorValue1DoFActuatorTorque*> torqueSensors;
-        std::vector<const SensorValue1DoFGravityTorque*> gravityTorqueSensors;
-        std::vector<ControlTarget1DoFActuatorVelocity*> targets;
-
-        // velocity ik controller parameters
-        std::vector<pidController> torquePIDs;
-        CartesianVelocityControllerPtr tcpController;
-        std::string nodeSetName;
-
-        // dmp parameters
-        UMIDMPPtr dmpPtr;
-        double timeDuration;
-        double canVal;
-        bool finished;
-        double tau;
-        ViaPointsSet viaPoints;
-
-        // phaseStop parameters
-        double phaseL;
-        double phaseK;
-        double phaseDist0;
-        double phaseDist1;
-        double phaseKpPos;
-        double phaseKpOri;
-        double posToOriRatio;
-
-
-        bool isDisturbance;
-        NJointTaskSpaceDMPControllerConfigPtr cfg;
-        VirtualRobot::RobotNodePtr tcp;
-        Eigen::Vector3f tcpPosition;
-        Eigen::Vector3f tcpOrientation;
-        DMP::Vec<DMP::DMPState> currentState;
-        DMP::DVec targetState;
-
-
-    };
-
-} // namespace armarx
-
diff --git a/source/RobotAPI/libraries/RobotAPINJointControllers/DMPController/NJointTaskSpaceImpedanceDMPController.cpp b/source/RobotAPI/libraries/RobotAPINJointControllers/DMPController/NJointTaskSpaceImpedanceDMPController.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..6c773caadf6d5bbb951a8dcfb1226aa212544b94
--- /dev/null
+++ b/source/RobotAPI/libraries/RobotAPINJointControllers/DMPController/NJointTaskSpaceImpedanceDMPController.cpp
@@ -0,0 +1,368 @@
+#include "NJointTaskSpaceImpedanceDMPController.h"
+
+namespace armarx
+{
+    NJointControllerRegistration<NJointTaskSpaceImpedanceDMPController> registrationControllerNJointTaskSpaceImpedanceDMPController("NJointTaskSpaceImpedanceDMPController");
+
+    NJointTaskSpaceImpedanceDMPController::NJointTaskSpaceImpedanceDMPController(armarx::NJointControllerDescriptionProviderInterfacePtr prov, const armarx::NJointControllerConfigPtr& config, const VirtualRobot::RobotPtr&)
+    {
+        cfg = NJointTaskSpaceImpedanceDMPControllerConfigPtr::dynamicCast(config);
+        RobotUnitPtr robotUnit = RobotUnitPtr::dynamicCast(prov);
+        VirtualRobot::RobotNodeSetPtr rns = robotUnit->getRtRobot()->getRobotNodeSet(cfg->nodeSetName);
+        ARMARX_CHECK_EXPRESSION_W_HINT(rns, cfg->nodeSetName);
+
+        for (size_t i = 0; i < rns->getSize(); ++i)
+        {
+            std::string jointName = rns->getNode(i)->getName();
+            jointNames.push_back(jointName);
+            ControlTargetBase* ct = prov->getControlTarget(jointName, ControlModes::Torque1DoF);
+            const SensorValueBase* sv = prov->getSensorValue(jointName);
+            targets.push_back(ct->asA<ControlTarget1DoFActuatorTorque>());
+            const SensorValue1DoFActuatorVelocity* velocitySensor = sv->asA<SensorValue1DoFActuatorVelocity>();
+            const SensorValue1DoFActuatorPosition* positionSensor = sv->asA<SensorValue1DoFActuatorPosition>();
+
+            if (!velocitySensor)
+            {
+                ARMARX_WARNING << "No velocitySensor available for " << jointName;
+            }
+            if (!positionSensor)
+            {
+                ARMARX_WARNING << "No positionSensor available for " << jointName;
+            }
+
+            velocitySensors.push_back(velocitySensor);
+            positionSensors.push_back(positionSensor);
+        };
+
+        tcp =  rns->getTCP();
+        ik.reset(new VirtualRobot::DifferentialIK(rns, rns->getRobot()->getRootNode(), VirtualRobot::JacobiProvider::eSVDDamped));
+
+        // set DMP
+        TaskSpaceDMPControllerConfig taskSpaceDMPConfig;
+        taskSpaceDMPConfig.motionTimeDuration = cfg->timeDuration;
+        taskSpaceDMPConfig.DMPKernelSize = cfg->kernelSize;
+        taskSpaceDMPConfig.DMPMode = cfg->dmpMode;
+        taskSpaceDMPConfig.DMPStyle = cfg->dmpType;
+        taskSpaceDMPConfig.DMPAmplitude = 1.0;
+        taskSpaceDMPConfig.phaseStopParas.goDist = cfg->phaseDist0;
+        taskSpaceDMPConfig.phaseStopParas.backDist = cfg->phaseDist1;
+        taskSpaceDMPConfig.phaseStopParas.Kpos = 0;
+        taskSpaceDMPConfig.phaseStopParas.Dpos = 0;
+        taskSpaceDMPConfig.phaseStopParas.Kori = 0;
+        taskSpaceDMPConfig.phaseStopParas.Dori = 0;
+        taskSpaceDMPConfig.phaseStopParas.mm2radi = cfg->posToOriRatio;
+        taskSpaceDMPConfig.phaseStopParas.maxValue = cfg->phaseL;
+        taskSpaceDMPConfig.phaseStopParas.slop = cfg->phaseK;
+
+        dmpCtrl.reset(new TaskSpaceDMPController("DMPController", taskSpaceDMPConfig, false));
+        finished = false;
+
+        useNullSpaceJointDMP = cfg->useNullSpaceJointDMP;
+        nullSpaceJointDMPPtr.reset(new DMP::UMIDMP(100));
+
+        isNullSpaceJointDMPLearned = false;
+
+        defaultNullSpaceJointValues.resize(targets.size());
+        ARMARX_CHECK_EQUAL(cfg->defaultNullSpaceJointValues.size(), targets.size());
+
+        for (size_t i = 0; i < targets.size(); ++i)
+        {
+            defaultNullSpaceJointValues(i) = cfg->defaultNullSpaceJointValues.at(i);
+        }
+
+
+        kpos << cfg->Kpos[0], cfg->Kpos[1], cfg->Kpos[2];
+        dpos << cfg->Dpos[0], cfg->Dpos[1], cfg->Dpos[2];
+        kori << cfg->Kori[0], cfg->Kori[1], cfg->Kori[2];
+        dori << cfg->Dori[0], cfg->Dori[1], cfg->Dori[2];
+        knull = cfg->Knull;
+        dnull = cfg->Dnull;
+
+        torqueLimit = cfg->torqueLimit;
+        timeDuration = cfg->timeDuration;
+        NJointTaskSpaceImpedanceDMPControllerControlData initData;
+        initData.targetPose = tcp->getPoseInRootFrame();
+        initData.targetVel.resize(6);
+        initData.targetVel.setZero();
+        initData.desiredNullSpaceJointValues = defaultNullSpaceJointValues;
+        reinitTripleBuffer(initData);
+
+    }
+
+    std::string NJointTaskSpaceImpedanceDMPController::getClassName(const Ice::Current&) const
+    {
+        return "NJointTaskSpaceImpedanceDMPController";
+    }
+
+    void NJointTaskSpaceImpedanceDMPController::controllerRun()
+    {
+        if (!controllerSensorData.updateReadBuffer() || !dmpCtrl)
+        {
+            return;
+        }
+
+        if (dmpCtrl->canVal < 1e-8)
+        {
+            finished = true;
+            LockGuardType guard {controlDataMutex};
+            getWriterControlStruct().targetVel.setZero();
+            writeControlStruct();
+            return;
+        }
+
+        double deltaT = controllerSensorData.getReadBuffer().deltaT;
+        Eigen::Matrix4f currentPose = controllerSensorData.getReadBuffer().currentPose;
+        Eigen::VectorXf currentTwist = controllerSensorData.getReadBuffer().currentTwist;
+
+        dmpCtrl->flow(deltaT, currentPose, currentTwist);
+
+        Eigen::VectorXf desiredNullSpaceJointValues(jointNames.size());
+        if (useNullSpaceJointDMP && isNullSpaceJointDMPLearned)
+        {
+            DMP::DVec targetJointState;
+            currentJointState = nullSpaceJointDMPPtr->calculateDirectlyVelocity(currentJointState, dmpCtrl->canVal / timeDuration, deltaT / timeDuration, targetJointState);
+
+            if (targetJointState.size() == jointNames.size())
+            {
+                for (size_t i = 0; i < targetJointState.size(); ++i)
+                {
+                    desiredNullSpaceJointValues(i) = targetJointState[i];
+                }
+            }
+            else
+            {
+                desiredNullSpaceJointValues = defaultNullSpaceJointValues;
+            }
+        }
+        else
+        {
+            desiredNullSpaceJointValues = defaultNullSpaceJointValues;
+        }
+
+        LockGuardType guard {controlDataMutex};
+        getWriterControlStruct().desiredNullSpaceJointValues = desiredNullSpaceJointValues;
+        getWriterControlStruct().targetVel = dmpCtrl->getTargetVelocity();
+        getWriterControlStruct().targetPose = dmpCtrl->getTargetPoseMat();
+        writeControlStruct();
+    }
+
+    void NJointTaskSpaceImpedanceDMPController::rtRun(const IceUtil::Time& sensorValuesTimestamp, const IceUtil::Time& timeSinceLastIteration)
+    {
+        double deltaT = timeSinceLastIteration.toSecondsDouble();
+
+        Eigen::MatrixXf jacobi = ik->getJacobianMatrix(tcp, VirtualRobot::IKSolver::CartesianSelection::All);
+
+        Eigen::VectorXf qpos(positionSensors.size());
+        Eigen::VectorXf qvel(velocitySensors.size());
+        for (size_t i = 0; i < positionSensors.size(); ++i)
+        {
+            qpos(i) = positionSensors[i]->position;
+            qvel(i) = velocitySensors[i]->velocity;
+        }
+
+        Eigen::Matrix4f currentPose = tcp->getPoseInRootFrame();
+        Eigen::VectorXf currentTwist = jacobi * qvel;
+
+        controllerSensorData.getWriteBuffer().currentPose = currentPose;
+        controllerSensorData.getWriteBuffer().currentTwist = currentTwist;
+        controllerSensorData.getWriteBuffer().deltaT = deltaT;
+        controllerSensorData.getWriteBuffer().currentTime += deltaT;
+        controllerSensorData.commitWrite();
+
+        jacobi.block<3, 8>(0, 0) = 0.001 * jacobi.block<3, 8>(0, 0); // convert mm to m
+
+        Eigen::Matrix4f targetPose = rtGetControlStruct().targetPose;
+        Eigen::VectorXf targetVel = rtGetControlStruct().targetVel;
+
+        Eigen::Vector6f jointControlWrench;
+        {
+            Eigen::Vector3f targetTCPLinearVelocity;
+            targetTCPLinearVelocity << 0.001 * targetVel(0), 0.001 * targetVel(1), 0.001 * targetVel(2);
+            Eigen::Vector3f currentTCPLinearVelocity;
+            currentTCPLinearVelocity <<  0.001 * currentTwist(0),  0.001 * currentTwist(1),   0.001 * currentTwist(2);
+            Eigen::Vector3f currentTCPPosition = currentPose.block<3, 1>(0, 3);
+            Eigen::Vector3f desiredPosition = targetPose.block<3, 1>(0, 3);
+            Eigen::Vector3f tcpDesiredForce = 0.001 * kpos.cwiseProduct(desiredPosition - currentTCPPosition) + dpos.cwiseProduct(targetTCPLinearVelocity - currentTCPLinearVelocity);
+
+            Eigen::Vector3f currentTCPAngularVelocity;
+            currentTCPAngularVelocity << currentTwist(3),   currentTwist(4),  currentTwist(5);
+            Eigen::Matrix3f currentRotMat = currentPose.block<3, 3>(0, 0);
+            Eigen::Matrix3f diffMat = targetPose.block<3, 3>(0, 0) * currentRotMat.inverse();
+            Eigen::Vector3f rpy = VirtualRobot::MathTools::eigen3f2rpy(diffMat);
+            Eigen::Vector3f tcpDesiredTorque = kori.cwiseProduct(rpy) - dori.cwiseProduct(currentTCPAngularVelocity);
+            jointControlWrench <<  tcpDesiredForce, tcpDesiredTorque;
+        }
+
+        Eigen::MatrixXf I = Eigen::MatrixXf::Identity(targets.size(), targets.size());
+
+        Eigen::VectorXf desiredNullSpaceJointValues = rtGetControlStruct().desiredNullSpaceJointValues;
+        Eigen::VectorXf nullspaceTorque = knull * (desiredNullSpaceJointValues - qpos) - dnull * qvel;
+        Eigen::MatrixXf jtpinv = ik->computePseudoInverseJacobianMatrix(jacobi.transpose(), 2.0);
+        Eigen::VectorXf jointDesiredTorques = jacobi.transpose() * jointControlWrench + (I - jacobi.transpose() * jtpinv) * nullspaceTorque;
+
+        // torque limit
+        for (size_t i = 0; i < targets.size(); ++i)
+        {
+            float desiredTorque = jointDesiredTorques(i);
+
+            if (isnan(desiredTorque))
+            {
+                desiredTorque = 0;
+            }
+
+            desiredTorque = (desiredTorque >  torqueLimit) ? torqueLimit : desiredTorque;
+            desiredTorque = (desiredTorque < -torqueLimit) ? -torqueLimit : desiredTorque;
+
+            debugOutputData.getWriteBuffer().desired_torques[jointNames[i]] = jointDesiredTorques(i);
+            debugOutputData.getWriteBuffer().desired_nullspaceJoint[jointNames[i]] = desiredNullSpaceJointValues(i);
+
+            targets.at(i)->torque = desiredTorque;
+        }
+
+        debugOutputData.getWriteBuffer().currentCanVal = dmpCtrl->debugData.canVal;
+        debugOutputData.getWriteBuffer().targetPose_x = targetPose(0, 3);
+        debugOutputData.getWriteBuffer().targetPose_y = targetPose(1, 3);
+        debugOutputData.getWriteBuffer().targetPose_z = targetPose(2, 3);
+        VirtualRobot::MathTools::Quaternion targetQuat = VirtualRobot::MathTools::eigen4f2quat(targetPose);
+        debugOutputData.getWriteBuffer().targetPose_qw = targetQuat.w;
+        debugOutputData.getWriteBuffer().targetPose_qx = targetQuat.x;
+        debugOutputData.getWriteBuffer().targetPose_qy = targetQuat.y;
+        debugOutputData.getWriteBuffer().targetPose_qz = targetQuat.z;
+
+
+
+
+
+        debugOutputData.getWriteBuffer().currentPose_x = currentPose(0, 3);
+        debugOutputData.getWriteBuffer().currentPose_y = currentPose(1, 3);
+        debugOutputData.getWriteBuffer().currentPose_z = currentPose(2, 3);
+        VirtualRobot::MathTools::Quaternion currentQuat = VirtualRobot::MathTools::eigen4f2quat(currentPose);
+        debugOutputData.getWriteBuffer().currentPose_qw = currentQuat.w;
+        debugOutputData.getWriteBuffer().currentPose_qx = currentQuat.x;
+        debugOutputData.getWriteBuffer().currentPose_qy = currentQuat.y;
+        debugOutputData.getWriteBuffer().currentPose_qz = currentQuat.z;
+
+        debugOutputData.commitWrite();
+
+    }
+
+
+    void NJointTaskSpaceImpedanceDMPController::learnDMPFromFiles(const Ice::StringSeq& fileNames, const Ice::Current&)
+    {
+        dmpCtrl->learnDMPFromFiles(fileNames);
+        ARMARX_INFO << "Learned DMP ... ";
+    }
+
+    void NJointTaskSpaceImpedanceDMPController::setViaPoints(Ice::Double u, const Ice::DoubleSeq& viapoint, const Ice::Current&)
+    {
+        LockGuardType guard(controllerMutex);
+        ARMARX_INFO << "setting via points ";
+        dmpCtrl->setViaPose(u, viapoint);
+    }
+
+
+    void NJointTaskSpaceImpedanceDMPController::setGoals(const Ice::DoubleSeq& goals, const Ice::Current& ice)
+    {
+        dmpCtrl->setGoalPoseVec(goals);
+    }
+
+    void NJointTaskSpaceImpedanceDMPController::learnJointDMPFromFiles(const std::string& fileName, const Ice::Current&)
+    {
+        DMP::Vec<DMP::SampledTrajectoryV2 > trajs;
+        DMP::DVec ratios;
+        DMP::SampledTrajectoryV2 traj;
+        traj.readFromCSVFile(fileName);
+        traj = DMP::SampledTrajectoryV2::normalizeTimestamps(traj, 0, 1);
+        if (traj.dim() != jointNames.size())
+        {
+            isNullSpaceJointDMPLearned = false;
+            return;
+        }
+
+        DMP::DVec goal;
+        goal.resize(traj.dim());
+        currentJointState.resize(traj.dim());
+
+        for (size_t i = 0; i < goal.size(); ++i)
+        {
+            goal.at(i) = traj.rbegin()->getPosition(i);
+            currentJointState.at(i).pos = traj.begin()->getPosition(i);
+            currentJointState.at(i).vel = 0;
+        }
+
+        trajs.push_back(traj);
+        nullSpaceJointDMPPtr->learnFromTrajectories(trajs);
+
+        // prepare exeuction of joint dmp
+        nullSpaceJointDMPPtr->prepareExecution(goal, currentJointState, 1.0, 1.0);
+        ARMARX_INFO << "prepared nullspace joint dmp";
+        isNullSpaceJointDMPLearned = true;
+    }
+
+    void NJointTaskSpaceImpedanceDMPController::runDMP(const Ice::DoubleSeq& goals, const Ice::Current&)
+    {
+        Eigen::Matrix4f pose = tcp->getPoseInRootFrame();
+        dmpCtrl->prepareExecution(dmpCtrl->eigen4f2vec(pose), goals);
+        finished = false;
+
+        if (isNullSpaceJointDMPLearned && useNullSpaceJointDMP)
+        {
+            ARMARX_INFO << "Using Null Space Joint DMP";
+        }
+
+        controllerTask->start();
+    }
+
+
+
+    void NJointTaskSpaceImpedanceDMPController::onPublish(const SensorAndControl&, const DebugDrawerInterfacePrx&, const DebugObserverInterfacePrx& debugObs)
+    {
+        StringVariantBaseMap datafields;
+        auto values = debugOutputData.getUpToDateReadBuffer().desired_torques;
+        for (auto& pair : values)
+        {
+            datafields[pair.first] = new Variant(pair.second);
+        }
+
+        auto values_null = debugOutputData.getUpToDateReadBuffer().desired_nullspaceJoint;
+        for (auto& pair : values_null)
+        {
+            datafields[pair.first] = new Variant(pair.second);
+        }
+
+        datafields["canVal"] = new Variant(debugOutputData.getUpToDateReadBuffer().currentCanVal);
+
+        datafields["targetPose_x"] = new Variant(debugOutputData.getUpToDateReadBuffer().targetPose_x);
+        datafields["targetPose_y"] = new Variant(debugOutputData.getUpToDateReadBuffer().targetPose_y);
+        datafields["targetPose_z"] = new Variant(debugOutputData.getUpToDateReadBuffer().targetPose_z);
+        datafields["targetPose_qw"] = new Variant(debugOutputData.getUpToDateReadBuffer().targetPose_qw);
+        datafields["targetPose_qx"] = new Variant(debugOutputData.getUpToDateReadBuffer().targetPose_qx);
+        datafields["targetPose_qy"] = new Variant(debugOutputData.getUpToDateReadBuffer().targetPose_qy);
+        datafields["targetPose_qz"] = new Variant(debugOutputData.getUpToDateReadBuffer().targetPose_qz);
+
+        datafields["currentPose_x"] = new Variant(debugOutputData.getUpToDateReadBuffer().currentPose_x);
+        datafields["currentPose_y"] = new Variant(debugOutputData.getUpToDateReadBuffer().currentPose_y);
+        datafields["currentPose_z"] = new Variant(debugOutputData.getUpToDateReadBuffer().currentPose_z);
+        datafields["currentPose_qw"] = new Variant(debugOutputData.getUpToDateReadBuffer().currentPose_qw);
+        datafields["currentPose_qx"] = new Variant(debugOutputData.getUpToDateReadBuffer().currentPose_qx);
+        datafields["currentPose_qy"] = new Variant(debugOutputData.getUpToDateReadBuffer().currentPose_qy);
+        datafields["currentPose_qz"] = new Variant(debugOutputData.getUpToDateReadBuffer().currentPose_qz);
+
+        debugObs->setDebugChannel("TaskSpaceImpedanceDMP", datafields);
+    }
+
+    void NJointTaskSpaceImpedanceDMPController::onInitComponent()
+    {
+        ARMARX_INFO << "init ...";
+        controllerTask = new PeriodicTask<NJointTaskSpaceImpedanceDMPController>(this, &NJointTaskSpaceImpedanceDMPController::controllerRun, 0.3);
+    }
+
+    void NJointTaskSpaceImpedanceDMPController::onDisconnectComponent()
+    {
+        controllerTask->stop();
+        ARMARX_INFO << "stopped ...";
+    }
+
+
+
+}
diff --git a/source/RobotAPI/libraries/RobotAPINJointControllers/DMPController/NJointTaskSpaceImpedanceDMPController.h b/source/RobotAPI/libraries/RobotAPINJointControllers/DMPController/NJointTaskSpaceImpedanceDMPController.h
new file mode 100644
index 0000000000000000000000000000000000000000..843908dfeb6729802815be1d3cbb3a3e326e4433
--- /dev/null
+++ b/source/RobotAPI/libraries/RobotAPINJointControllers/DMPController/NJointTaskSpaceImpedanceDMPController.h
@@ -0,0 +1,156 @@
+
+#pragma once
+
+#include <RobotAPI/components/units/RobotUnit/NJointControllers/NJointController.h>
+#include <VirtualRobot/Robot.h>
+#include <RobotAPI/components/units/RobotUnit/RobotUnit.h>
+#include <RobotAPI/components/units/RobotUnit/ControlTargets/ControlTarget1DoFActuator.h>
+#include <RobotAPI/components/units/RobotUnit/SensorValues/SensorValue1DoFActuator.h>
+#include <VirtualRobot/IK/DifferentialIK.h>
+#include <RobotAPI/interface/units/RobotUnit/NJointTaskSpaceDMPController.h>
+#include <RobotAPI/libraries/DMPController/TaskSpaceDMPController.h>
+#include <dmp/representation/dmp/umidmp.h>
+
+
+using namespace DMP;
+namespace armarx
+{
+
+
+    TYPEDEF_PTRS_HANDLE(NJointTaskSpaceImpedanceDMPController);
+    TYPEDEF_PTRS_HANDLE(NJointTaskSpaceImpedanceDMPControllerControlData);
+
+
+    class NJointTaskSpaceImpedanceDMPControllerControlData
+    {
+    public:
+        Eigen::VectorXf targetVel;
+        Eigen::Matrix4f targetPose;
+        Eigen::VectorXf desiredNullSpaceJointValues;
+    };
+
+
+
+    class NJointTaskSpaceImpedanceDMPController :
+        public NJointControllerWithTripleBuffer<NJointTaskSpaceImpedanceDMPControllerControlData>,
+        public NJointTaskSpaceImpedanceDMPControllerInterface
+    {
+    public:
+        using ConfigPtrT = NJointTaskSpaceImpedanceDMPControllerConfigPtr;
+        NJointTaskSpaceImpedanceDMPController(NJointControllerDescriptionProviderInterfacePtr prov, const NJointControllerConfigPtr& config, const VirtualRobot::RobotPtr&);
+
+        // NJointControllerInterface interface
+        std::string getClassName(const Ice::Current&) const;
+
+        // NJointController interface
+
+        void rtRun(const IceUtil::Time& sensorValuesTimestamp, const IceUtil::Time& timeSinceLastIteration);
+
+        // NJointTaskSpaceImpedanceDMPControllerInterface interface
+        void learnDMPFromFiles(const Ice::StringSeq& fileNames, const Ice::Current&);
+        bool isFinished(const Ice::Current&)
+        {
+            return finished;
+        }
+
+        void setViaPoints(Ice::Double u, const Ice::DoubleSeq& viapoint, const Ice::Current&);
+        void setGoals(const Ice::DoubleSeq& goals, const Ice::Current&);
+
+        void learnJointDMPFromFiles(const std::string& fileName, const Ice::Current&);
+        void runDMP(const Ice::DoubleSeq& goals, const Ice::Current&);
+        Ice::Double getVirtualTime(const Ice::Current&)
+        {
+            return dmpCtrl->canVal;
+        }
+
+    protected:
+        virtual void onPublish(const SensorAndControl&, const DebugDrawerInterfacePrx&, const DebugObserverInterfacePrx&);
+
+        void onInitComponent();
+        void onDisconnectComponent();
+        void controllerRun();
+
+    private:
+        struct DebugBufferData
+        {
+            double currentCanVal;
+            float targetPose_x;
+            float targetPose_y;
+            float targetPose_z;
+            float targetPose_qw;
+            float targetPose_qx;
+            float targetPose_qy;
+            float targetPose_qz;
+
+            float currentPose_x;
+            float currentPose_y;
+            float currentPose_z;
+            float currentPose_qw;
+            float currentPose_qx;
+            float currentPose_qy;
+            float currentPose_qz;
+
+            StringFloatDictionary desired_torques;
+            StringFloatDictionary desired_nullspaceJoint;
+
+        };
+
+        TripleBuffer<DebugBufferData> debugOutputData;
+
+        struct NJointTaskSpaceImpedanceDMPControllerSensorData
+        {
+            double currentTime;
+            double deltaT;
+            Eigen::Matrix4f currentPose;
+            Eigen::VectorXf currentTwist;
+        };
+        TripleBuffer<NJointTaskSpaceImpedanceDMPControllerSensorData> controllerSensorData;
+
+        TaskSpaceDMPControllerPtr dmpCtrl;
+
+        std::vector<const SensorValue1DoFActuatorTorque*> torqueSensors;
+        std::vector<const SensorValue1DoFActuatorVelocity*> velocitySensors;
+        std::vector<const SensorValue1DoFActuatorPosition*> positionSensors;
+        std::vector<ControlTarget1DoFActuatorTorque*> targets;
+
+        // velocity ik controller parameters
+        // dmp parameters
+        double timeDuration;
+        bool finished;
+
+        // phaseStop parameters
+        double phaseL;
+        double phaseK;
+        double phaseDist0;
+        double phaseDist1;
+        double posToOriRatio;
+
+
+        NJointTaskSpaceImpedanceDMPControllerConfigPtr cfg;
+        VirtualRobot::DifferentialIKPtr ik;
+        VirtualRobot::RobotNodePtr tcp;
+
+        float torqueLimit;
+
+        Eigen::Vector3f kpos;
+        Eigen::Vector3f kori;
+        Eigen::Vector3f dpos;
+        Eigen::Vector3f dori;
+        float knull;
+        float dnull;
+
+        DMP::UMIDMPPtr nullSpaceJointDMPPtr;
+        bool useNullSpaceJointDMP;
+        bool isNullSpaceJointDMPLearned;
+        DMP::Vec<DMP::DMPState> currentJointState;
+
+
+        Eigen::VectorXf defaultNullSpaceJointValues;
+        std::vector<std::string> jointNames;
+        mutable MutexType controllerMutex;
+        PeriodicTask<NJointTaskSpaceImpedanceDMPController>::pointer_type controllerTask;
+
+    };
+
+} // namespace armarx
+
diff --git a/source/RobotAPI/libraries/core/CMakeLists.txt b/source/RobotAPI/libraries/core/CMakeLists.txt
index 76beb836204971595ff2b84c4b2f973ea488bb09..9e863f65c7c570d36a34a4c5933c27d0a82253ac 100644
--- a/source/RobotAPI/libraries/core/CMakeLists.txt
+++ b/source/RobotAPI/libraries/core/CMakeLists.txt
@@ -31,6 +31,7 @@ set(LIB_FILES
     FramedOrientedPoint.cpp
     RobotStatechartContext.cpp
     checks/ConditionCheckMagnitudeChecks.cpp
+    observerfilters/PoseAverageFilter.cpp
     observerfilters/PoseMedianOffsetFilter.cpp
     observerfilters/MedianDerivativeFilterV3.cpp
     RobotAPIObjectFactories.cpp
@@ -59,6 +60,7 @@ set(LIB_HEADERS
     FramedOrientedPoint.h
     RobotStatechartContext.h
     observerfilters/PoseMedianFilter.h
+    observerfilters/PoseAverageFilter.h
     observerfilters/PoseMedianOffsetFilter.h
     observerfilters/OffsetFilter.h
     observerfilters/MatrixFilters.h
diff --git a/source/RobotAPI/libraries/core/RobotAPIObjectFactories.cpp b/source/RobotAPI/libraries/core/RobotAPIObjectFactories.cpp
index 0a85c9d8b064d34f62f2cec5aee27daf675a8d7c..e2d22fa0e321fc0ce6c3699466fc24b5002755c0 100644
--- a/source/RobotAPI/libraries/core/RobotAPIObjectFactories.cpp
+++ b/source/RobotAPI/libraries/core/RobotAPIObjectFactories.cpp
@@ -32,6 +32,7 @@
 #include <RobotAPI/libraries/core/observerfilters/OffsetFilter.h>
 #include <RobotAPI/libraries/core/observerfilters/MatrixFilters.h>
 #include <RobotAPI/libraries/core/observerfilters/PoseMedianOffsetFilter.h>
+#include <RobotAPI/libraries/core/observerfilters/PoseAverageFilter.h>
 #include <RobotAPI/libraries/core/observerfilters/MedianDerivativeFilterV3.h>
 #include <RobotAPI/libraries/core/OrientedPoint.h>
 #include <RobotAPI/libraries/core/FramedOrientedPoint.h>
@@ -59,6 +60,7 @@ ObjectFactoryMap RobotAPIObjectFactories::getFactories()
     add<armarx::FramedOrientedPointBase, armarx::FramedOrientedPoint>(map);
 
     add<armarx::PoseMedianFilterBase, armarx::filters::PoseMedianFilter>(map);
+    add<armarx::PoseAverageFilterBase, armarx::filters::PoseAverageFilter>(map);
     add<armarx::PoseMedianOffsetFilterBase, armarx::filters::PoseMedianOffsetFilter>(map);
     add<armarx::MedianDerivativeFilterV3Base, armarx::filters::MedianDerivativeFilterV3>(map);
     add<armarx::OffsetFilterBase, armarx::filters::OffsetFilter>(map);
@@ -69,5 +71,6 @@ ObjectFactoryMap RobotAPIObjectFactories::getFactories()
     add<armarx::MatrixPercentilesFilterBase, armarx::filters::MatrixPercentilesFilter>(map);
     add<armarx::MatrixCumulativeFrequencyFilterBase, armarx::filters::MatrixCumulativeFrequencyFilter>(map);
     add<armarx::TrajectoryBase, armarx::Trajectory>(map);
+
     return map;
 }
diff --git a/source/RobotAPI/libraries/core/observerfilters/PoseAverageFilter.cpp b/source/RobotAPI/libraries/core/observerfilters/PoseAverageFilter.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..e7a3eb89f12d234c31a406b1b54f9b927c937252
--- /dev/null
+++ b/source/RobotAPI/libraries/core/observerfilters/PoseAverageFilter.cpp
@@ -0,0 +1,116 @@
+/*
+ * This file is part of ArmarX.
+ *
+ * Copyright (C) 2011-2017, High Performance Humanoid Technologies (H2T), Karlsruhe Institute of Technology (KIT), all rights reserved.
+ *
+ * ArmarX is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * ArmarX is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * @package    ArmarX
+ * @author     Mirko Waechter( mirko.waechter at kit dot edu)
+ * @date       2018
+ * @copyright  http://www.gnu.org/licenses/gpl-2.0.txt
+ *             GNU General Public License
+ */
+#include "PoseAverageFilter.h"
+
+namespace armarx
+{
+    namespace filters
+    {
+
+        VariantBasePtr PoseAverageFilter::calculate(const Ice::Current& c) const
+        {
+            ScopedLock lock(historyMutex);
+
+            if (dataHistory.size() == 0)
+            {
+                return NULL;
+            }
+
+            VariantTypeId type = dataHistory.begin()->second->getType();
+
+            if ((type == VariantType::Vector3) || (type == VariantType::FramedDirection) || (type == VariantType::FramedPosition))
+            {
+
+                Eigen::Vector3f vec;
+                vec.setZero();
+                std::string frame = "";
+                std::string agent = "";
+                VariantPtr var = VariantPtr::dynamicCast(dataHistory.begin()->second);
+
+                if (type == VariantType::FramedDirection)
+                {
+                    FramedDirectionPtr p = var->get<FramedDirection>();
+                    frame = p->frame;
+                    agent = p->agent;
+                }
+                else if (type == VariantType::FramedPosition)
+                {
+                    FramedPositionPtr p = var->get<FramedPosition>();
+                    frame = p->frame;
+                    agent = p->agent;
+                }
+                Eigen::MatrixXf keypointPositions(dataHistory.size(), 3);
+                int i = 0;
+                for (auto& v : dataHistory)
+                {
+                    VariantPtr v2 = VariantPtr::dynamicCast(v.second);
+                    Eigen::Vector3f value = v2->get<Vector3>()->toEigen();
+                    keypointPositions(i, 0) = value(0);
+                    keypointPositions(i, 1) = value(1);
+                    keypointPositions(i, 2) = value(2);
+                    i++;
+                }
+                vec = keypointPositions.colwise().mean();
+
+
+                if (type == VariantType::Vector3)
+                {
+                    Vector3Ptr vecVar = new Vector3(vec);
+                    return new Variant(vecVar);
+                }
+                else if (type == VariantType::FramedDirection)
+                {
+
+                    FramedDirectionPtr vecVar = new FramedDirection(vec, frame, agent);
+                    return new Variant(vecVar);
+                }
+                else if (type == VariantType::FramedPosition)
+                {
+                    FramedPositionPtr vecVar = new FramedPosition(vec, frame, agent);
+                    return new Variant(vecVar);
+                }
+                else
+                {
+                    ARMARX_WARNING_S << "Implementation missing here";
+                    return NULL;
+                }
+            }
+            else if (type == VariantType::Double)
+            {
+                //                    auto values = SortVariants<double>(dataHistory);
+                //                    return new Variant(values.at(values.size()/2));
+            }
+            else if (type == VariantType::Int)
+            {
+                //                    auto values = SortVariants<int>(dataHistory);
+                //                    return new Variant(values.at(values.size()/2));
+            }
+
+            return AverageFilter::calculate(c);
+        }
+
+
+
+    } // namespace filters
+} // namespace armarx
diff --git a/source/RobotAPI/libraries/core/observerfilters/PoseAverageFilter.h b/source/RobotAPI/libraries/core/observerfilters/PoseAverageFilter.h
new file mode 100644
index 0000000000000000000000000000000000000000..34dae88a939f94111f1507dd8d1aee5132b1fa87
--- /dev/null
+++ b/source/RobotAPI/libraries/core/observerfilters/PoseAverageFilter.h
@@ -0,0 +1,68 @@
+/*
+ * This file is part of ArmarX.
+ *
+ * Copyright (C) 2011-2017, High Performance Humanoid Technologies (H2T), Karlsruhe Institute of Technology (KIT), all rights reserved.
+ *
+ * ArmarX is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * ArmarX is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * @package    ArmarX
+ * @author     Mirko Waechter( mirko.waechter at kit dot edu)
+ * @date       2018
+ * @copyright  http://www.gnu.org/licenses/gpl-2.0.txt
+ *             GNU General Public License
+ */
+#pragma once
+
+#include <ArmarXCore/observers/filters/AverageFilter.h>
+
+#include <RobotAPI/libraries/core/FramedPose.h>
+
+
+
+namespace armarx
+{
+    namespace filters
+    {
+
+        class PoseAverageFilter :
+            public ::armarx::PoseAverageFilterBase,
+            public AverageFilter
+        {
+        public:
+            PoseAverageFilter(int windowSize = 11)
+            {
+                this->windowFilterSize = windowSize;
+            }
+
+            // DatafieldFilterBase interface
+        public:
+            VariantBasePtr calculate(const Ice::Current& c) const override;
+
+            /**
+             * @brief This filter supports: Vector3, FramedDirection, FramedPosition
+             * @return List of VariantTypes
+             */
+            ParameterTypeList getSupportedTypes(const Ice::Current& c) const override
+            {
+                ParameterTypeList result = AverageFilter::getSupportedTypes(c);
+                result.push_back(VariantType::Vector3);
+                result.push_back(VariantType::FramedDirection);
+                result.push_back(VariantType::FramedPosition);
+                return result;
+            }
+        };
+
+    } // namespace
+} // namespace
+
+
diff --git a/source/RobotAPI/libraries/core/remoterobot/RemoteRobot.cpp b/source/RobotAPI/libraries/core/remoterobot/RemoteRobot.cpp
index b1399079c9f1b84f8e323ff41967cfd3480d88c3..cfa6f00629a5d027130a5f0cb76bb8a488a49e09 100644
--- a/source/RobotAPI/libraries/core/remoterobot/RemoteRobot.cpp
+++ b/source/RobotAPI/libraries/core/remoterobot/RemoteRobot.cpp
@@ -477,7 +477,7 @@ namespace armarx
 
             if (!c->setConfig(jointName, jointAngle))
             {
-                ARMARX_WARNING_S << "Joint not known in local copy:" << jointName << ". Skipping..." << endl;
+                ARMARX_WARNING << deactivateSpam(10, jointName) << "Joint not known in local copy:" << jointName << ". Skipping..." << endl;
             }
         }
 
@@ -510,7 +510,7 @@ namespace armarx
 
             if (!c->setConfig(jointName, jointAngle))
             {
-                ARMARX_WARNING_S << "Joint not known in local copy:" << jointName << ". Skipping..." << endl;
+                ARMARX_WARNING << deactivateSpam(10, jointName) << "Joint not known in local copy:" << jointName << ". Skipping..." << endl;
             }
         }