diff --git a/source/RobotAPI/interface/CMakeLists.txt b/source/RobotAPI/interface/CMakeLists.txt
index bb2e60cebea178d3758f62838781c68822c2abaa..448c6766549a06a9b396b9687f17f012b5cb43c6 100644
--- a/source/RobotAPI/interface/CMakeLists.txt
+++ b/source/RobotAPI/interface/CMakeLists.txt
@@ -30,7 +30,6 @@ set(SLICE_FILES
     units/KinematicUnitInterface.ice
     units/PlatformUnitInterface.ice
     units/RobotPoseUnitInterface.ice
-    units/RobotUnitInterface.ice
     units/TCPControlUnit.ice
     units/TCPMoverUnitInterface.ice
     units/UnitInterface.ice
@@ -41,6 +40,7 @@ set(SLICE_FILES
     visualization/DebugDrawerInterface.ice
 
     libraries/Controllers/LVL1Controller.ice
+    libraries/Controllers/RobotUnitInterface.ice
 )
     #core/RobotIK.ice
 
diff --git a/source/RobotAPI/interface/libraries/Controllers/LVL1Controller.ice b/source/RobotAPI/interface/libraries/Controllers/LVL1Controller.ice
index 2804d5d293bbf2480e3d12f11dc6873156963843..a229edc6ead598adad1cf61d0af6f630b616a389 100644
--- a/source/RobotAPI/interface/libraries/Controllers/LVL1Controller.ice
+++ b/source/RobotAPI/interface/libraries/Controllers/LVL1Controller.ice
@@ -27,6 +27,7 @@
 
 module armarx
 {
+    dictionary<string, string> JointNameToControlModeDictionary;
     class LVL1ControllerConfig
     {
     };
@@ -35,7 +36,7 @@ module armarx
     {
         ["cpp:const"] idempotent string getClassName();
         ["cpp:const"] idempotent string  getInstanceName();
-        ["cpp:const"] idempotent StringStringDictionary getJointControlModeMap();
+        ["cpp:const"] idempotent JointNameToControlModeDictionary getJointControlModeMap();
         ["cpp:const"] idempotent bool isControllerActive();
     };
 
diff --git a/source/RobotAPI/interface/units/RobotUnitInterface.ice b/source/RobotAPI/interface/libraries/Controllers/RobotUnitInterface.ice
similarity index 60%
rename from source/RobotAPI/interface/units/RobotUnitInterface.ice
rename to source/RobotAPI/interface/libraries/Controllers/RobotUnitInterface.ice
index 1dbee2d22f27ce22bed955b3fd1d0606d99cd360..c30c99739097b72ec8587d78d7bdbd767b0839a7 100644
--- a/source/RobotAPI/interface/units/RobotUnitInterface.ice
+++ b/source/RobotAPI/interface/libraries/Controllers/RobotUnitInterface.ice
@@ -23,6 +23,8 @@
 #ifndef _ARMARX_ROBOTAPI_UNITS_RobotUnit_SLICE_
 #define _ARMARX_ROBOTAPI_UNITS_RobotUnit_SLICE_
 
+#include <ArmarXCore/interface/core/UserException.ice>
+
 #include <RobotAPI/interface/libraries/Controllers/LVL1Controller.ice>
 
 #include <RobotAPI/interface/units/KinematicUnitInterface.ice>
@@ -32,22 +34,37 @@
 
 module armarx
 {
+    dictionary<string, Ice::StringSeq> JointNameToControlModesDictionary;
+
+    dictionary<string, string> JointNameToLVL1Dictionary;
+
     interface RobotUnitInterface
     {
-        //robot
-        ["cpp:const"] idempotent NameControlModeMap getJointControlModeMap();
-
         //controllers
-        ["cpp:const"] idempotent StringLVL1ControllerPrxDictionary getAllControllers();
-        ["cpp:const"] idempotent StringLVL1ControllerPrxDictionary getActiveControllers();
+        //names
+        ["cpp:const"] idempotent Ice::StringSeq getControllersKnown();
+        ["cpp:const"] idempotent Ice::StringSeq getControllerNamesLoaded();
+        ["cpp:const"] idempotent Ice::StringSeq getControllerNamesRequested();
+        ["cpp:const"] idempotent Ice::StringSeq getControllerNamesActivated();
+        //proxy
+        ["cpp:const"] idempotent StringLVL1ControllerPrxDictionary getControllersLoaded();
+        ["cpp:const"] idempotent StringLVL1ControllerPrxDictionary getControllersRequested();
+        ["cpp:const"] idempotent StringLVL1ControllerPrxDictionary getControllersActivated();
+        //assignement
+        ["cpp:const"] idempotent JointNameToLVL1Dictionary getControllerJointAssignment();
+
+        //modes
+        ["cpp:const"] idempotent JointNameToControlModeDictionary  getJointControlModesRequested();
+        ["cpp:const"] idempotent JointNameToControlModeDictionary  getJointControlModesActivated();
+        ["cpp:const"] idempotent JointNameToControlModesDictionary getJointControlModesSupported();
 
-        bool switchSetup(Ice::StringSeq controllerInstanceNames);
-        LVL1ControllerInterface* loadController(string className, string instanceName, Ice::StringSeq joints, LVL1ControllerConfig config);
+        //loading
+        void switchSetup(Ice::StringSeq controllerInstanceNames) throws InvalidArgumentException;
+        LVL1ControllerInterface* loadController(string className, string instanceName, LVL1ControllerConfig config) throws InvalidArgumentException;
 
         ["cpp:const"] idempotent bool loadLibFromPath(string path);
-        ["cpp:const"] idempotent bool loadLibFromPackage(string name, string package);
+        ["cpp:const"] idempotent bool loadLibFromPackage(string package, string lib);
 
-        ["cpp:const"] idempotent ControlModeBoolMap supportedControlModes();
 
         //units
         ["cpp:const"] idempotent KinematicUnitInterface* getKinematicUnit();
diff --git a/source/RobotAPI/libraries/Controllers/LVL1Controller.h b/source/RobotAPI/libraries/Controllers/LVL1Controller.h
index 3d3aca6c310f09f521c3d9beb23afea78ea16c60..e894ca8e2c7e82a1e425a62f7e779d60b8ec62b8 100644
--- a/source/RobotAPI/libraries/Controllers/LVL1Controller.h
+++ b/source/RobotAPI/libraries/Controllers/LVL1Controller.h
@@ -26,18 +26,18 @@
 #include <map>
 #include <atomic>
 #include <mutex>
+#include <functional>
 
 #include <ArmarXCore/core/Component.h>
-#include <ArmarXCore/core/util/TrippleBuffer.h>
+#include <ArmarXCore/core/util/Registrar.h>
+#include <ArmarXCore/core/util/TripleBuffer.h>
 
 #include <RobotAPI/interface/libraries/Controllers/LVL1Controller.h>
 
-#include "RobotUnit.h"
 #include "Targets/JointTargetBase.h"
 
 namespace armarx
 {
-
     class LVL1Controller:
         virtual public LVL1ControllerInterface,
         virtual public Component
@@ -50,7 +50,7 @@ namespace armarx
         }
         virtual std::string getInstanceName(const Ice::Current& = GlobalIceCurrent) const final
         {
-            return instanceName;
+            return getName();
         }
         virtual StringStringDictionary getJointControlModeMap(const Ice::Current& = GlobalIceCurrent) const final
         {
@@ -64,12 +64,25 @@ namespace armarx
     private:
         friend class RobotUnit;
         //this data is filled by the robot unit to provide convenience functions
-        std::string instanceName;
         std::atomic_bool isActive {false};
-        StringStringDictionary jointControlModeMap;
+        JointNameToControlModeDictionary jointControlModeMap;
     };
     using LVL1ControllerPtr = IceInternal::Handle<LVL1Controller>;
 
+    class RobotUnit;
+
+    using LVL1ControllerRegistry = Registrar<std::function<LVL1ControllerPtr(IceInternal::Handle<RobotUnit> robotUnit, LVL1ControllerConfigPtr config)>>;
+    template<class ControllerType>
+    struct LVL1ControllerRegistration
+    {
+        LVL1ControllerRegistration(const std::string& name)
+        {
+            LVL1ControllerRegistry::registerElement(name, [](IceInternal::Handle<RobotUnit> robotUnit, LVL1ControllerConfigPtr config)
+            {
+                return new ControllerType(robotUnit, config);
+            });
+        }
+    };
 
     /**
     * @defgroup Library-Controllers Controllers
@@ -86,15 +99,15 @@ namespace armarx
     //in ice
     module armarx
     {
-    struct SomeControllerConfig extends LVL1ControllerConfig
-    {
-        float paramSetViaConfig;
-    };
+        struct SomeControllerConfig extends LVL1ControllerConfig
+        {
+            float paramSetViaConfig;
+        };
 
-    interface SomeControllerInterface extends LVL1ControllerInterface
-    {
-        void setSomeParamChangedViaIce(float param);
-    };
+        interface SomeControllerInterface extends LVL1ControllerInterface
+        {
+            void setSomeParamChangedViaIce(float param);
+        };
     };
 
 
@@ -102,59 +115,61 @@ namespace armarx
     #include <ArmarXCore/core/exceptions/local/ExpressionException.h>
     namespace armarx
     {
-    struct SomeControlDataStruct
-    {
-        float parameterChangedViaIceCalls;
-    };
-
-    class SomeController : virtual public LVL1Controller<SomeControlDataStruct>,
-        public SomeControllerInterface
-    {
-        JointVelocityTargetPtr targetJointXPtr;
-        std::vector<const float*> jointValuePtrs;
-        float someParamSetViaConfig;
-        ExampleLvl1Controller(RobotUnitPtr robotUnit, LVL1ControllerConfigPtr config):
-            LVL1Controller<SomeControlDataStruct>(SomeControlDataStruct(1)) //initial parameter value
+        struct SomeControlDataStruct
         {
-            //cast the config to your config type
-            SomeControlDataStructPtr someConfig = SomeControlDataStructPtr::dynamicCast(config);
-            ARMARX_CHECK_EXPRESSION_W_HINT(someConfig,
-                                           "The provided config has the wrong type! The type is " << config->ice_id()
-                                           << " instead of " << SomeControllerConfig::ice_staticId());
-            //read the config
-            someParamSetViaConfig = someConfig->parameterSetViaIceCalls
-            //make sure the used units are supported
-            ARMARX_CHECK_EXPRESSION_W_HINT(robotUnit->getKinematicUnitData(), "The RobotUnit " << robotUnit->getName() << " has no kinematic data unit");
-            //get pointers to sensor values from units
-            jointValuePtrs = robotUnit->getKinematicUnitData()->getJointAngles({"jointX", "jointY"});
-
-            //get pointers for the results of this controller
-            targetJointXPtr = dynamic_cast<JointVelocityTarget*>(robotUnit->getJointTarget("jointX", ControlModes::VelocityMode));
-            ARMARX_CHECK_EXPRESSION_W_HINT(targetJointXPtr, "The Joint jointX does not support the mode " + ControlModes::VelocityMode);
-        }
+            float parameterChangedViaIceCalls;
+        };
 
-        ExampleLvl1Controller(JointVelocityTargetPtr targetPtr, ControllerConfigPtr config):
-            targetJointXPtr{targetPtr}
+        class SomeController : virtual public LVL1Controller<SomeControlDataStruct>,
+            public SomeControllerInterface
         {
-
+            JointVelocityTargetPtr targetJointXPtr;
+            std::vector<const float*> jointValuePtrs;
+            float someParamSetViaConfig;
+            SomeController(RobotUnitPtr robotUnit, LVL1ControllerConfigPtr config):
+                LVL1Controller<SomeControlDataStruct>(SomeControlDataStruct(1)) //initial parameter value
+            {
+                //cast the config to your config type
+                SomeControlDataStructPtr someConfig = SomeControlDataStructPtr::dynamicCast(config);
+                ARMARX_CHECK_EXPRESSION_W_HINT(someConfig,
+                                               "The provided config has the wrong type! The type is " << config->ice_id()
+                                               << " instead of " << SomeControllerConfig::ice_staticId());
+                //read the config
+                someParamSetViaConfig = someConfig->parameterSetViaIceCalls
+                //make sure the used units are supported
+                ARMARX_CHECK_EXPRESSION_W_HINT(robotUnit->getKinematicDataUnit(), "The RobotUnit " << robotUnit->getName() << " has no kinematic data unit");
+                //get pointers to sensor values from units
+                jointValuePtrs = robotUnit->getKinematicDataUnit()->getJointAngles({"jointX", "jointY"});
+
+                //get pointers for the results of this controller
+                targetJointXPtr = dynamic_cast<JointVelocityTarget*>(robotUnit->getJointTarget("jointX", ControlModes::VelocityMode));
+                ARMARX_CHECK_EXPRESSION_W_HINT(targetJointXPtr, "The Joint jointX does not support the mode " + ControlModes::VelocityMode);
+            }
+
+            SomeController(JointVelocityTargetPtr targetPtr, ControllerConfigPtr config):
+                targetJointXPtr{targetPtr}
+            {
+
+            }
+
+            virtual void run(const IceUtil::Time& sensorValuesTimestamp, const IceUtil::Time& timeSinceLastIteration) override
+            {
+                pid.update(
+                            rtGetControlStruct().parameterChangedViaIceCalls,
+                            jointValuePtrs.at(0),
+                            timeSinceLastIteration.toMicroSeconds());
+                *targetJointXPtr = pid.getValue() + someParamSetViaConfig;
+            }
+
+            virtual void setSomeParamChangedViaIce(float param, const Ice::Current& = GlobalIceCurrent) override
+            {
+                std::lock_guard<std::recursive_mutex> lock(controlDataMutex);
+                getWriterControlStruct().parameterChangedViaIceCalls = param;
+                writeControlStruct();
+            }
         }
-
-        virtual void run(const IceUtil::Time& sensorValuesTimestamp, const IceUtil::Time& timeSinceLastIteration) override
-        {
-            pid.update(
-                        rtGetControlStruct().parameterChangedViaIceCalls,
-                        jointValuePtrs.at(0),
-                        timeSinceLastIteration.toMicroSeconds());
-            *targetJointXPtr = pid.getValue() + someParamSetViaConfig;
-        }
-
-        virtual void setSomeParamChangedViaIce(float param, const Ice::Current& = GlobalIceCurrent) override
-        {
-            std::lock_guard<std::recursive_mutex> lock(controlDataMutex);
-            getWriterControlStruct().parameterChangedViaIceCalls = param;
-            writeControlStruct();
-        }
-    }
+        //register the controller
+        LVL1ControllerRegistration<SomeController> registrationSomeController("SomeController");
     }
     * \endcode
     */
@@ -163,18 +178,17 @@ namespace armarx
     {
     public:
         LVL1ControllerTemplate(const ControlDataStruct& initialCommands = ControlDataStruct()):
-            controlData {initialCommands},
-        controlDataTrippleBuffer {initialCommands}
+            controlDataTripleBuffer {initialCommands}
         {
         }
     protected:
         const ControlDataStruct& rtGetControlStruct() const
         {
-            return controlDataTrippleBuffer.getReadBuffer();
+            return controlDataTripleBuffer.getReadBuffer();
         }
         bool                     rtUpdateControlStruct()
         {
-            return controlDataTrippleBuffer.getUpToDateData();
+            return controlDataTripleBuffer.getUpToDateData();
         }
         virtual void rtSwapBufferAndRun(const IceUtil::Time& sensorValuesTimestamp, const IceUtil::Time& timeSinceLastIteration) override
         {
@@ -188,17 +202,16 @@ namespace armarx
             //also this allows code to unlock the mutex before calling this function
             //(can happen if some lockguard in a scope is used)
             std::lock_guard<std::recursive_mutex> lock(controlDataMutex);
-            controlDataTrippleBuffer.getWriteBuffer() = controlData;
+            controlDataTripleBuffer.commitWrite();
         }
         ControlDataStruct& getWriterControlStruct()
         {
-            return controlData;
+            return controlDataTripleBuffer.getWriteBuffer();
         }
 
         mutable std::recursive_mutex controlDataMutex;
     private:
-        TripleBuffer<ControlDataStruct> controlDataTrippleBuffer;
-        ControlDataStruct controlData;
+        WriteBufferedTripleBuffer<ControlDataStruct> controlDataTripleBuffer;
     };
     template <typename ControlDataStruct>
     using LVL1ControllerTemplatePtr = IceInternal::Handle<LVL1ControllerTemplate<ControlDataStruct>>;
diff --git a/source/RobotAPI/libraries/Controllers/RobotUnit.cpp b/source/RobotAPI/libraries/Controllers/RobotUnit.cpp
index 20f7b7b2d9382d167ccf8677c3948243b915bc4d..2a070fd777cc95776278b49adb087c706b21e2a0 100644
--- a/source/RobotAPI/libraries/Controllers/RobotUnit.cpp
+++ b/source/RobotAPI/libraries/Controllers/RobotUnit.cpp
@@ -22,36 +22,292 @@
 
 #include "RobotUnit.h"
 
+armarx::PropertyDefinitionsPtr armarx::RobotUnit::createPropertyDefinitions()
+{
+    return armarx::PropertyDefinitionsPtr(new RobotUnitPropertyDefinitions(getConfigIdentifier()));
+}
 
-//using namespace armarx;
+Ice::StringSeq armarx::RobotUnit::getControllersKnown(const Ice::Current&) const
+{
+    return LVL1ControllerRegistry::getKeys();
+}
 
+Ice::StringSeq armarx::RobotUnit::getControllerNamesLoaded(const Ice::Current&) const
+{
+    GuardType guard {dataMutex};
+    Ice::StringSeq result;
+    result.reserve(lvl1Controllers.size());
+    for (const auto& lvl1 : lvl1Controllers)
+    {
+        result.emplace_back(lvl1.first);
+    }
+    return result;
+}
+Ice::StringSeq armarx::RobotUnit::getControllerNamesRequested(const Ice::Current&) const
+{
+    GuardType guard {dataMutex};
+    Ice::StringSeq result;
+    result.reserve(lvl1Controllers.size());
+    for (const auto& lvl1 : controllersRequested.getWriteBuffer().lvl1Controllers)
+    {
+        result.emplace_back(lvl1->getName());
+    }
+    return result;
+}
+Ice::StringSeq armarx::RobotUnit::getControllerNamesActivated(const Ice::Current&) const
+{
+    GuardType guard {dataMutex};
+    Ice::StringSeq result;
+    result.reserve(lvl1Controllers.size());
+    for (const auto& lvl1 : controllersActivated.getUpToDateReadBuffer().lvl1Controllers)
+    {
+        result.emplace_back(lvl1->getName());
+    }
+    return result;
+}
 
-//void RobotUnit::onInitComponent()
-//{
+armarx::StringLVL1ControllerPrxDictionary armarx::RobotUnit::getControllersLoaded(const Ice::Current&) const
+{
+    GuardType guard {dataMutex};
+    StringLVL1ControllerPrxDictionary result;
+    for (const auto& lvl1 : lvl1Controllers)
+    {
+        result[lvl1.first] = LVL1ControllerInterfacePrx::uncheckedCast(lvl1.second->getProxy());
+    }
+    return result;
+}
+armarx::StringLVL1ControllerPrxDictionary armarx::RobotUnit::getControllersRequested(const Ice::Current&) const
+{
+    GuardType guard {dataMutex};
+    StringLVL1ControllerPrxDictionary result;
+    for (const auto& lvl1 : controllersRequested.getWriteBuffer().lvl1Controllers)
+    {
+        result[lvl1->getName()] = LVL1ControllerInterfacePrx::uncheckedCast(lvl1->getProxy());
+    }
+    return result;
+}
+armarx::StringLVL1ControllerPrxDictionary armarx::RobotUnit::getControllersActivated(const Ice::Current&) const
+{
+    GuardType guard {dataMutex};
+    StringLVL1ControllerPrxDictionary result;
+    for (const auto& lvl1 : controllersActivated.getUpToDateReadBuffer().lvl1Controllers)
+    {
+        result[lvl1->getName()] = LVL1ControllerInterfacePrx::uncheckedCast(lvl1->getProxy());
+    }
+    return result;
+}
 
-//}
+armarx::JointNameToLVL1Dictionary armarx::RobotUnit::getControllerJointAssignment(const Ice::Current&) const
+{
+    GuardType guard {dataMutex};
+    JointNameToLVL1Dictionary result;
+    for (const auto& lvl1 : controllersActivated.getUpToDateReadBuffer().lvl1Controllers)
+    {
+        for (const auto& jointMode : lvl1->jointControlModeMap)
+        {
+            result[jointMode.first] = lvl1->getName();
+        }
+    }
+    return result;
+}
 
+armarx::JointNameToControlModeDictionary armarx::RobotUnit::getJointControlModesRequested(const Ice::Current&) const
+{
+    GuardType guard {dataMutex};
+    JointNameToControlModeDictionary result;
+    const auto& requestedModes = controllersRequested.getWriteBuffer().lvl0Controllers;
+    ARMARX_CHECK_AND_THROW(jointNames.size() == requestedModes.size(), std::logic_error);
+    for (std::size_t i = 0; i < jointNames.size(); ++i)
+    {
+        result[jointNames.at(i)] = requestedModes.at(i)->getControlMode();
+    }
+    return result;
+}
+armarx::JointNameToControlModeDictionary armarx::RobotUnit::getJointControlModesActivated(const Ice::Current&) const
+{
+    GuardType guard {dataMutex};
+    JointNameToControlModeDictionary result;
+    const auto& activatedModes = controllersActivated.getUpToDateReadBuffer().lvl0Controllers;
+    ARMARX_CHECK_AND_THROW(jointNames.size() == activatedModes.size(), std::logic_error);
+    for (std::size_t i = 0; i < jointNames.size(); ++i)
+    {
+        result[jointNames.at(i)] = activatedModes.at(i)->getControlMode();
+    }
+    return result;
+}
+armarx::JointNameToControlModesDictionary armarx::RobotUnit::getJointControlModesSupported(const Ice::Current&) const
+{
+    GuardType guard {dataMutex};
+    JointNameToControlModesDictionary result;
+    for (const auto& joint : lvl0Controllers)
+    {
+        std::vector<std::string> modes;
+        modes.reserve(joint.second.size());
+        for (const auto& mode : joint.second)
+        {
+            modes.emplace_back(mode.first);
+        }
+        result[joint.first] = std::move(modes);
+    }
+    return result;
+}
 
-//void RobotUnit::onConnectComponent()
-//{
+void armarx::RobotUnit::switchSetup(const Ice::StringSeq& controllerRequestedNames, const Ice::Current&)
+{
+    GuardType guard {dataMutex};
+    //check if all of these controllers exist
+    for (const auto& lvl1 : controllerRequestedNames)
+    {
+        if (!hasLVL1Controller(lvl1))
+        {
+            ARMARX_ERROR << "No controler of the name '" << lvl1 << "' is loaded!";
+            throw InvalidArgumentException {"No controler of the name '" + lvl1 + "' is loaded!"};
+        }
+    }
+    //check controllers (is there a collision/which controllers need to be deactivated)
+    const auto currentActiveLVL1Controllers = getControllerNamesActivated();
+    auto lvl1ControllerAssignement = getControllerJointAssignment();
 
-//}
+    ARMARX_INFO << "current active lvl1 controllers:\n" << currentActiveLVL1Controllers;
 
+    std::set<std::string> controllersToActivate {currentActiveLVL1Controllers.begin(), currentActiveLVL1Controllers.end()}; //these controllers will be set as active controllers
 
-//void RobotUnit::onDisconnectComponent()
-//{
+    for (const auto& toActivate : controllerRequestedNames)
+    {
+        if (controllersToActivate.count(toActivate))
+        {
+            ARMARX_INFO << "controller already active: " << toActivate;
+            continue;
+        }
+        controllersToActivate.emplace(toActivate);
+        ARMARX_INFO << "activate '" << toActivate << "'";
+        const auto& lvl1 = lvl1Controllers.at(toActivate);
+        //check and update the assignement map
+        for (const auto& jointControlMode : lvl1->jointControlModeMap)
+        {
+            const auto& joint = jointControlMode.first;
+            const auto& currentAssignedLVL1 = lvl1ControllerAssignement.at(joint);
+            if (toActivate == currentAssignedLVL1)
+            {
+                continue;
+            }
+            if (currentAssignedLVL1.empty())
+            {
+                lvl1ControllerAssignement[joint] = toActivate;
+                continue;
+            }
+            //deactivate other controller
+            for (auto& assignement : lvl1ControllerAssignement)
+            {
+                if (assignement.second == currentAssignedLVL1)
+                {
+                    assignement.second.clear();
+                }
+            }
+            controllersToActivate.erase(currentAssignedLVL1);
+            ARMARX_INFO << "deactivated '" << currentAssignedLVL1 << "' (caused by activation of '" << toActivate << "')";
+            lvl1ControllerAssignement[joint] = toActivate;
+        }
+    }
+    //verify (exception for collision of requested lvl1)
+    for (const auto& toActivate : controllerRequestedNames)
+    {
+        if (!controllersToActivate.count(toActivate))
+        {
+            switchSetupError = true;
+            ARMARX_ERROR << "The given set of controllers is in conflict and could not be activated! (conflicting is: " + toActivate + ")";
+            throw InvalidArgumentException {"The given set of controllers is in conflict and could not be activated! (conflicting is: " + toActivate + ")"};
+        }
+    }
+    //verify (warn for orphant joints) + populate controllersRequested.lvl0Controllers
+    controllersRequested.getWriteBuffer().lvl0Controllers.resize(jointNames.size());
+    for (std::size_t i = 0; i < jointNames.size(); ++i)
+    {
+        const auto& joint = jointNames.at(i);
+        if (lvl1ControllerAssignement[joint].empty())
+        {
+            controllersRequested.getWriteBuffer().lvl0Controllers.at(i) = lvl0Controllers.at(joint).at(ControlModes::EmergencyStopMode);
+            ARMARX_WARNING << "Joint '" << joint << "' has no lvl1 controller assigned!";
+            continue;
+        }
+        const auto& lvl0Mode = lvl1Controllers.at(lvl1ControllerAssignement[joint])->jointControlModeMap.at(joint);
+        controllersRequested.getWriteBuffer().lvl0Controllers.at(i) = lvl0Controllers.at(joint).at(lvl0Mode);
+    }
+    //populate controllersRequested.lvl1Controllers
+    controllersRequested.getWriteBuffer().lvl1Controllers.clear();
+    controllersRequested.getWriteBuffer().lvl1Controllers.reserve(controllersToActivate.size());
+    for (const auto& lvl1 : controllersToActivate)
+    {
+        controllersRequested.getWriteBuffer().lvl1Controllers.emplace_back(lvl1Controllers.at(lvl1));
+    }
 
-//}
+    //now change the assignement
+    controllersRequested.commitWrite();
+    ARMARX_INFO << "requested lvl1 controllers:\n" << getControllerNamesRequested();
+}
 
+armarx::LVL1ControllerInterfacePrx armarx::RobotUnit::loadController(const std::string& className, const std::string& instanceName, const armarx::LVL1ControllerConfigPtr& config, const Ice::Current&)
+{
+    if (instanceName.empty())
+    {
+        ARMARX_ERROR << "The instance name is empty!";
+        throw InvalidArgumentException {"The instance name is empty!"};
+    }
+    //check if we would be able to create the class
+    if (!LVL1ControllerRegistry::has(className))
+    {
+        std::stringstream ss;
+        ss << "Requested controller class '" << className << "' unknown! Known classes:" << LVL1ControllerRegistry::getKeys();
+        ARMARX_ERROR << ss.str();
+        throw InvalidArgumentException {ss.str()};
+    }
+    auto factory = LVL1ControllerRegistry::get(className);
 
-//void RobotUnit::onExitComponent()
-//{
+    GuardType guard {dataMutex};
+    //check if the instance name is already in use
+    if (hasLVL1Controller(instanceName))
+    {
+        std::stringstream ss;
+        ss << "There already is a controller instance with the name '" << instanceName << "'";
+        ARMARX_ERROR << ss.str();
+        throw InvalidArgumentException {ss.str()};
+    }
+    //create the controler
+    jointsUsedByLVL1Controler.clear();
+    LVL1ControllerPtr lvl1 = factory(this, config);
+    lvl1->jointControlModeMap = jointsUsedByLVL1Controler;
+    getArmarXManager()->addObject(lvl1, instanceName);
+    const auto prx = lvl1->getProxy(-1);
+    lvl1Controllers[instanceName] = lvl1;
+    return LVL1ControllerInterfacePrx::uncheckedCast(prx);
+}
 
-//}
+armarx::JointTargetBase* armarx::RobotUnit::getJointTarget(const std::string& jointName, const std::string& controlMode)
+{
+    GuardType guard {dataMutex};
+    if (!hasLVL0Controller(jointName, controlMode))
+    {
+        return nullptr;
+    }
+    const auto& lvl0 = lvl0Controllers.at(jointName).at(controlMode);
+    if (!lvl0)
+    {
+        return nullptr;
+    }
+    ARMARX_CHECK_EXPRESSION(lvl0->getControlMode() == controlMode);
+    jointsUsedByLVL1Controler[jointName] = controlMode;
+    return lvl0->getTarget();
+}
 
-//armarx::PropertyDefinitionsPtr RobotUnit::createPropertyDefinitions()
-//{
-//    return armarx::PropertyDefinitionsPtr(new RobotUnitPropertyDefinitions(
-//            getConfigIdentifier()));
-//}
+bool armarx::RobotUnit::hasLVL1Controller(const std::string& name) const
+{
+    GuardType guard {dataMutex};
+    return lvl1Controllers.end() != lvl1Controllers.find(name);
+}
 
+bool armarx::RobotUnit::hasLVL0Controller(const std::string& jointName, const std::string& controlMode) const
+{
+    GuardType guard {dataMutex};
+    return lvl0Controllers.end()               != lvl0Controllers.find(jointName) &&
+           lvl0Controllers.at(jointName).end() != lvl0Controllers.at(jointName).find(controlMode);
+}
diff --git a/source/RobotAPI/libraries/Controllers/RobotUnit.h b/source/RobotAPI/libraries/Controllers/RobotUnit.h
index c4659b75242b8626316e5ead6d5d60306c64763e..d8c971d565aa41afbf76200d256266835e67a7f0 100644
--- a/source/RobotAPI/libraries/Controllers/RobotUnit.h
+++ b/source/RobotAPI/libraries/Controllers/RobotUnit.h
@@ -30,11 +30,20 @@
 #include <unordered_map>
 
 #include <ArmarXCore/core/Component.h>
+#include <ArmarXCore/core/ArmarXManager.h>
+#include <ArmarXCore/core/exceptions/local/ExpressionException.h>
 #include <ArmarXCore/core/util/algorithm.h>
-#include <ArmarXCore/core/util/OnScopeExit.h>
+#include <ArmarXCore/core/util/TripleBuffer.h>
 
-#include <RobotAPI/interface/units/RobotUnitInterface.h>
-#include <RobotAPI/libraries/Controllers/LVL0Controller.h>
+#include <RobotAPI/interface/libraries/Controllers/RobotUnitInterface.h>
+#include "LVL0Controller.h"
+#include "LVL1Controller.h"
+
+#include "DataUnits/ForceTorqueDataUnit.h"
+#include "DataUnits/HapticDataUnit.h"
+#include "DataUnits/IMUDataUnit.h"
+#include "DataUnits/KinematicDataUnit.h"
+#include "DataUnits/PlatformDataUnit.h"
 
 namespace armarx
 {
@@ -70,255 +79,94 @@ namespace armarx
         virtual public armarx::RobotUnitInterface
     {
     public:
-        //        /**
-        //         * @see armarx::ManagedIceObject::getDefaultName()
-        //         */
-        //        virtual std::string getDefaultName() const
-        //        {
-        //            return "RobotUnit";
-        //        }
-
-        //        // RobotUnitInterface interface
-        //        //robot
-        //        virtual NameControlModeMap getJointControlModeMap(const Ice::Current& = GlobalIceCurrent) const override;
-
-        //        //controllers
-        //        virtual StringLVL1ControllerPrxDictionary getAllControllers(const Ice::Current& = GlobalIceCurrent) const override
-        //        {
-        //            std::lock_guard<std::mutex> guard {slowDataMutex};
-        //            StringLVL1ControllerPrxDictionary result;
-        //            std::transform(
-        //                loadedLVL1Controllers.begin(), loadedLVL1Controllers.end(), std::back_inserter(result),
-        //                [](const LVL1ControllerPtr & lvl1)
-        //            {
-        //                return std::make_pair(lvl1->getName(), lvl1->getProxy());
-        //            }
-        //            );
-        //            return result;
-        //        }
-        //        virtual StringLVL1ControllerPrxDictionary getActiveControllers(const Ice::Current& = GlobalIceCurrent) const override
-        //        {
-        //            std::lock_guard<std::mutex> guard {slowDataMutex};
-        //            StringLVL1ControllerPrxDictionary result;
-        //            std::transform(
-        //                activeLVL1Controllers.begin(), activeLVL1Controllers.end(), std::back_inserter(result),
-        //                [](const LVL1ControllerPtr & lvl1)
-        //            {
-        //                return std::make_pair(lvl1->getName(), lvl1->getProxy());
-        //            }
-        //            );
-        //            return result;
-        //        }
-
-        //        virtual bool switchSetup(const Ice::StringSeq&, const Ice::Current& = GlobalIceCurrent) override;
-        //        virtual LVL1ControllerInterfacePrx loadController(
-        //            const std::string& className, const std::string& instanceName, const Ice::StringSeq& joints, const LVL1ControllerConfigPtr&,
-        //            const Ice::Current& = GlobalIceCurrent) override;
-
-
-        //        virtual bool loadLibFromPath(const std::string& path, const Ice::Current& = GlobalIceCurrent) const override
-        //        {
-        //            throw "NYI";   ///TODO mirko
-        //        }
-        //        virtual bool loadLibFromPackage(const std::string& package, const std::string& name, const Ice::Current& = GlobalIceCurrent) const override
-        //        {
-        //            throw "NYI";   ///TODO mirko
-        //        }
-        //        //units
-        //        virtual KinematicUnitInterfacePrx getKinematicUnit(const Ice::Current& = GlobalIceCurrent) const override
-        //        {
-        //            return kinematicUnitPrx;
-        //        }
-        //        virtual ForceTorqueUnitInterfacePrx getForceTorqueUnit(const Ice::Current& = GlobalIceCurrent) const override
-        //        {
-        //            return forceTorqueUnitPrx;
-        //        }
-        //        virtual InertialMeasurementUnitInterfacePrx getInertialMeasurementUnit(const Ice::Current& = GlobalIceCurrent) const override
-        //        {
-        //            return inertialMeasurementUnitPrx;
-        //        }
-        //        virtual PlatformUnitInterfacePrx getPlatformUnitInterface(const Ice::Current& = GlobalIceCurrent) const override
-        //        {
-        //            return platformUnitPrx;
-        //        }
-
-        //        //functions subclasses need to implement
-        //        virtual ControlModeBoolMap supportedControlModes(const Ice::Current& = GlobalIceCurrent) = 0;
-        //        virtual void initializeLVL0Controllers() = 0;
-        //        virtual void initializeBus() = 0;
-        //        virtual void copyControlBufferOut() = 0;
-        //        /**
-        //         * @brief send and receive data on the bus
-        //         */
-        //        virtual void sendReceiveData() = 0;
-        //        virtual void shutdownBus() = 0;
-        //        virtual void emergencyStop() = 0;
-        //        //        virtual void stopRobot() = 0; // may be implemented as {emergencyStop();}
-
-        //        virtual void controlLoopIteration()
-        //        {
-        //            ///how bridge loop while controllers are switched? (need some halt mode)
-        //            for (auto& lvl1 : activeLVL1Controllers)
-        //            {
-        //                lvl1->run();
-        //            }
-        //            for (auto& lvl0 : activeLVL0Controllers)
-        //            {
-        //                lvl0->run();
-        //            }
-        //            copyControlBufferOut();
-        //            sendReceiveData();
-        //        }
-
-        //    protected:
-        //        /**
-        //         * @see armarx::ManagedIceObject::onInitComponent()
-        //         */
-        //        virtual void onInitComponent() override
-        //        {
-
-        //            jointIndices = toIndexMap(jointNames);
-        //            rtControlThread = std::thread {[this]{rtControlThread();}};
-        //        }
-
-        //        /**
-        //         * @see armarx::ManagedIceObject::onConnectComponent()
-        //         */
-        //        virtual void onConnectComponent() override;
-
-        //        /**
-        //         * @see armarx::ManagedIceObject::onDisconnectComponent()
-        //         */
-        //        virtual void onDisconnectComponent() override;
-
-        //        /**
-        //         * @see armarx::ManagedIceObject::onExitComponent()
-        //         */
-        //        virtual void onExitComponent() override;
-
-        //        /**
-        //         * @see PropertyUser::createPropertyDefinitions()
-        //         */
-        //        virtual armarx::PropertyDefinitionsPtr createPropertyDefinitions() override;
-
-        //        //slow data (data changed in non rt threads)
-        //        mutable std::mutex slowDataMutex;
-        //        std::vector<LVL1ControllerPtr> loadedLVL1Controllers;
-
-
-        //        //slow data: running data (this data changes only in switchSetup)
-        //        NameControlModeMap jointControlModes;
-        //        std::vector<LVL1ControllerPtr> activeLVL1Controllers;
-        //        std::vector<LVL0ControllerBase*> activeLVL0Controllers;
-
-        //        //        //slow data: units
-        //        //        KinematicUnitInterfacePtr kinematicUnit;
-        //        //        KinematicUnitInterfacePrx kinematicUnitPrx;
-        //        //        ForceTorqueUnitInterfacePtr forceTorqueUnit;
-        //        //        ForceTorqueUnitInterfacePrx forceTorqueUnitPrx;
-        //        //        InertialMeasurementUnitInterfacePtr inertialMeasurementUnit;
-        //        //        InertialMeasurementUnitInterfacePrx inertialMeasurementUnitPrx;
-        //        //        PlatformUnitInterfacePtr platformUnit;
-        //        //        PlatformUnitInterfacePrx platformUnitPrx;
-
-        //        //constant data (this data does not change after onInitComponent)
-        //        std::vector<std::string> jointNames;
-        //        std::unordered_map<std::string, std::size_t> jointIndices;
-        //        std::chrono::nanoseconds controlLoopPeriod;
-        //        std::chrono::nanoseconds controlLoopEmergencyStopPeriod;
-        //        std::map<std::string, std::vector<LVL0ControllerBase*>> lvl0ControllerMap;
-
-        //    private:
-        //        enum class ControlThreadState
-        //        {
-        //            Unborn,
-        //            Uninitialized,
-        //            ControllerLoop,
-        //            /**
-        //             * @brief The LVL1 controllers are switched.
-        //             * The controller loop now bridges this period.
-        //             */
-        //            BridgingControllerSwitch,
-        //            Exception,
-        //            Dead
-        //        };
-
-        //        //fast data (used in rt threads)
-        //        std::thread rtControlThread;
-        //        std::atomic_bool stopControlLoop {false};
-        //        std::atomic<ControlThreadState> controlThreadState {ControlThreadState::Unborn};
-        //        std::atomic_bool requestBridging {true};
-        //        void rtControlThreadFunction()
-        //        {
-        //            controlThreadState = ControlThreadState::Uninitialized;
-        //            initializeBus();
-        //            ARMARX_ON_SCOPE_EXIT
-        //            {
-        //                shutdownBus();
-        //                controlThreadState = ControlThreadState::Dead;
-        //            };
-        //            try
-        //            {
-        //                initializeLVL0Controllers();
-        //                //validate
-        //                for (const auto& mode : supportedControlModes)
-        //                {
-        //                    switch (mode.first)
-        //                    {
-        //#define ERROR_HEAD "Wrong number of LVL0Controllers for"
-        //#define ERROR_TAIL ". (If supported, each joint needs one controller. If unsupported no controllers must be initialized!"
-        //                        case ePositionControl:
-        //                            if (lvl0PositionControlController.size() != mode.second * jointNames.size())
-        //                            {
-        //                                throw std::invalid_argument {ERROR_HEAD "ePositionControl" ERROR_TAIL};
-        //                            }
-        //                            break;
-        //                        case eVelocityControl:
-        //                            if (lvl0VelocityControlController.size() != mode.second * jointNames.size())
-        //                            {
-        //                                throw std::invalid_argument {ERROR_HEAD "eVelocityControl" ERROR_TAIL};
-        //                            }
-        //                            break;
-        //                        case eTorqueControl:
-        //                            if (lvl0TorqueControlController.size() != mode.second * jointNames.size())
-        //                            {
-        //                                throw std::invalid_argument {ERROR_HEAD "eTorqueControl" ERROR_TAIL};
-        //                            }
-        //                            break;
-        //                        case ePositionVelocityControl:
-        //                            if (lvl0PositionVelocityControlController.size() != mode.second * jointNames.size())
-        //                            {
-        //                                throw std::invalid_argument {ERROR_HEAD "ePositionVelocityControl" ERROR_TAIL};
-        //                            }
-        //                            break;
-        //#undef ERROR_HEAD
-        //#undef ERROR_TAIL
-        //                        default:
-        //                            if (mode.second)
-        //                            {
-        //                                throw std::invalid_argument {"Unknown ControlMode supported! mode = " + std::to_string(mode.first)};
-        //                            }
-        //                    }
-        //                }
-        //                controlThreadState = ControlThreadState::ControllerLoop;///TODO bridging
-        //                //loop
-        //                while (!stopControlLoop)
-        //                {
-        //                    auto iterationStartTime = std::chrono::high_resolution_clock::now();
-        //                    controlLoopIteration();
-        //                    std::this_thread::sleep_until(iterationStartTime + controlLoopPeriod);
-        //                }
+        using MutexType = std::recursive_mutex;
+        using GuardType = std::lock_guard<MutexType>;
+        //controllers
+        virtual Ice::StringSeq getControllersKnown(const Ice::Current& = GlobalIceCurrent) const override;
+        virtual Ice::StringSeq getControllerNamesLoaded(const Ice::Current& = GlobalIceCurrent) const override;
+        virtual Ice::StringSeq getControllerNamesRequested(const Ice::Current& = GlobalIceCurrent) const override;
+        virtual Ice::StringSeq getControllerNamesActivated(const Ice::Current& = GlobalIceCurrent) const override;
+
+        virtual StringLVL1ControllerPrxDictionary getControllersLoaded(const Ice::Current& = GlobalIceCurrent) const override;
+        virtual StringLVL1ControllerPrxDictionary getControllersRequested(const Ice::Current& = GlobalIceCurrent) const override;
+        virtual StringLVL1ControllerPrxDictionary getControllersActivated(const Ice::Current& = GlobalIceCurrent) const override;
+        virtual JointNameToLVL1Dictionary getControllerJointAssignment(const Ice::Current& = GlobalIceCurrent) const override;
+        //modes
+        virtual JointNameToControlModeDictionary  getJointControlModesRequested(const Ice::Current& = GlobalIceCurrent) const override;
+        virtual JointNameToControlModeDictionary  getJointControlModesActivated(const Ice::Current& = GlobalIceCurrent) const override;
+        virtual JointNameToControlModesDictionary getJointControlModesSupported(const Ice::Current& = GlobalIceCurrent) const override;
+        //loading and switching
+        virtual void switchSetup(const Ice::StringSeq& controllerRequestedNames, const Ice::Current& = GlobalIceCurrent) override;
+        virtual LVL1ControllerInterfacePrx loadController(const std::string& className, const std::string& instanceName, const LVL1ControllerConfigPtr& config, const Ice::Current& = GlobalIceCurrent) override;
+        virtual bool loadLibFromPath(const std::string& path   ,                         const Ice::Current& = GlobalIceCurrent) const override
+        {
+            throw "NYI";/*TODO mirko*/
+        }
+        virtual bool loadLibFromPackage(const std::string& package, const std::string& lib, const Ice::Current& = GlobalIceCurrent) const override
+        {
+            throw "NYI";/*TODO mirko*/
+        }
 
-        //            }
-        //            catch (...)
-        //            {
-        //                controlThreadState = ControlThreadState::Exception;
-        //                emergencyStop();
-        //                //TODO HANDLING
-        //            }
-        //        }
+        //units (ice)
+        virtual           KinematicUnitInterfacePrx getKinematicUnit(const Ice::Current& = GlobalIceCurrent) const = 0;
+        virtual         ForceTorqueUnitInterfacePrx getForceTorqueUnit(const Ice::Current& = GlobalIceCurrent) const = 0;
+        virtual InertialMeasurementUnitInterfacePrx getInertialMeasurementUnit(const Ice::Current& = GlobalIceCurrent) const = 0;
+        virtual            PlatformUnitInterfacePrx getPlatformUnitInterface(const Ice::Current& = GlobalIceCurrent) const = 0;
+        //units (rt)
+        virtual const ForceTorqueDataUnitInterface& getForceTorqueDataUnit() const = 0;
+        virtual const      HapticDataUnitInterface& getHapticDataUnit() const = 0;
+        virtual const         IMUDataUnitInterface& getIMUDataUnit() const = 0;
+        virtual const   KinematicDataUnitInterface& getKinematicDataUnit() const = 0;
+        virtual const    PlatformDataUnitInterface& getPlatformDataUnit() const = 0;
+        //targets
+        JointTargetBase* getJointTarget(const std::string& jointName, const std::string& controlMode);
+
+    protected:
+        /**
+         * @see PropertyUser::createPropertyDefinitions()
+         */
+        virtual armarx::PropertyDefinitionsPtr createPropertyDefinitions() override;
+
+        bool hasLVL1Controller(const std::string& name) const;
+        bool hasLVL0Controller(const std::string& jointName, const std::string& controlMode) const;
+
+        static void setLVL1ControllerActive(const LVL1ControllerPtr& lvl1, bool isActive = 1)
+        {
+            lvl1->isActive = isActive;
+        }
 
+        struct LVL0AndLVL1ControllerList
+        {
+            std::vector<LVL0ControllerBase*> lvl0Controllers;
+            std::vector<LVL1ControllerPtr  > lvl1Controllers;
+        };
+        mutable MutexType dataMutex;
+        //data accessible in RT and nonRT
+        const std::vector<std::string> jointNames;
+        std::atomic_bool switchSetupError {false};
+        //used to communicate with rt
+        /// @brief Controllers the RT thread is supposed to activate (direction nonRT -> RT)
+        TripleBuffer<LVL0AndLVL1ControllerList> controllersRequested;
+        /// @brief Controllers the RT thread is currently running (direction RT -> nonRT)
+        TripleBuffer<LVL0AndLVL1ControllerList> controllersActivated;
+        //non rt data
+        /**
+         * @brief Holds pointer to all lvl0 controllers. (index: [jointname][controlmode])
+         * Is initialized by derived classes.
+         * May not be accessed when the controll loop is running
+         */
+        std::map<std::string, std::map<std::string, LVL0ControllerBase*>> lvl0Controllers;
+        /**
+         * @brief Holds all currently loaded LVL1 controllers (index: [instancename])
+         * May not be accessed in rt.
+         */
+        std::map<std::string, LVL1ControllerPtr> lvl1Controllers;
+
+    private:
+        JointNameToControlModeDictionary jointsUsedByLVL1Controler;
     };
+
+    using RobotUnitPtr = IceInternal::Handle<RobotUnit>;
 }
 
 #endif