diff --git a/source/RobotAPI/interface/units/RobotUnit/NJointTaskSpaceDMPController.ice b/source/RobotAPI/interface/units/RobotUnit/NJointTaskSpaceDMPController.ice
index 8c649d9a730f40156508c14798cbb5b141221332..5160110c036e2db109a98e0f924f7648e9bbfc98 100644
--- a/source/RobotAPI/interface/units/RobotUnit/NJointTaskSpaceDMPController.ice
+++ b/source/RobotAPI/interface/units/RobotUnit/NJointTaskSpaceDMPController.ice
@@ -60,6 +60,7 @@ module armarx
         // velocity controller configuration
         string nodeSetName = "";
         string tcpName = "";
+        string frameName = "";
         NJointTaskSpaceDMPControllerMode::CartesianSelection mode = NJointTaskSpaceDMPControllerMode::eAll;
 
         double maxLinearVel;
diff --git a/source/RobotAPI/libraries/RobotAPINJointControllers/DMPController/NJointTSDMPController.cpp b/source/RobotAPI/libraries/RobotAPINJointControllers/DMPController/NJointTSDMPController.cpp
index 4c9a98199590d9c930eda4415fff212aabd95614..3b59d73217b9b605310c73ab620c5f5654f9dc09 100644
--- a/source/RobotAPI/libraries/RobotAPINJointControllers/DMPController/NJointTSDMPController.cpp
+++ b/source/RobotAPI/libraries/RobotAPINJointControllers/DMPController/NJointTSDMPController.cpp
@@ -41,6 +41,7 @@ namespace armarx
         };
 
         tcp = (cfg->tcpName.empty()) ? rns->getTCP() : rtGetRobot()->getRobotNode(cfg->tcpName);
+        refFrame = (cfg->frameName.empty()) ? rns->getRobot()->getRootNode() : rtGetRobot()->getRobotNode(cfg->frameName);
         ARMARX_CHECK_EXPRESSION_W_HINT(tcp, cfg->tcpName);
 
         // set tcp controller
@@ -48,7 +49,7 @@ namespace armarx
         nodeSetName = cfg->nodeSetName;
         torquePIDs.resize(tcpController->rns->getSize(), pidController());
 
-        ik.reset(new VirtualRobot::DifferentialIK(rns, rns->getRobot()->getRootNode(), VirtualRobot::JacobiProvider::eSVDDamped));
+        ik.reset(new VirtualRobot::DifferentialIK(rns, refFrame, VirtualRobot::JacobiProvider::eSVDDamped));
 
 
         finished = false;
@@ -103,7 +104,9 @@ namespace armarx
             initData.targetTSVel(i) = 0;
             targetVels(i) = 0;
         }
-        initData.targetPose = tcp->getPoseInRootFrame();
+        //        initData.targetPose = tcp->getPoseInRootFrame();
+        initData.targetPose = refFrame->toLocalCoordinateSystem(tcp->getGlobalPose());
+
         initData.nullspaceJointVelocities.resize(tcpController->rns->getSize(), 0);
         initData.torqueKp.resize(tcpController->rns->getSize(), 0);
         initData.torqueKd.resize(tcpController->rns->getSize(), 0);
@@ -212,10 +215,36 @@ namespace armarx
         writeControlStruct();
     }
 
+    Eigen::VectorXf NJointTSDMPController::calcIK(const Eigen::VectorXf& cartesianVel, const Eigen::VectorXf& nullspaceVel,  VirtualRobot::IKSolver::CartesianSelection mode)
+    {
+        Eigen::MatrixXf jacobi = ik->getJacobianMatrix(tcp, mode);
+
+        Eigen::FullPivLU<Eigen::MatrixXf> lu_decomp(jacobi);
+
+        Eigen::MatrixXf nullspace = lu_decomp.kernel();
+        Eigen::VectorXf nsv = Eigen::VectorXf::Zero(nullspace.rows());
+        for (int i = 0; i < nullspace.cols(); i++)
+        {
+            float squaredNorm = nullspace.col(i).squaredNorm();
+            // Prevent division by zero
+            if (squaredNorm > 1.0e-32f)
+            {
+                nsv += nullspace.col(i) * nullspace.col(i).dot(nullspaceVel) / nullspace.col(i).squaredNorm();
+            }
+        }
+
+        Eigen::MatrixXf inv = ik->computePseudoInverseJacobianMatrix(jacobi, ik->getJacobiRegularization(mode));
+        ARMARX_INFO << "inv: " << inv;
+        Eigen::VectorXf jointVel = inv * cartesianVel;
+        //        jointVel += nsv;
+        return jointVel;
+    }
 
     void NJointTSDMPController::rtRun(const IceUtil::Time& sensorValuesTimestamp, const IceUtil::Time& timeSinceLastIteration)
     {
-        Eigen::Matrix4f currentPose = tcp->getPoseInRootFrame();
+        //        Eigen::Matrix4f currentPose = tcp->getPoseInRootFrame();
+        //
+        Eigen::Matrix4f currentPose = refFrame->toLocalCoordinateSystem(tcp->getGlobalPose());
         rt2UserData.getWriteBuffer().currentTcpPose = currentPose;
         rt2UserData.commitWrite();
 
@@ -315,7 +344,9 @@ namespace armarx
                 jnv(i) += rtGetControlStruct().nullspaceJointVelocities.at(i);
             }
 
-            jointTargetVelocities = tcpController->calculate(x, jnv, VirtualRobot::IKSolver::CartesianSelection::All);
+            //            jointTargetVelocities = tcpController->calculate(x, jnv, VirtualRobot::IKSolver::CartesianSelection::All);
+            jointTargetVelocities = calcIK(x, jnv, VirtualRobot::IKSolver::CartesianSelection::All);
+
             ARMARX_CHECK_EXPRESSION(!targets.empty());
             ARMARX_CHECK_LESS(targets.size(), 1000);
         }
diff --git a/source/RobotAPI/libraries/RobotAPINJointControllers/DMPController/NJointTSDMPController.h b/source/RobotAPI/libraries/RobotAPINJointControllers/DMPController/NJointTSDMPController.h
index c48ac700c06800bd4c19c2509b27244ef71899ad..95d31adcc36f1515c608f22e78427eda1e9562c0 100644
--- a/source/RobotAPI/libraries/RobotAPINJointControllers/DMPController/NJointTSDMPController.h
+++ b/source/RobotAPI/libraries/RobotAPINJointControllers/DMPController/NJointTSDMPController.h
@@ -106,6 +106,7 @@ namespace armarx
         std::vector<double> createDMPFromString(const std::string& dmpString, const Ice::Current&) override;
 
         VirtualRobot::IKSolver::CartesianSelection ModeFromIce(const NJointTaskSpaceDMPControllerMode::CartesianSelection mode);
+        Eigen::VectorXf calcIK(const Eigen::VectorXf& cartesianVel, const Eigen::VectorXf& nullspace, VirtualRobot::IKSolver::CartesianSelection mode);
     protected:
         void rtPreActivateController() override;
         void rtPostDeactivateController() override;
@@ -183,6 +184,7 @@ namespace armarx
 
         VirtualRobot::DifferentialIKPtr ik;
         VirtualRobot::RobotNodePtr tcp;
+        VirtualRobot::RobotNodePtr refFrame;
         Eigen::VectorXf targetVels;
         Eigen::Matrix4f targetPose;