diff --git a/source/RobotAPI/libraries/core/CMakeLists.txt b/source/RobotAPI/libraries/core/CMakeLists.txt
index 9a151bdb8fb2a9b04f696b9a6e17c6c7fe3903b9..24a754acb477f73020bcf123138ec1bd76d6eca2 100644
--- a/source/RobotAPI/libraries/core/CMakeLists.txt
+++ b/source/RobotAPI/libraries/core/CMakeLists.txt
@@ -51,6 +51,7 @@ set(LIB_FILES
 set(LIB_HEADERS
     EigenStl.h
     PIDController.h
+    MultiDimPIDController.h
     Trajectory.h
     TrajectoryController.h
     VectorHelpers.h
diff --git a/source/RobotAPI/libraries/core/MultiDimPIDController.h b/source/RobotAPI/libraries/core/MultiDimPIDController.h
new file mode 100644
index 0000000000000000000000000000000000000000..0d0cce9ec7904331f09394c0bb65f61fba62a09b
--- /dev/null
+++ b/source/RobotAPI/libraries/core/MultiDimPIDController.h
@@ -0,0 +1,238 @@
+/*
+ * 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/core/logging/Logging.h>
+#include <Eigen/Core>
+#include <ArmarXCore/core/exceptions/local/ExpressionException.h>
+#include <ArmarXCore/core/time/TimeUtil.h>
+#include <RobotAPI/libraries/core/math/MathUtils.h>
+
+namespace armarx
+{
+    template <int dimensions = Eigen::Dynamic>
+    class MultiDimPIDControllerTemplate :
+        public Logging
+    {
+    public:
+        typedef Eigen::Matrix<float, dimensions, 1> PIDVectorX;
+
+        MultiDimPIDControllerTemplate(float Kp,
+                                      float Ki,
+                                      float Kd,
+                                      double maxControlValue = std::numeric_limits<double>::max(),
+                                      double maxDerivation = std::numeric_limits<double>::max(),
+                                      bool threadSafe = true,
+                                      std::vector<bool> limitless = {}) :
+            Kp(Kp),
+            Ki(Ki),
+            Kd(Kd),
+            integral(0),
+            derivative(0),
+            previousError(0),
+            maxControlValue(maxControlValue),
+            maxDerivation(maxDerivation),
+            threadSafe(threadSafe),
+            limitless(limitless)
+        {
+            reset();
+        }
+
+        void preallocate(size_t size)
+        {
+            stackAllocations.zeroVec = PIDVectorX::Zero(size);
+            stackAllocations.errorVec = stackAllocations.zeroVec;
+            stackAllocations.direction = stackAllocations.zeroVec;
+            stackAllocations.oldControlValue = stackAllocations.zeroVec;
+        }
+
+        ~MultiDimPIDControllerTemplate() {}
+        void update(const double deltaSec, const PIDVectorX& measuredValue, const PIDVectorX& targetValue)
+        {
+            ScopedRecursiveLockPtr lock = getLock();
+            processValue = measuredValue;
+            target = targetValue;
+
+            stackAllocations.errorVec = target - processValue;
+
+            if (limitless.size() != 0)
+            {
+                ARMARX_CHECK_EQUAL(limitless.size(), (size_t)stackAllocations.errorVec.rows());
+                for (size_t i = 0; i < limitless.size(); i++)
+                {
+                    if (limitless.at(i))
+                    {
+                        stackAllocations.errorVec(i) = math::MathUtils::angleModPI(stackAllocations.errorVec(i));
+                    }
+                }
+            }
+
+
+            double error = stackAllocations.errorVec.norm();
+
+            //double dt = (now - lastUpdateTime).toSecondsDouble();
+            //    ARMARX_INFO << deactivateSpam() << VAROUT(dt);
+            if (!firstRun)
+            {
+                integral += error * deltaSec;
+
+                if (deltaSec > 0.0)
+                {
+                    derivative = (error - previousError) / deltaSec;
+                }
+            }
+
+            firstRun = false;
+            stackAllocations.direction = targetValue; // copy size
+
+            if (error > 0)
+            {
+                stackAllocations.direction = stackAllocations.errorVec.normalized();
+            }
+            else
+            {
+                stackAllocations.direction.setZero();
+            }
+
+            if (controlValue.rows() > 0)
+            {
+                stackAllocations.oldControlValue = controlValue;
+            }
+            else
+            {
+                stackAllocations.oldControlValue = stackAllocations.zeroVec;
+            }
+            controlValue = stackAllocations.direction * (Kp * error + Ki * integral + Kd * derivative);
+
+            if (deltaSec > 0.0)
+            {
+                PIDVectorX accVec = (controlValue - stackAllocations.oldControlValue) / deltaSec;
+                float maxNewJointAcc = accVec.maxCoeff();
+                float minNewJointAcc = accVec.minCoeff();
+                maxNewJointAcc = std::max<float>(fabs(minNewJointAcc), fabs(maxNewJointAcc));
+                if (maxNewJointAcc > maxDerivation)
+                {
+                    auto newValue = stackAllocations.oldControlValue + accVec * maxDerivation / maxNewJointAcc * deltaSec;
+                    ARMARX_DEBUG << deactivateSpam(0.5) << VAROUT(maxDerivation) << VAROUT(maxNewJointAcc) << VAROUT(controlValue)  << VAROUT(stackAllocations.oldControlValue) << VAROUT(newValue);
+                    controlValue = newValue;
+                }
+            }
+
+
+            float max = controlValue.maxCoeff();
+            float min = controlValue.minCoeff();
+            max = std::max<float>(fabs(min), fabs(max));
+
+
+
+            if (max > maxControlValue)
+            {
+                auto newValue = controlValue  * maxControlValue / max;
+                ARMARX_DEBUG << deactivateSpam(0.5) << " Control value to big: " << controlValue << " max value: " << maxControlValue << " new value: " << newValue;
+                controlValue = newValue;
+            }
+            ARMARX_DEBUG << deactivateSpam(0.5) << " error: " << error << " cV: " << (controlValue) <<  " i: " << (Ki * integral) << " d: " << (Kd * derivative) << " dt: " << deltaSec;
+
+            previousError = error;
+            lastUpdateTime += IceUtil::Time::seconds(deltaSec);
+
+        }
+        void update(const PIDVectorX& measuredValue, const PIDVectorX& targetValue)
+        {
+            ScopedRecursiveLockPtr lock = getLock();
+            IceUtil::Time now = TimeUtil::GetTime();
+
+            if (firstRun)
+            {
+                lastUpdateTime = TimeUtil::GetTime();
+            }
+
+            double dt = (now - lastUpdateTime).toSecondsDouble();
+            update(dt, measuredValue, targetValue);
+            lastUpdateTime = now;
+        }
+        const PIDVectorX&
+        getControlValue() const
+        {
+            return controlValue;
+        }
+        void setMaxControlValue(double value)
+        {
+            ScopedRecursiveLockPtr lock = getLock();
+            maxControlValue = value;
+        }
+
+        void reset()
+        {
+            ScopedRecursiveLockPtr lock = getLock();
+            firstRun = true;
+            previousError = 0;
+            integral = 0;
+            lastUpdateTime = TimeUtil::GetTime();
+            //    controlValue.setZero();
+            //    processValue.setZero();
+            //    target.setZero();
+
+
+        }
+        //    protected:
+        float Kp, Ki, Kd;
+        double integral;
+        double derivative;
+        double previousError;
+        PIDVectorX processValue;
+        PIDVectorX target;
+        IceUtil::Time lastUpdateTime;
+        PIDVectorX controlValue;
+        double maxControlValue;
+        double maxDerivation;
+        bool firstRun;
+        mutable  RecursiveMutex mutex;
+        bool threadSafe = true;
+        std::vector<bool> limitless;
+    private:
+
+        struct StackAllocationHelper
+        {
+            PIDVectorX errorVec;
+            PIDVectorX direction;
+            PIDVectorX oldControlValue;
+            PIDVectorX zeroVec;
+        } stackAllocations;
+
+        ScopedRecursiveLockPtr getLock() const
+        {
+            if (threadSafe)
+            {
+                return ScopedRecursiveLockPtr(new ScopedRecursiveLock(mutex));
+            }
+            else
+            {
+                return ScopedRecursiveLockPtr();
+            }
+        }
+    };
+    typedef MultiDimPIDControllerTemplate<> MultiDimPIDController;
+    typedef boost::shared_ptr<MultiDimPIDControllerTemplate<>> MultiDimPIDControllerPtr;
+}
diff --git a/source/RobotAPI/libraries/core/PIDController.cpp b/source/RobotAPI/libraries/core/PIDController.cpp
index 928e8451aee81823951866979f5d0a30321ca70b..e364f8d9bcdc0e688a986cec002390acf32deae0 100644
--- a/source/RobotAPI/libraries/core/PIDController.cpp
+++ b/source/RobotAPI/libraries/core/PIDController.cpp
@@ -25,7 +25,6 @@
 #include "PIDController.h"
 #include <ArmarXCore/core/time/TimeUtil.h>
 #include <RobotAPI/libraries/core/math/MathUtils.h>
-#include <RobotAPI/libraries/core/math/MathUtils.h>
 #include <ArmarXCore/core/exceptions/local/ExpressionException.h>
 
 using namespace armarx;
@@ -162,158 +161,16 @@ double PIDController::getControlValue() const
 }
 
 
-MultiDimPIDController::MultiDimPIDController(float Kp, float Ki, float Kd, double maxControlValue, double maxDerivation, bool threadSafe, std::vector<bool> limitless) :
-    Kp(Kp),
-    Ki(Ki),
-    Kd(Kd),
-    integral(0),
-    derivative(0),
-    previousError(0),
-    maxControlValue(maxControlValue),
-    maxDerivation(maxDerivation),
-    threadSafe(threadSafe),
-    limitless(limitless)
-{
-    reset();
-}
 
-void MultiDimPIDController::update(const double deltaSec, const Eigen::VectorXf& measuredValue, const Eigen::VectorXf& targetValue)
-{
-    ScopedRecursiveLockPtr lock = getLock();
-    processValue = measuredValue;
-    target = targetValue;
 
-    Eigen::VectorXf errorVec = target - processValue;
 
-    if (limitless.size() != 0)
-    {
-        ARMARX_CHECK_EQUAL(limitless.size(), (size_t)errorVec.rows());
-        for (size_t i = 0; i < limitless.size(); i++)
-        {
-            if (limitless.at(i))
-            {
-                errorVec(i) = math::MathUtils::angleModPI(errorVec(i));
-            }
-        }
-    }
 
 
-    double error = errorVec.norm();
 
-    //double dt = (now - lastUpdateTime).toSecondsDouble();
-    //    ARMARX_INFO << deactivateSpam() << VAROUT(dt);
-    if (!firstRun)
-    {
-        integral += error * deltaSec;
 
-        if (deltaSec > 0.0)
-        {
-            derivative = (error - previousError) / deltaSec;
-        }
-    }
-
-    firstRun = false;
-    Eigen::VectorXf direction = targetValue; // copy size
-
-    if (error > 0)
-    {
-        direction = errorVec.normalized();
-    }
-    else
-    {
-        direction.setZero();
-    }
-    Eigen::VectorXf oldControlValue;
-    if (controlValue.rows() > 0)
-    {
-        oldControlValue = controlValue;
-    }
-    else
-    {
-        oldControlValue = Eigen::VectorXf::Zero(measuredValue.rows());
-    }
-    controlValue = direction * (Kp * error + Ki * integral + Kd * derivative);
 
-    if (deltaSec > 0.0)
-    {
-        Eigen::VectorXf accVec = (controlValue - oldControlValue) / deltaSec;
-        float maxNewJointAcc = accVec.maxCoeff();
-        float minNewJointAcc = accVec.minCoeff();
-        maxNewJointAcc = std::max<float>(fabs(minNewJointAcc), fabs(maxNewJointAcc));
-        if (maxNewJointAcc > maxDerivation)
-        {
-            auto newValue = oldControlValue + accVec * maxDerivation / maxNewJointAcc * deltaSec;
-            ARMARX_DEBUG << deactivateSpam(0.5) << VAROUT(maxDerivation) << VAROUT(maxNewJointAcc) << VAROUT(controlValue)  << VAROUT(oldControlValue) << VAROUT(newValue);
-            controlValue = newValue;
-        }
-    }
 
 
-    float max = controlValue.maxCoeff();
-    float min = controlValue.minCoeff();
-    max = std::max<float>(fabs(min), fabs(max));
 
 
 
-    if (max > maxControlValue)
-    {
-        auto newValue = controlValue  * maxControlValue / max;
-        ARMARX_DEBUG << deactivateSpam(0.5) << " Control value to big: " << controlValue << " max value: " << maxControlValue << " new value: " << newValue;
-        controlValue = newValue;
-    }
-    ARMARX_DEBUG << deactivateSpam(0.5) << " error: " << error << " cV: " << (controlValue) <<  " i: " << (Ki * integral) << " d: " << (Kd * derivative) << " dt: " << deltaSec;
-
-    previousError = error;
-    lastUpdateTime += IceUtil::Time::seconds(deltaSec);
-
-}
-
-void MultiDimPIDController::update(const Eigen::VectorXf& measuredValue, const Eigen::VectorXf& targetValue)
-{
-    ScopedRecursiveLockPtr lock = getLock();
-    IceUtil::Time now = TimeUtil::GetTime();
-
-    if (firstRun)
-    {
-        lastUpdateTime = TimeUtil::GetTime();
-    }
-
-    double dt = (now - lastUpdateTime).toSecondsDouble();
-    update(dt, measuredValue, targetValue);
-    lastUpdateTime = now;
-}
-
-const Eigen::VectorXf& MultiDimPIDController::getControlValue() const
-{
-    return controlValue;
-}
-
-void MultiDimPIDController::reset()
-{
-    ScopedRecursiveLockPtr lock = getLock();
-    firstRun = true;
-    previousError = 0;
-    integral = 0;
-    lastUpdateTime = TimeUtil::GetTime();
-    //    controlValue.setZero();
-    //    processValue.setZero();
-    //    target.setZero();
-}
-
-ScopedRecursiveLockPtr MultiDimPIDController::getLock() const
-{
-    if (threadSafe)
-    {
-        return ScopedRecursiveLockPtr(new ScopedRecursiveLock(mutex));
-    }
-    else
-    {
-        return ScopedRecursiveLockPtr();
-    }
-}
-
-void MultiDimPIDController::setMaxControlValue(double value)
-{
-    ScopedRecursiveLockPtr lock = getLock();
-    maxControlValue = value;
-}
diff --git a/source/RobotAPI/libraries/core/PIDController.h b/source/RobotAPI/libraries/core/PIDController.h
index e6e9976b94e31241d086ee513f117d8b3aa81fed..8fa7fba0a9b6a8096e03b343a2cf8cd90f6e2c0a 100644
--- a/source/RobotAPI/libraries/core/PIDController.h
+++ b/source/RobotAPI/libraries/core/PIDController.h
@@ -26,6 +26,7 @@
 
 #include <ArmarXCore/core/logging/Logging.h>
 #include <Eigen/Core>
+#include "MultiDimPIDController.h"
 
 namespace armarx
 {
@@ -69,41 +70,6 @@ namespace armarx
     };
     typedef boost::shared_ptr<PIDController> PIDControllerPtr;
 
-    class MultiDimPIDController :
-        public Logging
-    {
-    public:
-        MultiDimPIDController(float Kp,
-                              float Ki,
-                              float Kd,
-                              double maxControlValue = std::numeric_limits<double>::max(),
-                              double maxDerivation = std::numeric_limits<double>::max(),
-                              bool threadSafe = true,
-                              std::vector<bool> limitless = {});
-        void update(const double deltaSec, const Eigen::VectorXf& measuredValue, const Eigen::VectorXf& targetValue);
-        void update(const Eigen::VectorXf& measuredValue, const Eigen::VectorXf& targetValue);
-        const Eigen::VectorXf& getControlValue() const;
-        void setMaxControlValue(double value);
 
-        void reset();
-        //    protected:
-        float Kp, Ki, Kd;
-        double integral;
-        double derivative;
-        double previousError;
-        Eigen::VectorXf processValue;
-        Eigen::VectorXf target;
-        IceUtil::Time lastUpdateTime;
-        Eigen::VectorXf controlValue;
-        double maxControlValue;
-        double maxDerivation;
-        bool firstRun;
-        mutable  RecursiveMutex mutex;
-        bool threadSafe = true;
-        std::vector<bool> limitless;
-    private:
-        ScopedRecursiveLockPtr getLock() const;
-    };
-    typedef boost::shared_ptr<MultiDimPIDController> MultiDimPIDControllerPtr;
 }