diff --git a/source/RobotAPI/components/units/RobotUnit/CMakeLists.txt b/source/RobotAPI/components/units/RobotUnit/CMakeLists.txt
index 2bbf03b242fa4be240287ca624050274f0af19ca..89a1d7833a64a2bdab3d46d00f07a619f60f32fb 100644
--- a/source/RobotAPI/components/units/RobotUnit/CMakeLists.txt
+++ b/source/RobotAPI/components/units/RobotUnit/CMakeLists.txt
@@ -40,6 +40,7 @@ set(LIB_FILES
     NJointControllers/NJointTrajectoryController.cpp
     NJointControllers/NJointKinematicUnitPassThroughController.cpp
     NJointControllers/NJointHolonomicPlatformUnitVelocityPassThroughController.cpp
+    NJointControllers/NJointTCPController.cpp
 
     Devices/SensorDevice.cpp
     Devices/ControlDevice.cpp
@@ -79,6 +80,7 @@ set(LIB_HEADERS
     NJointControllers/NJointTrajectoryController.h
     NJointControllers/NJointKinematicUnitPassThroughController.h
     NJointControllers/NJointHolonomicPlatformUnitVelocityPassThroughController.h
+    NJointControllers/NJointTCPController.h
 
     Devices/DeviceBase.h
     Devices/SensorDevice.h
diff --git a/source/RobotAPI/components/units/RobotUnit/NJointControllers/NJointTCPController.cpp b/source/RobotAPI/components/units/RobotUnit/NJointControllers/NJointTCPController.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..7f0ef41fa60c6d2881a1575312b3854a925ad2d9
--- /dev/null
+++ b/source/RobotAPI/components/units/RobotUnit/NJointControllers/NJointTCPController.cpp
@@ -0,0 +1,199 @@
+/*
+ * 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       2017
+ * @copyright  http://www.gnu.org/licenses/gpl-2.0.txt
+ *             GNU General Public License
+ */
+#include "NJointTCPController.h"
+#include <VirtualRobot/RobotNodeSet.h>
+#include "../RobotUnit.h"
+
+#define DEFAULT_TCP_STRING "default TCP"
+
+namespace armarx
+{
+
+    NJointControllerRegistration<NJointTCPController> registrationControllerNJointTCPController("NJointTCPController");
+
+    std::string NJointTCPController::getClassName(const Ice::Current&) const
+    {
+        return "NJointTCPController";
+    }
+
+    void NJointTCPController::rtPreActivateController()
+    {
+        xVel = 0;
+        yVel = 0;
+        zVel = 0;
+        rollVel = 0;
+        pitchVel = 0;
+        yawVel = 0;
+    }
+
+    void NJointTCPController::rtRun(const IceUtil::Time& sensorValuesTimestamp, const IceUtil::Time& timeSinceLastIteration)
+    {
+        Eigen::VectorXf x(6);
+        x << this->xVel, yVel, zVel, rollVel, pitchVel, yawVel;
+        Eigen::MatrixXf jacobiInv = ik->getPseudoInverseJacobianMatrix(tcp);
+        Eigen::VectorXf jointTargetVelocities = jacobiInv * x;
+        for (size_t i = 0; i < targets.size(); ++i)
+        {
+            targets.at(i)->velocity = jointTargetVelocities(i);
+        }
+    }
+
+
+    ::armarx::WidgetDescription::WidgetSeq createSliders()
+    {
+        using namespace armarx::WidgetDescription;
+        ::armarx::WidgetDescription::WidgetSeq widgets;
+        auto addSlider = [&](const std::string & label, float limit)
+        {
+            widgets.emplace_back(new Label(false, label));
+            {
+                FloatSliderPtr c_x = new FloatSlider;
+                c_x->name = label;
+                c_x->min = -limit;
+                c_x->defaultValue = 0.0f;
+                c_x->max = limit;
+                widgets.emplace_back(c_x);
+            }
+        };
+
+        addSlider("x", 100);
+        addSlider("y", 100);
+        addSlider("z", 100);
+        addSlider("r", 0.5);
+        addSlider("p", 0.5);
+        addSlider("y", 0.5);
+        return widgets;
+    }
+
+    WidgetDescription::WidgetPtr NJointTCPController::GenerateConfigDescription(const boost::shared_ptr<VirtualRobot::Robot>& robot, const std::map<std::string, ConstControlDevicePtr>& controlDevices, const std::map<std::string, ConstSensorDevicePtr>&)
+    {
+        using namespace armarx::WidgetDescription;
+        HBoxLayoutPtr layout = new HBoxLayout;
+
+        LabelPtr label = new Label;
+        label->text = "nodeset name";
+        layout->children.emplace_back(label);
+        StringComboBoxPtr box = new StringComboBox;
+        box->defaultIndex = 0;
+
+        box->options = robot->getRobotNodeSetNames();
+        box->name = "nodeSetName";
+        layout->children.emplace_back(box);
+
+        LabelPtr labelTCP = new Label;
+        labelTCP->text = "tcp name";
+        layout->children.emplace_back(labelTCP);
+        StringComboBoxPtr boxTCP = new StringComboBox;
+        boxTCP->defaultIndex = 0;
+
+        boxTCP->options = robot->getRobotNodeNames();
+        boxTCP->options.insert(boxTCP->options.begin(), DEFAULT_TCP_STRING);
+        boxTCP->name = "tcpName";
+        layout->children.emplace_back(boxTCP);
+
+        LabelPtr labelMode = new Label;
+        labelMode->text = "mode";
+        layout->children.emplace_back(labelMode);
+        StringComboBoxPtr boxMode = new StringComboBox;
+        boxMode->defaultIndex = 0;
+
+        boxMode->options = {"Position", "Orientation", "Both"};
+        boxMode->name = "mode";
+        layout->children.emplace_back(boxMode);
+
+
+        //        auto sliders = createSliders();
+        //        layout->children.insert(layout->children.end(),
+        //                                sliders.begin(),
+        //                                sliders.end());
+        layout->children.emplace_back(new HSpacer);
+        return layout;
+    }
+
+    NJointTCPControllerConfigPtr NJointTCPController::GenerateConfigFromVariants(const StringVariantBaseMap& values)
+    {
+        return new NJointTCPControllerConfig {values.at("nodeSetName")->getString(), values.at("tcpName")->getString()};
+    }
+
+    NJointTCPController::NJointTCPController(NJointControllerDescriptionProviderInterfacePtr prov, NJointTCPControllerConfigPtr config, const boost::shared_ptr<VirtualRobot::Robot>& r)
+    {
+        ARMARX_CHECK_EXPRESSION(prov);
+        RobotUnitPtr robotUnit = RobotUnitPtr::dynamicCast(prov);
+        ARMARX_CHECK_EXPRESSION(robotUnit);
+        ARMARX_CHECK_EXPRESSION(!config->nodeSetName.empty());
+        auto nodeset = robotUnit->getRtRobot()->getRobotNodeSet(config->nodeSetName);
+        ARMARX_CHECK_EXPRESSION_W_HINT(nodeset, config->nodeSetName);
+        for (size_t i = 0; i < nodeset->getSize(); ++i)
+        {
+            auto jointName = nodeset->getNode(i)->getName();
+            ControlTargetBase* ct = prov->getControlTarget(jointName, ControlModes::Velocity1DoF);
+            const SensorValueBase* sv = prov->getSensorValue(jointName);
+            targets.push_back(ct->asA<ControlTarget1DoFActuatorVelocity>());
+            sensors.push_back(sv->asA<SensorValue1DoFActuatorPosition>());
+        };
+        ik.reset(new VirtualRobot::DifferentialIK(nodeset, robotUnit->getRtRobot()->getRootNode(), VirtualRobot::JacobiProvider::eSVDDamped));
+        tcp = (config->tcpName.empty() || config->tcpName == DEFAULT_TCP_STRING) ? nodeset->getTCP() : robotUnit->getRtRobot()->getRobotNode(config->tcpName);
+        ARMARX_CHECK_EXPRESSION_W_HINT(tcp, config->tcpName);
+    }
+
+    void NJointTCPController::rtPostDeactivateController()
+    {
+
+    }
+
+    WidgetDescription::StringWidgetDictionary NJointTCPController::getFunctionDescriptions(const Ice::Current&) const
+    {
+        using namespace armarx::WidgetDescription;
+        HBoxLayoutPtr layout = new HBoxLayout;
+        auto sliders = createSliders();
+        layout->children.insert(layout->children.end(),
+                                sliders.begin(),
+                                sliders.end());
+        return {{"ControllerConfig", layout}};
+    }
+
+    void NJointTCPController::callDescribedFunction(const std::string& name, const StringVariantBaseMap& valueMap, const Ice::Current&)
+    {
+        if (name == "ControllerConfig")
+        {
+            xVel = valueMap.at("x")->getFloat();
+            yVel = valueMap.at("y")->getFloat();
+            zVel = valueMap.at("z")->getFloat();
+            rollVel = valueMap.at("r")->getFloat();
+            pitchVel = valueMap.at("p")->getFloat();
+            yawVel = valueMap.at("y")->getFloat();
+        }
+        else
+        {
+            ARMARX_WARNING << "Unknown function name called: " << name;
+        }
+    }
+
+
+
+} // namespace armarx
+
+
+
+
diff --git a/source/RobotAPI/components/units/RobotUnit/NJointControllers/NJointTCPController.h b/source/RobotAPI/components/units/RobotUnit/NJointControllers/NJointTCPController.h
new file mode 100644
index 0000000000000000000000000000000000000000..356457a7ea461d0f0755ff4b71328b2d1109be3e
--- /dev/null
+++ b/source/RobotAPI/components/units/RobotUnit/NJointControllers/NJointTCPController.h
@@ -0,0 +1,98 @@
+/*
+ * 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       2017
+ * @copyright  http://www.gnu.org/licenses/gpl-2.0.txt
+ *             GNU General Public License
+ */
+#pragma once
+
+
+#include "NJointController.h"
+#include <VirtualRobot/Robot.h>
+#include <RobotAPI/components/units/RobotUnit/ControlTargets/ControlTarget1DoFActuator.h>
+#include <RobotAPI/components/units/RobotUnit/SensorValues/SensorValue1DoFActuator.h>
+#include <VirtualRobot/IK/DifferentialIK.h>
+
+namespace armarx
+{
+
+    TYPEDEF_PTRS_HANDLE(NJointTCPController);
+    TYPEDEF_PTRS_HANDLE(NJointTCPControllerConfig);
+
+    class NJointTCPControllerConfig : virtual public NJointControllerConfig
+    {
+    public:
+        NJointTCPControllerConfig(std::string const& nodeSetName, const std::string& tcpName):
+            nodeSetName(nodeSetName),
+            tcpName(tcpName)
+        {}
+
+        const std::string nodeSetName;
+        const std::string tcpName;
+    };
+
+
+    class NJointTCPController : public NJointController
+    {
+    public:
+        using ConfigPtrT = NJointTCPControllerConfigPtr;
+        NJointTCPController(NJointControllerDescriptionProviderInterfacePtr prov, const NJointControllerConfigPtr& config, const VirtualRobot::RobotPtr&);
+
+        // NJointControllerInterface interface
+        std::string getClassName(const Ice::Current&) const override;
+        WidgetDescription::StringWidgetDictionary getFunctionDescriptions(const Ice::Current&) const override;
+        void callDescribedFunction(const std::string& name, const StringVariantBaseMap& valueMap, const Ice::Current&) override;
+
+        // NJointController interface
+        void rtRun(const IceUtil::Time& sensorValuesTimestamp, const IceUtil::Time& timeSinceLastIteration) override;
+        static WidgetDescription::WidgetPtr GenerateConfigDescription(
+            const boost::shared_ptr<VirtualRobot::Robot>&,
+            const std::map<std::string, ConstControlDevicePtr>&,
+            const std::map<std::string, ConstSensorDevicePtr>&);
+
+        static NJointTCPControllerConfigPtr GenerateConfigFromVariants(const StringVariantBaseMap& values);
+        NJointTCPController(
+            NJointControllerDescriptionProviderInterfacePtr prov,
+            NJointTCPControllerConfigPtr config,
+            const boost::shared_ptr<VirtualRobot::Robot>& r);
+    protected:
+        void rtPreActivateController() override;
+        void rtPostDeactivateController() override;
+    private:
+        std::vector<ControlTarget1DoFActuatorVelocity*> targets;
+        std::vector<const SensorValue1DoFActuatorPosition*> sensors;
+
+        std::atomic<float> xVel;
+        std::atomic<float> yVel;
+        std::atomic<float> zVel;
+        std::atomic<float> rollVel;
+        std::atomic<float> pitchVel;
+        std::atomic<float> yawVel;
+        VirtualRobot::RobotNodePtr tcp;
+        VirtualRobot::DifferentialIKPtr ik;
+
+
+
+
+
+    };
+
+} // namespace armarx
+
diff --git a/source/RobotAPI/components/units/RobotUnit/NJointControllers/NJointTrajectoryController.cpp b/source/RobotAPI/components/units/RobotUnit/NJointControllers/NJointTrajectoryController.cpp
index 9325ae45b38fce80796974759fc18a71ab439984..2efa4a636ac1370101e116142b1cf16847eddd68 100644
--- a/source/RobotAPI/components/units/RobotUnit/NJointControllers/NJointTrajectoryController.cpp
+++ b/source/RobotAPI/components/units/RobotUnit/NJointControllers/NJointTrajectoryController.cpp
@@ -23,6 +23,7 @@ namespace armarx
                                             cfg->PID_i, cfg->PID_d,
                                             cfg->maxVelocity)));
         }
+        currentPos.resize(cfg->jointNames.size());
     }
 
     std::string NJointTrajectoryController::getClassName(const Ice::Current&) const
@@ -33,40 +34,18 @@ namespace armarx
     void NJointTrajectoryController::rtRun(const IceUtil::Time& sensorValuesTimestamp, const IceUtil::Time& timeSinceLastIteration)
     {
         TIMING_START(TrajectoryControl);
-        const Trajectory& trajectory = *rtGetControlStruct().trajectory;
-        if (startTime.toMicroSeconds() == 0)
+        TrajectoryController& contr = *rtGetControlStruct().trajectory;
+        int i = 0;
+        for (auto& sv : sensors)
         {
-            startTime = sensorValuesTimestamp;
+            currentPos(i) = sv->position;
+            i++;
         }
-        auto timeSinceStart = sensorValuesTimestamp - startTime;
-        if (timeSinceStart.toSecondsDouble() > duration)
+        auto newVelocities = contr.update(timeSinceLastIteration.toSecondsDouble(), currentPos);
+        bool finished = contr.getCurrentTimestamp() >= contr.getTraj()->rbegin()->getTimestamp();
+        for (size_t i = 0; i < targets.size(); ++i)
         {
-            for (size_t d = 0; d < targets.size(); ++d)
-            {
-                targets.at(d)->velocity = 0;
-            }
-        }
-        else
-        {
-            auto positions = trajectory.getStates(timeSinceStart.toSecondsDouble(), 0);
-            auto velocities = trajectory.getStates(timeSinceStart.toSecondsDouble(), 1);
-            //        size_t dim = trajectory->dim();
-
-            for (size_t d = 0; d < targets.size(); ++d)
-            {
-                ARMARX_CHECK_EXPRESSION(d < targets.size());
-                ARMARX_CHECK_EXPRESSION(d < PIDs.size());
-                ARMARX_CHECK_EXPRESSION(d < sensors.size());
-                ARMARX_CHECK_EXPRESSION(d < positions.size());
-                ARMARX_CHECK_EXPRESSION(d < velocities.size());
-                PIDControllerPtr& pid = PIDs.at(d);
-                pid->update(timeSinceLastIteration.toSecondsDouble(),
-                            sensors.at(d)->position,
-                            positions.at(d));
-                double newVel = pid->getControlValue();
-                newVel += velocities.at(1);
-                targets.at(d)->velocity = newVel;
-            }
+            targets.at(i)->velocity = finished ? 0.0f : newVelocities(i);
         }
         TIMING_END(TrajectoryControl);
 
@@ -101,7 +80,7 @@ namespace armarx
         TrajectoryPtr newTraj = new Trajectory();
 
         Ice::DoubleSeq newTimestamps;
-        duration = timeOptimalTraj.getDuration();
+        double duration = timeOptimalTraj.getDuration();
         for (double t = 0.0; t < duration; t += timeStep)
         {
             newTimestamps.push_back(t);
@@ -135,7 +114,7 @@ namespace armarx
         TIMING_END(TrajectoryOptimization);
         ARMARX_INFO << "Trajectory duration: " << newTraj->getTimeLength();
         LockGuardType guard {controlDataMutex};
-        getWriterControlStruct().trajectory = newTraj;
+        getWriterControlStruct().trajectory.reset(new TrajectoryController(newTraj, cfg->PID_p, cfg->PID_i, cfg->PID_d));
         writeControlStruct();
     }
 
diff --git a/source/RobotAPI/components/units/RobotUnit/NJointControllers/NJointTrajectoryController.h b/source/RobotAPI/components/units/RobotUnit/NJointControllers/NJointTrajectoryController.h
index 337ba7e0171072c4b76c66de0cdf7ce225d09c4b..5bde47d194952216ea67decd9881d2c0c7ae8122 100644
--- a/source/RobotAPI/components/units/RobotUnit/NJointControllers/NJointTrajectoryController.h
+++ b/source/RobotAPI/components/units/RobotUnit/NJointControllers/NJointTrajectoryController.h
@@ -5,18 +5,17 @@
 #include <VirtualRobot/Robot.h>
 #include <RobotAPI/interface/units/RobotUnit/NJointTrajectoryController.h>
 #include <RobotAPI/libraries/core/PIDController.h>
-#include <RobotAPI/libraries/core/Trajectory.h>
+#include <RobotAPI/libraries/core/TrajectoryController.h>
 #include <RobotAPI/components/units/RobotUnit/ControlTargets/ControlTarget1DoFActuator.h>
 #include <RobotAPI/components/units/RobotUnit/SensorValues/SensorValue1DoFActuator.h>
 
 
 namespace armarx
 {
-    TYPEDEF_PTRS_HANDLE(NJointHolonomicPlatformUnitVelocityPassThroughController);
     class NJointTrajectoryControllerControlData
     {
     public:
-        TrajectoryPtr trajectory = TrajectoryPtr(new Trajectory());
+        TrajectoryControllerPtr trajectory;
     };
 
     class NJointTrajectoryController :
@@ -38,10 +37,10 @@ namespace armarx
     private:
         //        TrajectoryPtr trajectory;
         IceUtil::Time startTime;
-        double duration = 0;
         std::vector<PIDControllerPtr> PIDs;
         std::vector<ControlTarget1DoFActuatorVelocity*> targets;
         std::vector<const SensorValue1DoFActuatorPosition*> sensors;
+        Eigen::VectorXf currentPos;
         NJointTrajectoryControllerConfigPtr cfg;
         virtual void onInitComponent() override {}
         virtual void onConnectComponent() override {}
diff --git a/source/RobotAPI/libraries/core/CMakeLists.txt b/source/RobotAPI/libraries/core/CMakeLists.txt
index d4b664fbc4187f504993d8b99b80b83835931ce2..5d95a14df4202afb817f3e466fd6192bfd75e65f 100644
--- a/source/RobotAPI/libraries/core/CMakeLists.txt
+++ b/source/RobotAPI/libraries/core/CMakeLists.txt
@@ -23,6 +23,7 @@ set(LIBS RobotAPIInterfaces ArmarXCoreObservers ArmarXCoreStatechart ArmarXCoreE
 set(LIB_FILES
     PIDController.cpp
     Trajectory.cpp
+    TrajectoryController.cpp
     Pose.cpp
     FramedPose.cpp
     LinkedPose.cpp
@@ -41,6 +42,7 @@ set(LIB_HEADERS
     EigenStl.h
     PIDController.h
     Trajectory.h
+    TrajectoryController.h
     VectorHelpers.h
     Pose.h
     FramedPose.h
diff --git a/source/RobotAPI/libraries/core/TrajectoryController.cpp b/source/RobotAPI/libraries/core/TrajectoryController.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..b5781ecb570979260cb4db190f8b1dbe0051cf6d
--- /dev/null
+++ b/source/RobotAPI/libraries/core/TrajectoryController.cpp
@@ -0,0 +1,78 @@
+/*
+ * 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       2017
+ * @copyright  http://www.gnu.org/licenses/gpl-2.0.txt
+ *             GNU General Public License
+ */
+#include "TrajectoryController.h"
+
+namespace armarx
+{
+
+    TrajectoryController::TrajectoryController(const TrajectoryPtr& traj, float kp, float ki, float kd) :
+        traj(traj)
+    {
+        pid.reset(new MultiDimPIDController(kp, ki, kd));
+
+        ARMARX_CHECK_EXPRESSION(traj);
+        currentTimestamp = traj->begin()->getTimestamp();
+        positions.resize(traj->dim(), 1);
+        veloctities.resize(traj->dim(), 1);
+    }
+
+    Eigen::VectorXf TrajectoryController::update(double deltaT, const Eigen::VectorXf currentPosition)
+    {
+        ARMARX_CHECK_EXPRESSION(pid);
+        ARMARX_CHECK_EXPRESSION(traj);
+        ARMARX_CHECK_EQUAL(currentPosition.rows(), traj->dim());
+        int dim = traj->dim();
+        currentTimestamp  = currentTimestamp + deltaT;
+        for (int i = 0; i < dim; ++i)
+        {
+            positions(i) = traj->getState(currentTimestamp, i, 0);
+            veloctities(i) = traj->getState(currentTimestamp, i, 1);
+        }
+        pid->update(deltaT, currentPosition, positions);
+        veloctities += pid->getControlValue();
+        return veloctities;
+    }
+
+    MultiDimPIDControllerPtr TrajectoryController::getPid() const
+    {
+        return pid;
+    }
+
+    void TrajectoryController::setPid(const MultiDimPIDControllerPtr& value)
+    {
+        pid = value;
+    }
+
+    double TrajectoryController::getCurrentTimestamp() const
+    {
+        return currentTimestamp;
+    }
+
+    TrajectoryPtr TrajectoryController::getTraj() const
+    {
+        return traj;
+    }
+
+
+} // namespace armarx
diff --git a/source/RobotAPI/libraries/core/TrajectoryController.h b/source/RobotAPI/libraries/core/TrajectoryController.h
new file mode 100644
index 0000000000000000000000000000000000000000..f8a80e6db1b7e6ec0edbbf2960240e81ba5ffa4a
--- /dev/null
+++ b/source/RobotAPI/libraries/core/TrajectoryController.h
@@ -0,0 +1,55 @@
+/*
+ * 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       2017
+ * @copyright  http://www.gnu.org/licenses/gpl-2.0.txt
+ *             GNU General Public License
+ */
+
+#include "PIDController.h"
+#include "Trajectory.h"
+#pragma once
+
+namespace armarx
+{
+
+    class TrajectoryController
+    {
+    public:
+        TrajectoryController(const TrajectoryPtr& traj, float kp, float ki = 0.0f, float kd = 0.0f);
+        Eigen::VectorXf update(double deltaT, const Eigen::VectorXf currentPosition);
+        MultiDimPIDControllerPtr getPid() const;
+        void setPid(const MultiDimPIDControllerPtr& value);
+
+        double getCurrentTimestamp() const;
+
+        TrajectoryPtr getTraj() const;
+
+    protected:
+        TrajectoryPtr traj;
+        MultiDimPIDControllerPtr pid;
+        double currentTimestamp;
+        Eigen::VectorXf positions;
+        Eigen::VectorXf veloctities;
+
+    };
+    typedef std::shared_ptr<TrajectoryController> TrajectoryControllerPtr;
+
+} // namespace armarx
+
diff --git a/source/RobotAPI/libraries/core/test/TrajectoryTest.cpp b/source/RobotAPI/libraries/core/test/TrajectoryTest.cpp
index b657d0f3a8d9a93c1a6856db492172bab695a521..8c8cf2eaa858a490a570f2b4ba0c65e4f7277ced 100644
--- a/source/RobotAPI/libraries/core/test/TrajectoryTest.cpp
+++ b/source/RobotAPI/libraries/core/test/TrajectoryTest.cpp
@@ -26,6 +26,8 @@
 #include <ArmarXCore/core/test/IceTestHelper.h>
 #include <ArmarXCore/util/json/JSONObject.h>
 #include "../Trajectory.h"
+#include "../TrajectoryController.h"
+#include <random>
 using namespace armarx;
 
 
@@ -257,6 +259,28 @@ BOOST_AUTO_TEST_CASE(TrajectoryCopyIfTest)
     ARMARX_INFO_S << VAROUT(selection);
 }
 
+BOOST_AUTO_TEST_CASE(TrajectoryControllerTest)
+{
+    FloatSeqSeq positions {{ 0, 0, 1 }, { 0, 1, 1 }};
+    TrajectoryPtr traj = new Trajectory(positions, {}, {"joint1", "joint2"});
+
+    TrajectoryController c(traj, 0, 1);
+    float t = 0.0f;
+    float deltaT = 0.001f;
+
+    std::default_random_engine generator;
+    std::normal_distribution<float> distribution(1.0, 0.001);
 
+    Eigen::VectorXf pos = Eigen::VectorXf::Zero(traj->dim(), 1);
+    while (t < 1.0f)
+    {
+        Eigen::VectorXf vel = c.update(deltaT, pos);
+        pos += vel * deltaT *  distribution(generator);
+        ARMARX_INFO /*<< deactivateSpam(0.01)*/ << VAROUT(t) << VAROUT(pos);
+        t += deltaT;
+    }
+
+
+}