diff --git a/source/RobotAPI/components/units/RobotUnit/CMakeLists.txt b/source/RobotAPI/components/units/RobotUnit/CMakeLists.txt
index ff3d42340eb8804e6d472ad44fcb76f648a03428..dd03919fe258401049146b5578db8dd12d34f456 100644
--- a/source/RobotAPI/components/units/RobotUnit/CMakeLists.txt
+++ b/source/RobotAPI/components/units/RobotUnit/CMakeLists.txt
@@ -29,7 +29,9 @@ set(LIB_FILES
     RobotUnitObserver.cpp
     BasicControllers.cpp
     DefaultWidgetDescriptions.cpp
-    RobotSynchronization.cpp
+
+    #robot unit modules need to be added to the list below (but not here)
+    RobotUnitModules/RobotUnitModuleBase.cpp
 
     ControlTargets/ControlTargetBase.cpp
 
@@ -60,6 +62,8 @@ set(LIB_FILES
 set(LIB_HEADERS
     util.h
     util/EigenForwardDeclarations.h
+    util/HeterogenousContinuousContainer.h
+    util/HeterogenousContinuousContainerMacros.h
     util/KeyValueVector.h
     util/AtomicWrapper.h
     util/Time.h
@@ -70,15 +74,18 @@ set(LIB_HEADERS
     util/introspection/ClassMemberInfo.h
     util/RtLogging.h
 
+    #robot unit modules need to be added to the list below (but not here)
+    RobotUnitModules/RobotUnitModuleBase.h
+    RobotUnitModules/RobotUnitModuleBase.ipp
+    RobotUnitModules/RobotUnitModules.h
+
     PDController.h
     Constants.h
     ControlModes.h
     RobotUnit.h
-    RobotUnit.ipp
     RobotUnitObserver.h
     BasicControllers.h
     DefaultWidgetDescriptions.h
-    RobotSynchronization.h
 
     ControlTargets/ControlTargetBase.h
     ControlTargets/ControlTarget1DoFActuator.h
@@ -102,7 +109,7 @@ set(LIB_HEADERS
     JointControllers/JointController.h
 
     NJointControllers/NJointController.h
-    NJointControllers/NJointController.hpp
+    NJointControllers/NJointController.ipp
     NJointControllers/NJointTrajectoryController.h
     NJointControllers/NJointKinematicUnitPassThroughController.h
     NJointControllers/NJointHolonomicPlatformUnitVelocityPassThroughController.h
@@ -117,6 +124,85 @@ set(LIB_HEADERS
 
     Devices/RTThreadTimingsSensorDevice.h
 )
+###########################################################################
+#since the robot unit is a complex class, it is split into several modules.
+#one reason behind this is stopping developers from using datastructures in the wrong way (eg causing racing conditions)
+#for the robot unit to work, ALL modules are required (a class has to derive all of them)
+#modules are autodetected in the RobotUnitModules folder, but should be listed here anyways
+#(since glob does not autodetect new files)
+#(see: https://cmake.org/cmake/help/v3.0/command/file.html)
+# > If no CMakeLists.txt file changes when a source is added or removed then the generated build system cannot know when to ask CMake to regenerate.
+set(RobotUnitModules
+    Management
+    ControllerManagement
+    ControlThread
+    ControlThreadDataBuffer
+    Devices
+    Logging
+    Publisher
+    RobotData
+    SelfCollisionChecker
+    Units
+)
+file(GLOB_RECURSE files_full_path "${CMAKE_CURRENT_SOURCE_DIR}/RobotUnitModules/*")
+set(files)
+foreach(file_full_path ${files_full_path})
+    #remove prefix
+    string(REGEX REPLACE "${CMAKE_CURRENT_SOURCE_DIR}/" "" file_rel_path "${file_full_path}")
+    list(APPEND files ${file_rel_path})
+endforeach()
+#remove base module / collection header
+list(REMOVE_ITEM files RobotUnitModules/RobotUnitModuleBase.h)
+list(REMOVE_ITEM files RobotUnitModules/RobotUnitModuleBase.cpp)
+list(REMOVE_ITEM files RobotUnitModules/RobotUnitModuleBase.ipp)
+list(REMOVE_ITEM files RobotUnitModules/RobotUnitModules.h)
+
+#remove all expected files
+foreach(module ${RobotUnitModules})
+    set(ModuleName RobotUnitModule${module})
+    set(ModuleFileBase "RobotUnitModules/${ModuleName}")
+
+    #h
+    list(FIND files "${ModuleFileBase}.h" idx)
+
+    if(idx EQUAL -1)
+        message(STATUS "Files:")
+        printlist("     " "${files}")
+        message(FATAL_ERROR "MODULE FILE NOT FOUND: '${ModuleFileBase}.h'")
+    endif()
+    list(REMOVE_ITEM files ${ModuleFileBase}.h)
+    list(APPEND LIB_HEADERS ${ModuleFileBase}.h)
+
+    #cpp
+    list(FIND      files ${ModuleFileBase}.cpp idx)
+    if(idx EQUAL -1)
+        message(STATUS "Files:")
+        printlist("     " "${files}")
+        message(FATAL_ERROR "MODULE FILE NOT FOUND: '${ModuleFileBase}.cpp'")
+    endif()
+    list(REMOVE_ITEM files ${ModuleFileBase}.cpp)
+    list(APPEND LIB_FILES ${ModuleFileBase}.cpp)
+
+    #ipp
+    list(FIND      files ${ModuleFileBase}.ipp idx)
+    if(NOT idx EQUAL -1)
+        list(APPEND LIB_HEADERS ${ModuleFileBase}.ipp)
+        list(REMOVE_ITEM files ${ModuleFileBase}.ipp)
+    endif()
+    message(STATUS "Found RobotUnitModule ${ModuleName}")
+endforeach()
+#check remaining files
+foreach(f ${files})
+    if(f MATCHES ".*/RobotUnitModule[a-zA-Z]*.*" )
+        message(FATAL_ERROR "MODULE NOT ADDED TO LIST OF MODULES: ${f}" )
+    endif()
+endforeach()
+
+list_to_string(RobotUnitModules "," ${RobotUnitModules})
+
+message(STATUS "collected these names for RobotUnitModules: ${RobotUnitModules}")
+#done detecting modules!
+###########################################################################
 
 
 
@@ -124,3 +210,4 @@ add_subdirectory(test)
 
 armarx_add_library("${LIB_NAME}" "${LIB_FILES}" "${LIB_HEADERS}" "${LIBS}")
 
+target_compile_definitions("${LIB_NAME}" PUBLIC "-DRobotUnitModules=${RobotUnitModules}")
diff --git a/source/RobotAPI/components/units/RobotUnit/ControlTargets/ControlTargetBase.h b/source/RobotAPI/components/units/RobotUnit/ControlTargets/ControlTargetBase.h
index af8fa62e0e08a2c967c442c3601337a239278d26..5ca733da695eb174ae9b69d0c86abefdbe5df0e1 100644
--- a/source/RobotAPI/components/units/RobotUnit/ControlTargets/ControlTargetBase.h
+++ b/source/RobotAPI/components/units/RobotUnit/ControlTargets/ControlTargetBase.h
@@ -32,6 +32,7 @@
 #include "../util.h"
 #include "../Constants.h"
 #include "../ControlModes.h"
+#include "../util/HeterogenousContinuousContainerMacros.h"
 
 namespace armarx
 {
@@ -86,74 +87,48 @@ namespace armarx
         virtual std::string getDataFieldAsString(std::size_t i) const = 0;
 
         //management functions
-        virtual void _copyTo(ControlTargetBase* target) const = 0;
         template<class T, class = typename std::enable_if<std::is_base_of<ControlTargetBase, T>::value>::type>
         void _copyTo(std::unique_ptr<T>& target) const
         {
             _copyTo(target.get());
         }
 
-        virtual std::unique_ptr<ControlTargetBase> _clone() const = 0;
-
-        virtual std::size_t _sizeInBytes() const = 0;
-        virtual std::size_t _alignof() const = 0;
-        virtual ControlTargetBase* _placementConstruct(void* place) const = 0;
-
         ARMARX_META_MAKE_HAS_MEMBER_FNC_CHECK(
             ControlTargetHasGetClassMemberInfo,
             GetClassMemberInfo, ControlTargetInfo<T>(*)(void));
+
+        ARMARX_PLACEMENT_CONSTRUCTION_HELPER_BASE(ControlTargetBase)
     };
 
-#define DETAIL_ControlTargetBase_DEFAULT_METHOD_IMPLEMENTATION                                                  \
-    virtual ControlTargetBase* _placementConstruct(void* place) const override                                  \
-    {                                                                                                           \
-        return new(place) std::decay<decltype(*this)>::type;                                                    \
-    }                                                                                                           \
-    virtual std::size_t _sizeInBytes() const override                                                           \
-    {                                                                                                           \
-        return sizeof(std::decay<decltype(*this)>::type);                                                       \
-    }                                                                                                           \
-    virtual std::size_t _alignof() const override                                                               \
-    {                                                                                                           \
-        return alignof(std::decay<decltype(*this)>::type);                                                      \
-    }                                                                                                           \
-    virtual void _copyTo(ControlTargetBase* target) const override                                              \
-    {                                                                                                           \
-        const auto targAsThis = target->asA<std::decay<decltype(*this)>::type>();                               \
-        ARMARX_CHECK_NOT_NULL(targAsThis);                                                                      \
-        *targAsThis = *this;                                                                                    \
-    }                                                                                                           \
-    virtual std::unique_ptr<ControlTargetBase> _clone() const override                                          \
-    {                                                                                                           \
-        std::unique_ptr<ControlTargetBase> c {new std::decay<decltype(*this)>::type};                           \
-        ControlTargetBase::_copyTo(c);                                                                          \
-        return c;                                                                                               \
-    }                                                                                                           \
-    virtual std::string getControlTargetType(bool withoutNamespaceSpecifier = false) const override             \
-    {                                                                                                           \
-        return armarx::GetTypeString(*this, withoutNamespaceSpecifier);                                         \
-    }                                                                                                           \
-    void _check_for_static_GetClassMemberInfo_overload()                                                        \
-    {                                                                                                           \
-        static_assert(ControlTargetHasGetClassMemberInfo<std::decay<decltype(*this)>::type>::value,             \
-                      "This class has to implement GetClassMemberInfo() returning "                             \
-                      "an instance of ControlTargetInfo<THIS_CLASS_TYPE>");                                     \
-    }                                                                                                           \
-    virtual std::map<std::string, VariantBasePtr> toVariants(const IceUtil::Time& timestamp) const override     \
-    {                                                                                                           \
-        return ControlTargetInfo<std::decay<decltype(*this)>::type>::ToVariants(timestamp,this);                \
-    }                                                                                                           \
-    virtual std::size_t getNumberOfDataFields() const override                                                  \
-    {                                                                                                           \
-        return ControlTargetInfo<std::decay<decltype(*this)>::type>::GetNumberOfDataFields();                   \
-    }                                                                                                           \
-    virtual std::string getDataFieldAsString(std::size_t i) const override                                      \
-    {                                                                                                           \
-        return ControlTargetInfo<std::decay<decltype(*this)>::type>::GetDataFieldAsString(this, i);             \
-    }                                                                                                           \
-    virtual std::vector<std::string> getDataFieldNames() const override                                         \
-    {                                                                                                           \
-        return ControlTargetInfo<std::decay<decltype(*this)>::type>::GetDataFieldNames();                       \
+#define DETAIL_ControlTargetBase_DEFAULT_METHOD_IMPLEMENTATION                                      \
+    ARMARX_PLACEMENT_CONSTRUCTION_HELPER                                                            \
+    using ControlTargetBase = ::armarx::ControlTargetBase;                                          \
+    using VariantBasePtr = ::armarx::VariantBasePtr;                                                \
+    std::string getControlTargetType(bool withoutNamespaceSpecifier = false) const override         \
+    {                                                                                               \
+        return armarx::GetTypeString(*this, withoutNamespaceSpecifier);                             \
+    }                                                                                               \
+    void _check_for_static_GetClassMemberInfo_overload()                                            \
+    {                                                                                               \
+        static_assert(ControlTargetHasGetClassMemberInfo<std::decay<decltype(*this)>::type>::value, \
+                      "This class has to implement GetClassMemberInfo() returning "                 \
+                      "an instance of ControlTargetInfo<THIS_CLASS_TYPE>");                         \
+    }                                                                                               \
+    std::map<std::string, VariantBasePtr> toVariants(const IceUtil::Time& timestamp) const override \
+    {                                                                                               \
+        return ControlTargetInfo<std::decay<decltype(*this)>::type>::ToVariants(timestamp,this);    \
+    }                                                                                               \
+    std::size_t getNumberOfDataFields() const override                                              \
+    {                                                                                               \
+        return ControlTargetInfo<std::decay<decltype(*this)>::type>::GetNumberOfDataFields();       \
+    }                                                                                               \
+    std::string getDataFieldAsString(std::size_t i) const override                                  \
+    {                                                                                               \
+        return ControlTargetInfo<std::decay<decltype(*this)>::type>::GetDataFieldAsString(this, i); \
+    }                                                                                               \
+    std::vector<std::string> getDataFieldNames() const override                                     \
+    {                                                                                               \
+        return ControlTargetInfo<std::decay<decltype(*this)>::type>::GetDataFieldNames();           \
     }
 
 #define make_DummyControlTarget(Suffix,ControlMode)                     \
diff --git a/source/RobotAPI/components/units/RobotUnit/Devices/RTThreadTimingsSensorDevice.h b/source/RobotAPI/components/units/RobotUnit/Devices/RTThreadTimingsSensorDevice.h
index 734907c05b46755a12ae06def73b07727e56fa98..b7b0778f647f95c6a14d1e34fd82fedec1a2efe3 100644
--- a/source/RobotAPI/components/units/RobotUnit/Devices/RTThreadTimingsSensorDevice.h
+++ b/source/RobotAPI/components/units/RobotUnit/Devices/RTThreadTimingsSensorDevice.h
@@ -27,6 +27,10 @@
 
 namespace armarx
 {
+    namespace RobotUnitModule
+    {
+        TYPEDEF_PTRS_HANDLE(ControlThread);
+    }
     TYPEDEF_PTRS_SHARED(RTThreadTimingsSensorDevice);
 
     class RTThreadTimingsSensorDevice: virtual public SensorDevice
@@ -42,6 +46,7 @@ namespace armarx
         virtual void rtMarkRtBusSendReceiveEnd() = 0;
     protected:
         friend class RobotUnit;
+        friend class RobotUnitModule::ControlThread;
 
         virtual void rtMarkRtSwitchControllerSetupStart() = 0;
         virtual void rtMarkRtSwitchControllerSetupEnd() = 0;
diff --git a/source/RobotAPI/components/units/RobotUnit/NJointControllers/NJointCartesianTorqueController.cpp b/source/RobotAPI/components/units/RobotUnit/NJointControllers/NJointCartesianTorqueController.cpp
index b41543c9f389983f01ac52f99c5895e2523020e2..28ade519086d07f71aa03673a41972ebf3919a2e 100644
--- a/source/RobotAPI/components/units/RobotUnit/NJointControllers/NJointCartesianTorqueController.cpp
+++ b/source/RobotAPI/components/units/RobotUnit/NJointControllers/NJointCartesianTorqueController.cpp
@@ -37,19 +37,17 @@ namespace armarx
         return "NJointCartesianTorqueController";
     }
 
-    NJointCartesianTorqueController::NJointCartesianTorqueController(NJointControllerDescriptionProviderInterfacePtr prov, NJointCartesianTorqueControllerConfigPtr config, const boost::shared_ptr<VirtualRobot::Robot>& r)
+    NJointCartesianTorqueController::NJointCartesianTorqueController(RobotUnitPtr, NJointCartesianTorqueControllerConfigPtr 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());
-        VirtualRobot::RobotNodeSetPtr rns = robotUnit->getRtRobot()->getRobotNodeSet(config->nodeSetName);
+        useSynchronizedRtRobot();
+        VirtualRobot::RobotNodeSetPtr rns = rtGetRobot()->getRobotNodeSet(config->nodeSetName);
         ARMARX_CHECK_EXPRESSION_W_HINT(rns, config->nodeSetName);
         for (size_t i = 0; i < rns->getSize(); ++i)
         {
             std::string jointName = rns->getNode(i)->getName();
-            ControlTargetBase* ct = prov->getControlTarget(jointName, ControlModes::Torque1DoF);
-            //const SensorValueBase* sv = prov->getSensorValue(jointName);
+            ControlTargetBase* ct = useControlTarget(jointName, ControlModes::Torque1DoF);
+            //const SensorValueBase* sv = useSensorValue(jointName);
             targets.push_back(ct->asA<ControlTarget1DoFActuatorTorque>());
 
             /*const SensorValue1DoFActuatorTorque* torqueSensor = sv->asA<SensorValue1DoFActuatorTorque>();
@@ -66,7 +64,7 @@ namespace armarx
             gravityTorqueSensors.push_back(gravityTorqueSensor);*/
         };
 
-        tcp = (config->tcpName.empty() || config->tcpName == DEFAULT_TCP_STRING) ? rns->getTCP() : robotUnit->getRtRobot()->getRobotNode(config->tcpName);
+        tcp = (config->tcpName.empty() || config->tcpName == DEFAULT_TCP_STRING) ? rns->getTCP() : rtGetRobot()->getRobotNode(config->tcpName);
         ARMARX_CHECK_EXPRESSION_W_HINT(tcp, config->tcpName);
 
         nodeSetName = config->nodeSetName;
diff --git a/source/RobotAPI/components/units/RobotUnit/NJointControllers/NJointCartesianTorqueController.h b/source/RobotAPI/components/units/RobotUnit/NJointControllers/NJointCartesianTorqueController.h
index fd2e86457ef8f5bf5d15b04a99f53f4b8bb5fe3f..e52f3df118b8924cb281c8163a95acd1d0903a98 100644
--- a/source/RobotAPI/components/units/RobotUnit/NJointControllers/NJointCartesianTorqueController.h
+++ b/source/RobotAPI/components/units/RobotUnit/NJointControllers/NJointCartesianTorqueController.h
@@ -73,7 +73,7 @@ namespace armarx
     {
     public:
         using ConfigPtrT = NJointCartesianTorqueControllerConfigPtr;
-        NJointCartesianTorqueController(NJointControllerDescriptionProviderInterfacePtr prov, const NJointControllerConfigPtr& config, const VirtualRobot::RobotPtr&);
+        NJointCartesianTorqueController(RobotUnitPtr prov, const NJointControllerConfigPtr& config, const VirtualRobot::RobotPtr&);
 
         // NJointControllerInterface interface
         std::string getClassName(const Ice::Current&) const override;
@@ -89,7 +89,7 @@ namespace armarx
 
         static NJointCartesianTorqueControllerConfigPtr GenerateConfigFromVariants(const StringVariantBaseMap& values);
         NJointCartesianTorqueController(
-            NJointControllerDescriptionProviderInterfacePtr prov,
+            RobotUnitPtr prov,
             NJointCartesianTorqueControllerConfigPtr config,
             const boost::shared_ptr<VirtualRobot::Robot>& r);
 
diff --git a/source/RobotAPI/components/units/RobotUnit/NJointControllers/NJointCartesianVelocityController.cpp b/source/RobotAPI/components/units/RobotUnit/NJointControllers/NJointCartesianVelocityController.cpp
index 8e97708c59029a5f511e6b044dd8120ca8d4e933..7d2264e65314ffe5023cc98d9855936596d268eb 100644
--- a/source/RobotAPI/components/units/RobotUnit/NJointControllers/NJointCartesianVelocityController.cpp
+++ b/source/RobotAPI/components/units/RobotUnit/NJointControllers/NJointCartesianVelocityController.cpp
@@ -37,19 +37,17 @@ namespace armarx
         return "NJointCartesianVelocityController";
     }
 
-    NJointCartesianVelocityController::NJointCartesianVelocityController(NJointControllerDescriptionProviderInterfacePtr prov, NJointCartesianVelocityControllerConfigPtr config, const boost::shared_ptr<VirtualRobot::Robot>& r)
+    NJointCartesianVelocityController::NJointCartesianVelocityController(RobotUnitPtr robotUnit, NJointCartesianVelocityControllerConfigPtr config, const boost::shared_ptr<VirtualRobot::Robot>& r)
     {
-        ARMARX_CHECK_EXPRESSION(prov);
-        RobotUnitPtr robotUnit = RobotUnitPtr::dynamicCast(prov);
-        ARMARX_CHECK_EXPRESSION(robotUnit);
+        useSynchronizedRtRobot();
         ARMARX_CHECK_EXPRESSION(!config->nodeSetName.empty());
-        VirtualRobot::RobotNodeSetPtr rns = robotUnit->getRtRobot()->getRobotNodeSet(config->nodeSetName);
+        VirtualRobot::RobotNodeSetPtr rns = rtGetRobot()->getRobotNodeSet(config->nodeSetName);
         ARMARX_CHECK_EXPRESSION_W_HINT(rns, config->nodeSetName);
         for (size_t i = 0; i < rns->getSize(); ++i)
         {
             std::string jointName = rns->getNode(i)->getName();
-            ControlTargetBase* ct = prov->getControlTarget(jointName, ControlModes::Velocity1DoF);
-            const SensorValueBase* sv = prov->getSensorValue(jointName);
+            ControlTargetBase* ct = useControlTarget(jointName, ControlModes::Velocity1DoF);
+            const SensorValueBase* sv = useSensorValue(jointName);
             targets.push_back(ct->asA<ControlTarget1DoFActuatorVelocity>());
 
             const SensorValue1DoFActuatorTorque* torqueSensor = sv->asA<SensorValue1DoFActuatorTorque>();
@@ -66,7 +64,7 @@ namespace armarx
             gravityTorqueSensors.push_back(gravityTorqueSensor);
         };
 
-        VirtualRobot::RobotNodePtr tcp = (config->tcpName.empty() || config->tcpName == DEFAULT_TCP_STRING) ? rns->getTCP() : robotUnit->getRtRobot()->getRobotNode(config->tcpName);
+        VirtualRobot::RobotNodePtr tcp = (config->tcpName.empty() || config->tcpName == DEFAULT_TCP_STRING) ? rns->getTCP() : rtGetRobot()->getRobotNode(config->tcpName);
         ARMARX_CHECK_EXPRESSION_W_HINT(tcp, config->tcpName);
         tcpController.reset(new CartesianVelocityController(rns, tcp));
 
diff --git a/source/RobotAPI/components/units/RobotUnit/NJointControllers/NJointCartesianVelocityController.h b/source/RobotAPI/components/units/RobotUnit/NJointControllers/NJointCartesianVelocityController.h
index bc7744f4064e6a351f235f99b3eeff1bde445fe1..7c792c309119b66a07e9c13983e75c3e177eac4d 100644
--- a/source/RobotAPI/components/units/RobotUnit/NJointControllers/NJointCartesianVelocityController.h
+++ b/source/RobotAPI/components/units/RobotUnit/NJointControllers/NJointCartesianVelocityController.h
@@ -86,7 +86,7 @@ namespace armarx
     {
     public:
         using ConfigPtrT = NJointCartesianVelocityControllerConfigPtr;
-        NJointCartesianVelocityController(NJointControllerDescriptionProviderInterfacePtr prov, const NJointControllerConfigPtr& config, const VirtualRobot::RobotPtr&);
+        NJointCartesianVelocityController(RobotUnitPtr prov, const NJointControllerConfigPtr& config, const VirtualRobot::RobotPtr&);
 
         // NJointControllerInterface interface
         std::string getClassName(const Ice::Current&) const override;
@@ -102,7 +102,7 @@ namespace armarx
 
         static NJointCartesianVelocityControllerConfigPtr GenerateConfigFromVariants(const StringVariantBaseMap& values);
         NJointCartesianVelocityController(
-            NJointControllerDescriptionProviderInterfacePtr prov,
+            RobotUnitPtr prov,
             NJointCartesianVelocityControllerConfigPtr config,
             const boost::shared_ptr<VirtualRobot::Robot>& r);
 
diff --git a/source/RobotAPI/components/units/RobotUnit/NJointControllers/NJointController.cpp b/source/RobotAPI/components/units/RobotUnit/NJointControllers/NJointController.cpp
index 9b87ed517a71f0a6ae1dad5fc897bbc67559bec6..c2f632008576b93d774acdd6ab22fc1c8a2ed508 100644
--- a/source/RobotAPI/components/units/RobotUnit/NJointControllers/NJointController.cpp
+++ b/source/RobotAPI/components/units/RobotUnit/NJointControllers/NJointController.cpp
@@ -26,205 +26,295 @@
 
 #include "../RobotUnit.h"
 
-using namespace armarx;
+#include <atomic>
 
-const NJointControllerPtr NJointController::NullPtr
+namespace armarx
 {
-    nullptr
-};
+    namespace RobotUnitModule
+    {
 
-NJointControllerDescription NJointController::getControllerDescription(const Ice::Current&) const
-{
-    NJointControllerDescription d;
-    d.className = getClassName();
-    ARMARX_CHECK_EXPRESSION(getProxy(-1));
-    d.controller = NJointControllerInterfacePrx::uncheckedCast(getProxy(-1));
-    d.controlModeAssignment = controlDeviceControlModeMap;
-    d.instanceName = getInstanceName();
-    d.deletable = deletable;
-    d.internal = internal;
-    return d;
+        /**
+         * \brief This class allows minimal access to private members of \ref armarx::RobotUnitModule::Devices in a sane fashion for \ref armarx::NJointController.
+         * \warning !! DO NOT ADD ANYTHING IF YOU DO NOT KNOW WAHT YOU ARE DOING! IF YOU DO SOMETHING WRONG YOU WILL CAUSE UNDEFINED BEHAVIOUR !!
+         */
+        class DevicesAttorneyForNJointController
+        {
+            friend class ::armarx::NJointController;
+            static JointController* GetJointController(Devices& d, const std::string &deviceName, const std::string &controlMode)
+            {
+                if(d.controlDevices.has(deviceName))
+                {
+                    auto& dev = d.controlDevices.at(deviceName);
+                    if(dev->hasJointController(controlMode))
+                    {
+                        ARMARX_CHECK_NOT_NULL(dev->getJointController(controlMode));
+                        ARMARX_CHECK_NOT_NULL(dev->getJointController(controlMode)->getControlTarget());
+                        return dev->getJointController(controlMode);
+                    }
+                }
+                return nullptr;
+            }
+        };
+    }
 }
 
-boost::optional<std::vector<char> > NJointController::isNotInConflictWith(const std::vector<char>& used) const
+
+thread_local bool armarx::NJointControllerRegistryEntry::ConstructorIsRunning_ = false;
+
+namespace armarx
 {
-    ARMARX_CHECK_EXPRESSION(used.size() == controlDeviceUsedBitmap.size());
-    auto result = used;
-    for (std::size_t i = 0; i < controlDeviceUsedBitmap.size(); ++i)
+    const NJointControllerPtr NJointController::NullPtr
+    {
+        nullptr
+    };
+
+    NJointControllerDescription NJointController::getControllerDescription(const Ice::Current&) const
+    {
+        NJointControllerDescription d;
+        d.className = getClassName();
+        ARMARX_CHECK_EXPRESSION(getProxy(-1));
+        d.controller = NJointControllerInterfacePrx::uncheckedCast(getProxy(-1));
+        d.controlModeAssignment = controlDeviceControlModeMap;
+        d.instanceName = getInstanceName();
+        d.deletable = deletable;
+        d.internal = internal;
+        return d;
+    }
+
+    boost::optional<std::vector<char> > NJointController::isNotInConflictWith(const std::vector<char>& used) const
     {
-        if (controlDeviceUsedBitmap.at(i))
+        ARMARX_CHECK_EXPRESSION(used.size() == controlDeviceUsedBitmap.size());
+        auto result = used;
+        for (std::size_t i = 0; i < controlDeviceUsedBitmap.size(); ++i)
         {
-            if (used.at(i))
+            if (controlDeviceUsedBitmap.at(i))
             {
-                return boost::optional<std::vector<char>>();
+                if (used.at(i))
+                {
+                    return boost::optional<std::vector<char>>();
+                }
+                result.at(i) = true;
             }
-            result.at(i) = true;
-        }
 
+        }
+        return {true, std::move(result)};
     }
-    return {true, std::move(result)};
-}
 
-NJointControllerStatus NJointController::getControllerStatus(const Ice::Current&) const
-{
-    NJointControllerStatus s;
-    s.active = isActive;
-    s.instanceName = getInstanceName();
-    s.requested = isRequested;
-    s.error = deactivatedBecauseOfError;
-    s.timestampUSec = std::chrono::duration_cast<std::chrono::microseconds>(std::chrono::high_resolution_clock::now().time_since_epoch()).count();
-    return s;
-}
+    NJointControllerStatus NJointController::getControllerStatus(const Ice::Current&) const
+    {
+        NJointControllerStatus s;
+        s.active = isActive;
+        s.instanceName = getInstanceName();
+        s.requested = isRequested;
+        s.error = deactivatedBecauseOfError;
+        s.timestampUSec = std::chrono::duration_cast<std::chrono::microseconds>(std::chrono::high_resolution_clock::now().time_since_epoch()).count();
+        return s;
+    }
 
-NJointControllerDescriptionWithStatus NJointController::getControllerDescriptionWithStatus(const Ice::Current&) const
-{
-    NJointControllerDescriptionWithStatus ds;
-    ds.description = getControllerDescription();
-    ds.status = getControllerStatus();
-    return ds;
-}
+    NJointControllerDescriptionWithStatus NJointController::getControllerDescriptionWithStatus(const Ice::Current&) const
+    {
+        NJointControllerDescriptionWithStatus ds;
+        ds.description = getControllerDescription();
+        ds.status = getControllerStatus();
+        return ds;
+    }
 
-RobotUnitInterfacePrx NJointController::getRobotUnit(const Ice::Current&) const
-{
-    ARMARX_CHECK_EXPRESSION(robotUnit);
-    return RobotUnitInterfacePrx::uncheckedCast(robotUnit->getProxy(-1));
-}
+    RobotUnitInterfacePrx NJointController::getRobotUnit(const Ice::Current&) const
+    {
+        return RobotUnitInterfacePrx::uncheckedCast(robotUnit.getProxy(-1));
+    }
 
-void NJointController::activateController(const Ice::Current&) const
-{
-    ARMARX_CHECK_EXPRESSION(robotUnit);
-    robotUnit->activateNJointController(getInstanceName());
-}
+    void NJointController::activateController(const Ice::Current&) const
+    {
+        robotUnit.activateNJointController(getInstanceName());
+    }
 
-void NJointController::deactivateController(const Ice::Current&) const
-{
-    ARMARX_CHECK_EXPRESSION(robotUnit);
-    robotUnit->deactivateNJointController(getInstanceName());
-}
+    void NJointController::deactivateController(const Ice::Current&) const
+    {
+        robotUnit.deactivateNJointController(getInstanceName());
+    }
 
-void NJointController::deleteController(const Ice::Current&) const
-{
-    ARMARX_CHECK_EXPRESSION(robotUnit);
-    robotUnit->deleteNJointController(getInstanceName());
-}
+    void NJointController::deleteController(const Ice::Current&) const
+    {
+        robotUnit.deleteNJointController(getInstanceName());
+    }
 
-void NJointController::publish(const SensorAndControl& sac, const DebugDrawerInterfacePrx& draw, const DebugObserverInterfacePrx& observer)
-{
-    const bool active = isActive;
-    if (publishActive.exchange(active) != active)
+    void NJointController::publish(const SensorAndControl& sac, const DebugDrawerInterfacePrx& draw, const DebugObserverInterfacePrx& observer)
     {
-        if (active)
+        const bool active = isActive;
+        if (publishActive.exchange(active) != active)
         {
-            ARMARX_DEBUG << "activating publishing for " << getInstanceName();
-            try
+            if (active)
             {
-                onPublishActivation(draw, observer);
+                ARMARX_DEBUG << "activating publishing for " << getInstanceName();
+                try
+                {
+                    onPublishActivation(draw, observer);
+                }
+                catch (std::exception& e)
+                {
+                    ARMARX_WARNING << "onPublishActivation of '" << getInstanceName() << "' threw an exception!\nWhat:\n" << e.what();
+                }
+                catch (...)
+                {
+                    ARMARX_WARNING << "onPublishActivation of '" << getInstanceName() << "' threw an exception!";
+                }
             }
-            catch (std::exception& e)
-            {
-                ARMARX_WARNING << "onPublishActivation of '" << getInstanceName() << "' threw an exception!\nWhat:\n" << e.what();
-            }
-            catch (...)
+            else
             {
-                ARMARX_WARNING << "onPublishActivation of '" << getInstanceName() << "' threw an exception!";
+                ARMARX_DEBUG << "deactivating publishing for " << getInstanceName();
+                try
+                {
+                    onPublishDeactivation(draw, observer);
+                }
+                catch (std::exception& e)
+                {
+                    ARMARX_WARNING << "onPublishDeactivation of '" << getInstanceName() << "' threw an exception!\nWhat:\n" << e.what();
+                }
+                catch (...)
+                {
+                    ARMARX_WARNING << "onPublishDeactivation of '" << getInstanceName() << "' threw an exception!";
+                }
             }
         }
-        else
+        if (active)
         {
-            ARMARX_DEBUG << "deactivating publishing for " << getInstanceName();
             try
             {
-                onPublishDeactivation(draw, observer);
+                onPublish(sac, draw, observer);
             }
             catch (std::exception& e)
             {
-                ARMARX_WARNING << "onPublishDeactivation of '" << getInstanceName() << "' threw an exception!\nWhat:\n" << e.what();
+                ARMARX_WARNING << "onPublish of '" << getInstanceName() << "' threw an exception!\nWhat:\n" << e.what();
             }
             catch (...)
             {
-                ARMARX_WARNING << "onPublishDeactivation of '" << getInstanceName() << "' threw an exception!";
+                ARMARX_WARNING << "onPublish of '" << getInstanceName() << "' threw an exception!";
             }
         }
     }
-    if (active)
+
+    void NJointController::deactivatePublish(const DebugDrawerInterfacePrx& draw, const DebugObserverInterfacePrx& observer)
     {
-        try
+        if (publishActive.exchange(false))
         {
-            onPublish(sac, draw, observer);
+            ARMARX_DEBUG << "forced deactivation of publishing for " << getInstanceName();
+            onPublishDeactivation(draw, observer);
         }
-        catch (std::exception& e)
+    }
+
+    void NJointController::rtActivateController()
+    {
+        if (!isActive)
         {
-            ARMARX_WARNING << "onPublish of '" << getInstanceName() << "' threw an exception!\nWhat:\n" << e.what();
+            deactivatedBecauseOfError = false;
+            rtPreActivateController();
+            isActive = true;
         }
-        catch (...)
+    }
+
+    void NJointController::rtDeactivateController()
+    {
+        if (isActive)
         {
-            ARMARX_WARNING << "onPublish of '" << getInstanceName() << "' threw an exception!";
+            isActive = false;
+            rtPostDeactivateController();
         }
     }
-}
 
-void NJointController::deactivatePublish(const DebugDrawerInterfacePrx& draw, const DebugObserverInterfacePrx& observer)
-{
-    if (publishActive.exchange(false))
+    void NJointController::rtDeactivateControllerBecauseOfError()
     {
-        ARMARX_DEBUG << "forced deactivation of publishing for " << getInstanceName();
-        onPublishDeactivation(draw, observer);
+        deactivatedBecauseOfError = true;
+        rtDeactivateController();
     }
-}
 
-void NJointController::rtActivateController()
-{
-    if (!isActive)
+    armarx::ConstSensorDevicePtr armarx::NJointController::peekSensorDevice(const std::string &deviceName) const
     {
-        deactivatedBecauseOfError = false;
-        rtPreActivateController();
-        isActive = true;
+        ARMARX_CHECK_EXPRESSION_W_HINT(
+            NJointControllerRegistryEntry::ConstructorIsRunning(),
+            "The function '" << BOOST_CURRENT_FUNCTION << "' must only be called during the construction of an NJointController."
+        );
+        return RobotUnitModule::Devices::Instance().getSensorDevice(deviceName);
     }
-}
 
-void NJointController::rtDeactivateController()
-{
-    if (isActive)
+    ConstControlDevicePtr NJointController::peekControlDevice(const std::string &deviceName) const
     {
-        isActive = false;
-        rtPostDeactivateController();
+        ARMARX_CHECK_EXPRESSION_W_HINT(
+            NJointControllerRegistryEntry::ConstructorIsRunning(),
+            "The function '" << BOOST_CURRENT_FUNCTION << "' must only be called during the construction of an NJointController."
+        );
+        return RobotUnitModule::Devices::Instance().getControlDevice(deviceName);
     }
-}
 
-void NJointController::rtDeactivateControllerBecauseOfError()
-{
-    deactivatedBecauseOfError = true;
-    rtDeactivateController();
-}
+    void NJointController::useSynchronizedRtRobot(bool updateCollisionModel)
+    {
+        ARMARX_CHECK_EXPRESSION_W_HINT(
+                    NJointControllerRegistryEntry::ConstructorIsRunning(),
+                    "The function '" << BOOST_CURRENT_FUNCTION << "' must only be called during the construction of an NJointController."
+        );
+        ARMARX_CHECK_IS_NULL_W_HINT(rtRobot, "useSynchronizedRtRobot was already called");
+        rtRobot = RobotUnitModule::RobotData::Instance().cloneRobot(updateCollisionModel);
+        rtRobotNodes = rtRobot->getRobotNodes();
+    }
 
-void NJointController::robotUnitInit(
-    RobotUnit* ru,
-    std::size_t ctrlId,
-    std::map<std::string, const JointController*> ctrlDeviceUsedJointController,
-    std::vector<char> ctrlDeviceUsedBitmap,
-    std::vector<std::size_t> ctrlDeviceUsedIndices,
-    bool ctrlDeletable,
-    bool ctrlInternal)
-{
-    ARMARX_CHECK_EXPRESSION(ru);
-    ARMARX_CHECK_EXPRESSION_W_HINT(ctrlDeviceUsedJointController.size(), "Controller requested zero joints");
-    ARMARX_CHECK_EXPRESSION(ctrlId != std::numeric_limits<std::size_t>::max());
-    ARMARX_CHECK_EXPRESSION_W_HINT(ru->getNumberOfControlDevices() == ctrlDeviceUsedBitmap.size(),
-                                   "ru->getNumberOfControlDevices() == ctrlDeviceUsedBitmap.size() ->" +
-                                   to_string(ru->getNumberOfControlDevices()) + " > " + to_string(ctrlDeviceUsedBitmap.size()));
-    ARMARX_CHECK_EXPRESSION(ctrlDeviceUsedJointController.size() == ctrlDeviceUsedIndices.size());
-
-    robotUnit = ru;
-    id = ctrlId;
-    controlDeviceUsedJointController = std::move(ctrlDeviceUsedJointController);
-    for (const auto& pair : controlDeviceUsedJointController)
-    {
-        ARMARX_CHECK_EXPRESSION(pair.second);
-        controlDeviceControlModeMap[pair.first] = pair.second->getControlMode();
-    }
-    controlDeviceUsedBitmap     = std::move(ctrlDeviceUsedBitmap);
-    controlDeviceUsedIndices    = std::move(ctrlDeviceUsedIndices);
-    deletable = ctrlDeletable;
-    internal = ctrlInternal;
-}
+    const SensorValueBase* NJointController::useSensorValue(const std::string &deviceName) const
+    {
+        ARMARX_CHECK_EXPRESSION_W_HINT(
+                    NJointControllerRegistryEntry::ConstructorIsRunning(),
+                    "The function '" << BOOST_CURRENT_FUNCTION << "' must only be called during the construction of an NJointController."
+        );
+        auto dev = peekSensorDevice(deviceName);
+        if(!dev)
+        {
+            ARMARX_DEBUG << "No sensor device for " << deviceName;
+            return nullptr;
+        }
+        return dev->getSensorValue();
+    }
+
+    NJointController::NJointController() :
+        robotUnit(RobotUnitModule::ModuleBase::Instance< ::armarx::RobotUnit>()),
+        controlDeviceUsedBitmap(robotUnit.getNumberOfControlDevices(), 0)
+    {
+        controlDeviceUsedIndices.reserve(robotUnit.getNumberOfControlDevices());
+    }
 
+    ControlTargetBase *NJointController::useControlTarget(const std::string &deviceName, const std::string &controlMode)
+    {
+        ARMARX_CHECK_EXPRESSION_W_HINT(
+            NJointControllerRegistryEntry::ConstructorIsRunning(),
+            "The function '" << BOOST_CURRENT_FUNCTION << "' must only be called during the construction of an NJointController."
+        );
+        ARMARX_CHECK_EQUAL_W_HINT(
+            controlDeviceControlModeMap.count(deviceName),0,
+            BOOST_CURRENT_FUNCTION << ": Must not request two ControlTargets for the same device. (got = "
+            << controlDeviceControlModeMap.at(deviceName) << ", requested " + controlMode + ") "
+            << "(You can only have a ControlDevice in one ControlMode. "
+            << "To check all available ControlModes for this device, get the ControlDevice via peekControlDevice(" + deviceName + ") and querry it)"
+        );
+
+        //there is a device and a target was requested:
+        JointController* const jointCtrl = RobotUnitModule::DevicesAttorneyForNJointController::GetJointController(RobotUnitModule::Devices::Instance(), deviceName, controlMode);
+        if (!jointCtrl)
+        {
+            return nullptr;
+        }
+
+        //update meta data structured
+        const std::size_t devIndex = robotUnit.getControlDeviceIndex(deviceName);
+        controlDeviceUsedJointController[deviceName] = jointCtrl;
+
+        controlDeviceControlModeMap[deviceName] = controlMode;
+
+        ARMARX_CHECK_EQUAL(0, controlDeviceUsedBitmap.at(devIndex));
+        controlDeviceUsedBitmap.at(devIndex) = 1;
+        //we want this vector to be sorted
+        controlDeviceUsedIndices.insert
+        (
+            std::upper_bound( controlDeviceUsedIndices.begin(), controlDeviceUsedIndices.end(), devIndex),
+            devIndex
+        );
+
+        return jointCtrl->getControlTarget();
+    }
+}
diff --git a/source/RobotAPI/components/units/RobotUnit/NJointControllers/NJointController.h b/source/RobotAPI/components/units/RobotUnit/NJointControllers/NJointController.h
index b9fbd1980f0097db0d22db4b74fbfd32f11c28aa..ce5845ae37aeac6f58c0f1ecd990a52db8a1af4f 100644
--- a/source/RobotAPI/components/units/RobotUnit/NJointControllers/NJointController.h
+++ b/source/RobotAPI/components/units/RobotUnit/NJointControllers/NJointController.h
@@ -54,32 +54,27 @@
 namespace VirtualRobot
 {
     class Robot;
+    class RobotNode;
+    typedef boost::shared_ptr<RobotNode> RobotNodePtr;
+    typedef boost::shared_ptr<Robot> RobotPtr;
 }
 
 namespace armarx
 {
-    TYPEDEF_PTRS_HANDLE(NJointController);
-    TYPEDEF_PTRS_HANDLE(NJointControllerDescriptionProviderInterface);
-
-    class RobotUnit;
-
-    class NJointControllerDescriptionProviderInterface: virtual public Ice::Object
+    namespace RobotUnitModule
     {
-    public:
-        ~NJointControllerDescriptionProviderInterface() override = default;
-
-        virtual ConstSensorDevicePtr   getSensorDevice(const std::string& sensorDeviceName) const = 0;
-        virtual const SensorValueBase* getSensorValue(const std::string& sensorDeviceName) const;
-        virtual ConstControlDevicePtr getControlDevice(const std::string& deviceName) const = 0;
-        virtual ControlTargetBase* getControlTarget(const std::string& deviceName, const std::string& controlMode) = 0;
+        class NJointControllerAttorneyForPublisher;
+        class NJointControllerAttorneyForControlThread;
+        class NJointControllerAttorneyForControllerManagement;
+    }
+    namespace detail
+    {
+        template<class> class NJointControllerRegistryEntryHelperBase;
+    }
 
-        virtual std::string getName() const = 0;
+    TYPEDEF_PTRS_HANDLE(NJointController);
 
-        template<class T>
-        const T* getSensorValue(const std::string& sensorDeviceName) const;
-        template<class T>
-        T* getControlTarget(const std::string& deviceName, const std::string& controlMode);
-    };
+    TYPEDEF_PTRS_HANDLE(RobotUnit);
 
     /**
     * @defgroup Library-RobotUnit RobotUnit
@@ -158,6 +153,51 @@ namespace armarx
         virtual public NJointControllerInterface,
         virtual public ManagedIceObject
     {
+        //firends
+        /**
+        * \brief This class allows minimal access to private members of \ref NJointController in a sane fashion for \ref RobotUnitModule::ControllerManagement.
+        * \warning !! DO NOT ADD ADDITIONAL FRIENDS IF YOU DO NOT KNOW WAHT YOU ARE DOING! IF YOU DO SOMETHING WRONG YOU WILL CAUSE UNDEFINED BEHAVIOUR !!
+        */
+        friend class RobotUnitModule::NJointControllerAttorneyForControllerManagement;
+        /**
+        * \brief This class allows minimal access to private members of \ref NJointController in a sane fashion for \ref RobotUnitModule::ControlThread.
+        * \warning !! DO NOT ADD ADDITIONAL FRIENDS IF YOU DO NOT KNOW WAHT YOU ARE DOING! IF YOU DO SOMETHING WRONG YOU WILL CAUSE UNDEFINED BEHAVIOUR !!
+        */
+        friend class RobotUnitModule::NJointControllerAttorneyForControlThread;
+        /**
+        * \brief This class allows minimal access to private members of \ref NJointController in a sane fashion for \ref RobotUnitModule::Publisher.
+        * \warning !! DO NOT ADD ADDITIONAL FRIENDS IF YOU DO NOT KNOW WAHT YOU ARE DOING! IF YOU DO SOMETHING WRONG YOU WILL CAUSE UNDEFINED BEHAVIOUR !!
+        */
+        friend class RobotUnitModule::NJointControllerAttorneyForPublisher;
+        /**
+        * \brief This is required for the factory
+        * \warning !! DO NOT ADD ADDITIONAL FRIENDS IF YOU DO NOT KNOW WAHT YOU ARE DOING! IF YOU DO SOMETHING WRONG YOU WILL CAUSE UNDEFINED BEHAVIOUR !!
+        */
+        template<class> friend class detail::NJointControllerRegistryEntryHelperBase;
+    public:
+
+        ConstSensorDevicePtr   peekSensorDevice(const std::string& deviceName) const;
+        ConstControlDevicePtr peekControlDevice(const std::string& deviceName) const;
+
+        ControlTargetBase* useControlTarget(const std::string& deviceName, const std::string& controlMode);
+        template<class T>
+        T* useControlTarget(const std::string& deviceName, const std::string& controlMode)
+        {
+            static_assert(std::is_base_of<ControlTargetBase, T>::value, "The given type does not derive ControlTargetBase");
+            ControlTargetBase* const ptr = useControlTarget(deviceName, controlMode);
+            return ptr ? ptr->asA<T>(): nullptr;
+        }
+        const SensorValueBase* useSensorValue(const std::string& sensorDeviceName) const;
+        template<class T>
+        const T* useSensorValue(const std::string& deviceName) const
+        {
+            static_assert(std::is_base_of<SensorValueBase, T>::value, "The given type does not derive SensorValueBase");
+            const SensorValueBase* const ptr = useSensorValue(deviceName);
+            return ptr ? ptr->asA<T>(): nullptr;
+        }
+
+        void useSynchronizedRtRobot(bool updateCollisionModel = false);
+
     protected:
         std::string getDefaultName() const override;
         void onInitComponent() override;
@@ -189,6 +229,8 @@ namespace armarx
 
         static const NJointControllerPtr NullPtr;
 
+        NJointController();
+
         ~NJointController() override = default;
         //ice interface (must not be called in the rt thread)
         bool isControllerActive(const Ice::Current& = GlobalIceCurrent) const final override;
@@ -211,11 +253,22 @@ namespace armarx
         WidgetDescription::StringWidgetDictionary getFunctionDescriptions(const Ice::Current& = GlobalIceCurrent) const override;
         void callDescribedFunction(const std::string&, const StringVariantBaseMap&, const Ice::Current& = GlobalIceCurrent) override;
 
-        std::size_t getId() const;
+//        std::size_t getId() const;
 
         //c++ interface (local calls) (must be called in the rt thread)
         virtual void rtRun(const IceUtil::Time& sensorValuesTimestamp, const IceUtil::Time& timeSinceLastIteration) = 0;
         virtual void rtSwapBufferAndRun(const IceUtil::Time& sensorValuesTimestamp, const IceUtil::Time& timeSinceLastIteration);
+
+        const VirtualRobot::RobotPtr& rtGetRobot()
+        {
+            return rtRobot;
+        }
+
+        const std::vector<VirtualRobot::RobotNodePtr>& rtGetRobotNodes()
+        {
+            return rtRobotNodes;
+        }
+
     protected:
         /**
          * @brief This function is called before the controller is activated.
@@ -230,7 +283,7 @@ namespace armarx
     public:
         bool rtUsesControlDevice(std::size_t deviceIndex) const;
 
-        std::size_t rtGetId() const;
+//        std::size_t rtGetId() const;
 
         //used control devices
         StringStringDictionary getControlDeviceUsedControlModeMap(const Ice::Current& = GlobalIceCurrent) const final override;
@@ -259,19 +312,8 @@ namespace armarx
         void rtDeactivateController();
         void rtDeactivateControllerBecauseOfError();
 
-        //firends
-        friend class RobotUnitNJointControllerAccess;
-
-        void robotUnitInit(RobotUnit* ru,
-                           std::size_t ctrlId,
-                           std::map<std::string, const JointController*> ctrlDeviceControlModeMap,
-                           std::vector<char> ctrlDeviceUsedBitmap,
-                           std::vector<std::size_t> ctrlDeviceUsedIndices,
-                           bool ctrlDeletable,
-                           bool ctrlInternal);
-
-        RobotUnit* robotUnit;
-        std::size_t id = std::numeric_limits<std::size_t>::max();
+        RobotUnit& robotUnit;
+//        const std::size_t id;
         StringStringDictionary controlDeviceControlModeMap;
         std::map<std::string, const JointController*> controlDeviceUsedJointController;
         std::vector<char> controlDeviceUsedBitmap;
@@ -289,22 +331,38 @@ namespace armarx
         std::atomic_bool statusReportedActive {false};
         std::atomic_bool statusReportedRequested {false};
 
-    public:
-        struct IdComp
-        {
-            template<class PtrT1, class PtrT2>
-            bool operator()(PtrT1 l, PtrT2 r) const;
-        };
+        VirtualRobot::RobotPtr rtRobot;
+        std::vector<VirtualRobot::RobotNodePtr> rtRobotNodes;
     };
+}
+
+namespace armarx
+{
+    namespace RobotUnitModule
+    {
+        class ControllerManagement;
+    }
 
     class NJointControllerRegistryEntry
     {
     private:
-        friend class RobotUnit;
-        virtual NJointControllerPtr create(NJointControllerDescriptionProviderInterfacePtr, const NJointControllerConfigPtr&, const boost::shared_ptr<VirtualRobot::Robot>&) const = 0;
+        friend class RobotUnitModule::ControllerManagement;
+        virtual NJointControllerPtr create(
+                RobotUnitModule::ControllerManagement* cmngr,
+                const NJointControllerConfigPtr&,
+                const boost::shared_ptr<VirtualRobot::Robot>&,
+                bool deletable,
+                bool internal) const = 0;
         virtual WidgetDescription::WidgetPtr GenerateConfigDescription(const boost::shared_ptr<VirtualRobot::Robot>&, const std::map<std::string, ConstControlDevicePtr>&, const std::map<std::string, ConstSensorDevicePtr>&) const = 0;
         virtual NJointControllerConfigPtr GenerateConfigFromVariants(const StringVariantBaseMap&) const = 0;
         virtual bool hasRemoteConfiguration() const = 0;
+    protected:
+        static thread_local bool ConstructorIsRunning_;
+    public:
+        static bool ConstructorIsRunning()
+        {
+            return ConstructorIsRunning_;
+        }
     };
     using NJointControllerRegistry = Registrar<std::unique_ptr<NJointControllerRegistryEntry>>;
 
@@ -348,31 +406,6 @@ namespace armarx
 //inline functions
 namespace armarx
 {
-    //NJointControllerDescriptionProviderInterface
-    inline const SensorValueBase* NJointControllerDescriptionProviderInterface::getSensorValue(const std::string& sensorDeviceName) const
-    {
-        auto sd = getSensorDevice(sensorDeviceName);
-        return sd ? sd->getSensorValue() : nullptr;
-    }
-
-    template<class T>
-    inline const T* NJointControllerDescriptionProviderInterface::getSensorValue(const std::string& sensorDeviceName) const
-    {
-        return dynamic_cast<const T*>(getSensorValue(sensorDeviceName));
-    }
-
-    template<class T>
-    inline T* NJointControllerDescriptionProviderInterface::getControlTarget(const std::string& deviceName, const std::string& controlMode)
-    {
-        return dynamic_cast<T*>(getControlTarget(deviceName, controlMode));
-    }
-
-    //NJointController
-    inline std::size_t NJointController::getId() const
-    {
-        return id;
-    }
-
     inline void NJointController::rtSwapBufferAndRun(const IceUtil::Time& sensorValuesTimestamp, const IceUtil::Time& timeSinceLastIteration)
     {
         rtRun(sensorValuesTimestamp, timeSinceLastIteration);
@@ -383,11 +416,6 @@ namespace armarx
         return controlDeviceUsedBitmap.at(deviceIndex);
     }
 
-    inline std::size_t NJointController::rtGetId() const
-    {
-        return id;
-    }
-
     inline StringStringDictionary NJointController::getControlDeviceUsedControlModeMap(const Ice::Current&) const
     {
         return controlDeviceControlModeMap;
@@ -465,21 +493,6 @@ namespace armarx
     {
     }
 
-    template<class PtrT1, class PtrT2>
-    inline bool NJointController::IdComp::operator()(PtrT1 l, PtrT2 r) const
-    {
-        //null is bigger than any other
-        if (!l)
-        {
-            return false;
-        }
-        if (!r)
-        {
-            return true;
-        }
-        return l->id < r->id;
-    }
-
     //NJointControllerWithTripleBuffer<ControlDataStruct>
     template <typename ControlDataStruct>
     void NJointControllerWithTripleBuffer<ControlDataStruct>::rtSwapBufferAndRun(
@@ -532,4 +545,4 @@ namespace armarx
         controlDataTripleBuffer.reinitAllBuffers(initial);
     }
 }
-#include "NJointController.hpp"
+#include "NJointController.ipp"
diff --git a/source/RobotAPI/components/units/RobotUnit/NJointControllers/NJointController.hpp b/source/RobotAPI/components/units/RobotUnit/NJointControllers/NJointController.ipp
similarity index 80%
rename from source/RobotAPI/components/units/RobotUnit/NJointControllers/NJointController.hpp
rename to source/RobotAPI/components/units/RobotUnit/NJointControllers/NJointController.ipp
index f1579a7483a6ba25dfb6875832ea0614c2492565..41cce1faf33e0395e450c19572ed8bfbcd253956 100644
--- a/source/RobotAPI/components/units/RobotUnit/NJointControllers/NJointController.hpp
+++ b/source/RobotAPI/components/units/RobotUnit/NJointControllers/NJointController.ipp
@@ -23,8 +23,13 @@
 #ifndef _ARMARX_LIB_RobotAPI_NJointController_HPP
 #define _ARMARX_LIB_RobotAPI_NJointController_HPP
 
+#include <thread>
+
 #include <ArmarXCore/core/util/TemplateMetaProgramming.h>
+#include <ArmarXCore/core/util/OnScopeExit.h>
+
 #include "NJointController.h"
+#include "../RobotUnit.h"
 
 namespace armarx
 {
@@ -52,20 +57,39 @@ namespace armarx
 
     namespace detail
     {
-        template<class NJointControllerT, class = void, class = void>
-        class NJointControllerRegistryEntryHelper : public NJointControllerRegistryEntry
+        template<class NJointControllerT>
+        class NJointControllerRegistryEntryHelperBase : public NJointControllerRegistryEntry
         {
-            NJointControllerPtr create(NJointControllerDescriptionProviderInterfacePtr prov,
-                                       const NJointControllerConfigPtr& config,
-                                       const boost::shared_ptr<VirtualRobot::Robot>& rob) const final override
+            NJointControllerPtr create(RobotUnitModule::ControllerManagement* cmngr,
+                const NJointControllerConfigPtr& config,
+                const boost::shared_ptr<VirtualRobot::Robot>& rob,
+                bool deletable,
+                bool internal) const final override
             {
-                ARMARX_CHECK_EXPRESSION_W_HINT(prov, "DataProvider is NULL!");
-                using ConfigPtrT = typename NJointControllerT::ConfigPtrT;
-                ConfigPtrT cfg = ConfigPtrT::dynamicCast(config);
-                ARMARX_CHECK_EXPRESSION_W_HINT(cfg, "The configuration is of the wrong type! it has to be an instance of: "
-                                               << GetTypeString<ConfigPtrT>());
-                return new NJointControllerT(prov, cfg, rob);
+                ARMARX_CHECK_EXPRESSION_W_HINT(cmngr, "ControllerManagement module is NULL!");
+
+               using ConfigPtrT = typename NJointControllerT::ConfigPtrT;
+               ConfigPtrT cfg = ConfigPtrT::dynamicCast(config);
+               ARMARX_CHECK_EXPRESSION_W_HINT(cfg, "The configuration is of the wrong type! it has to be an instance of: "
+                                                   << GetTypeString<ConfigPtrT>());
+
+                ARMARX_CHECK_EXPRESSION_W_HINT(!ConstructorIsRunning(), "Two NJointControllers are created at the same time");
+                NJointControllerPtr ptr;
+                {
+                    ConstructorIsRunning_ = true;
+                    ARMARX_ON_SCOPE_EXIT{ConstructorIsRunning_ = false;};
+                    ptr = new NJointControllerT(cmngr->_modulePtr<RobotUnit>(), cfg, rob);
+                }
+                ptr->deletable = deletable;
+                ptr->internal = internal;
+                return ptr;
             }
+        };
+
+
+        template<class NJointControllerT, class = void, class = void>
+        class NJointControllerRegistryEntryHelper : public NJointControllerRegistryEntryHelperBase<NJointControllerT>
+        {
             WidgetDescription::WidgetPtr GenerateConfigDescription(const boost::shared_ptr<VirtualRobot::Robot>&,
                     const std::map<std::string, ConstControlDevicePtr>&,
                     const std::map<std::string, ConstSensorDevicePtr>&) const final override
@@ -95,23 +119,10 @@ namespace armarx
         template<class NJointControllerT>
         class NJointControllerRegistryEntryHelper <
             NJointControllerT,
-        //            meta::void_t<decltype(NJointControllerT::GenerateConfigDescription)>,
             typename std::enable_if < hasGenerateConfigDescription<NJointControllerT>::value >::type,
-        //            meta::void_t<decltype(NJointControllerT::GenerateConfigFromVariants)
             typename std::enable_if < hasGenerateConfigFromVariants<NJointControllerT>::value >::type
-            > : public NJointControllerRegistryEntry
+            > : public NJointControllerRegistryEntryHelperBase<NJointControllerT>
         {
-            NJointControllerPtr create(NJointControllerDescriptionProviderInterfacePtr prov,
-                                       const NJointControllerConfigPtr& config,
-                                       const boost::shared_ptr<VirtualRobot::Robot>& rob) const final override
-            {
-                ARMARX_CHECK_EXPRESSION_W_HINT(prov, "DataProvider is NULL!");
-                using ConfigPtrT = typename NJointControllerT::ConfigPtrT;
-                ConfigPtrT cfg = ConfigPtrT::dynamicCast(config);
-                ARMARX_CHECK_EXPRESSION_W_HINT(cfg, "The configuration is of the wrong type! it has to be an instance of: "
-                                               << GetTypeString<ConfigPtrT>());
-                return new NJointControllerT(prov, cfg, rob);
-            }
             WidgetDescription::WidgetPtr GenerateConfigDescription(
                 const boost::shared_ptr<VirtualRobot::Robot>& robot,
                 const std::map<std::string, ConstControlDevicePtr>& controlDevices,
@@ -191,4 +202,6 @@ namespace armarx
         }
     };
 }
+
+
 #endif
diff --git a/source/RobotAPI/components/units/RobotUnit/NJointControllers/NJointHolonomicPlatformUnitVelocityPassThroughController.cpp b/source/RobotAPI/components/units/RobotUnit/NJointControllers/NJointHolonomicPlatformUnitVelocityPassThroughController.cpp
index f5bc30a8521b64942a5d8940328531f8b1b88905..148090ede09cbaf44fe80ccc2c581f6bc50b9668 100644
--- a/source/RobotAPI/components/units/RobotUnit/NJointControllers/NJointHolonomicPlatformUnitVelocityPassThroughController.cpp
+++ b/source/RobotAPI/components/units/RobotUnit/NJointControllers/NJointHolonomicPlatformUnitVelocityPassThroughController.cpp
@@ -27,11 +27,11 @@
 using namespace armarx;
 
 NJointHolonomicPlatformUnitVelocityPassThroughController::NJointHolonomicPlatformUnitVelocityPassThroughController(
-    NJointControllerDescriptionProviderInterfacePtr prov,
+    RobotUnitPtr prov,
     NJointHolonomicPlatformUnitVelocityPassThroughControllerConfigPtr
     cfg, const VirtualRobot::RobotPtr&)
 {
-    target = prov->getControlTarget(cfg->platformName, ControlModes::HolonomicPlatformVelocity)->asA<ControlTargetHolonomicPlatformVelocity>();
+    target = useControlTarget(cfg->platformName, ControlModes::HolonomicPlatformVelocity)->asA<ControlTargetHolonomicPlatformVelocity>();
     ARMARX_CHECK_EXPRESSION_W_HINT(target, "The actuator " << cfg->platformName << " has no control mode " << ControlModes::HolonomicPlatformVelocity);
 
     initialSettings.velocityX        = cfg->initialVelocityX;
diff --git a/source/RobotAPI/components/units/RobotUnit/NJointControllers/NJointHolonomicPlatformUnitVelocityPassThroughController.h b/source/RobotAPI/components/units/RobotUnit/NJointControllers/NJointHolonomicPlatformUnitVelocityPassThroughController.h
index 8cc71e9189a91e84d3f6a2965a129932e0cff580..313f95abefef29bc3f020c3bd1a6a9b965b3976e 100644
--- a/source/RobotAPI/components/units/RobotUnit/NJointControllers/NJointHolonomicPlatformUnitVelocityPassThroughController.h
+++ b/source/RobotAPI/components/units/RobotUnit/NJointControllers/NJointHolonomicPlatformUnitVelocityPassThroughController.h
@@ -58,7 +58,7 @@ namespace armarx
         using ConfigPtrT = NJointHolonomicPlatformUnitVelocityPassThroughControllerConfigPtr;
 
         NJointHolonomicPlatformUnitVelocityPassThroughController(
-            NJointControllerDescriptionProviderInterfacePtr prov,
+            RobotUnitPtr prov,
             NJointHolonomicPlatformUnitVelocityPassThroughControllerConfigPtr config,
             const VirtualRobot::RobotPtr&);
 
diff --git a/source/RobotAPI/components/units/RobotUnit/NJointControllers/NJointKinematicUnitPassThroughController.cpp b/source/RobotAPI/components/units/RobotUnit/NJointControllers/NJointKinematicUnitPassThroughController.cpp
index 02da648c7dffcee50611d9928ce6478a9b0ac34d..61e768884245fc6a1601b3a867d160d2504037db 100644
--- a/source/RobotAPI/components/units/RobotUnit/NJointControllers/NJointKinematicUnitPassThroughController.cpp
+++ b/source/RobotAPI/components/units/RobotUnit/NJointControllers/NJointKinematicUnitPassThroughController.cpp
@@ -26,11 +26,11 @@ using namespace armarx;
 NJointControllerRegistration<NJointKinematicUnitPassThroughController> registrationControllerNJointKinematicUnitPassThroughController("NJointKinematicUnitPassThroughController");
 
 NJointKinematicUnitPassThroughController::NJointKinematicUnitPassThroughController(
-    NJointControllerDescriptionProviderInterfacePtr prov,
+    RobotUnitPtr prov,
     const NJointKinematicUnitPassThroughControllerConfigPtr& cfg,
     const VirtualRobot::RobotPtr&)
 {
-    const SensorValueBase* sv = prov->getSensorValue(cfg->deviceName);
+    const SensorValueBase* sv = useSensorValue(cfg->deviceName);
 
     std::string controlMode = cfg->controlMode;
     std::string deviceName = cfg->deviceName;
@@ -41,7 +41,7 @@ NJointKinematicUnitPassThroughController::NJointKinematicUnitPassThroughControll
         controlMode = ControlModes::VelocityTorque;
     }*/
 
-    ControlTargetBase* ct = prov->getControlTarget(cfg->deviceName, controlMode);
+    ControlTargetBase* ct = useControlTarget(cfg->deviceName, controlMode);
     //get sensor
     if (controlMode == ControlModes::Position1DoF)
     {
diff --git a/source/RobotAPI/components/units/RobotUnit/NJointControllers/NJointKinematicUnitPassThroughController.h b/source/RobotAPI/components/units/RobotUnit/NJointControllers/NJointKinematicUnitPassThroughController.h
index 6936d394c847beb6f64409914a9471820bb0ff41..3119a0fc23a89029515d6829087798f358ed49b5 100644
--- a/source/RobotAPI/components/units/RobotUnit/NJointControllers/NJointKinematicUnitPassThroughController.h
+++ b/source/RobotAPI/components/units/RobotUnit/NJointControllers/NJointKinematicUnitPassThroughController.h
@@ -53,7 +53,7 @@ namespace armarx
         using ConfigPtrT = NJointKinematicUnitPassThroughControllerConfigPtr;
 
         inline NJointKinematicUnitPassThroughController(
-            NJointControllerDescriptionProviderInterfacePtr prov,
+            RobotUnitPtr prov,
             const NJointKinematicUnitPassThroughControllerConfigPtr& cfg,
             const VirtualRobot::RobotPtr&);
 
diff --git a/source/RobotAPI/components/units/RobotUnit/NJointControllers/NJointTCPController.cpp b/source/RobotAPI/components/units/RobotUnit/NJointControllers/NJointTCPController.cpp
index d2df87384c5dac6572a462f8ab10b87e892b08c9..6350540cb8fce388944f31dc2b94359bd2a7d657 100644
--- a/source/RobotAPI/components/units/RobotUnit/NJointControllers/NJointTCPController.cpp
+++ b/source/RobotAPI/components/units/RobotUnit/NJointControllers/NJointTCPController.cpp
@@ -154,24 +154,23 @@ namespace armarx
         return new NJointTCPControllerConfig {values.at("nodeSetName")->getString(), values.at("tcpName")->getString()};
     }
 
-    NJointTCPController::NJointTCPController(NJointControllerDescriptionProviderInterfacePtr prov, NJointTCPControllerConfigPtr config, const boost::shared_ptr<VirtualRobot::Robot>& r)
+    NJointTCPController::NJointTCPController(RobotUnitPtr robotUnit, 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);
+        useSynchronizedRtRobot();
+        auto nodeset = rtGetRobot()->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);
+            ControlTargetBase* ct = useControlTarget(jointName, ControlModes::Velocity1DoF);
+            const SensorValueBase* sv = useSensorValue(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);
+        ik.reset(new VirtualRobot::DifferentialIK(nodeset, rtGetRobot()->getRootNode(), VirtualRobot::JacobiProvider::eSVDDamped));
+        tcp = (config->tcpName.empty() || config->tcpName == DEFAULT_TCP_STRING) ? nodeset->getTCP() : rtGetRobot()->getRobotNode(config->tcpName);
         ARMARX_CHECK_EXPRESSION_W_HINT(tcp, config->tcpName);
 
         nodeSetName = config->nodeSetName;
diff --git a/source/RobotAPI/components/units/RobotUnit/NJointControllers/NJointTCPController.h b/source/RobotAPI/components/units/RobotUnit/NJointControllers/NJointTCPController.h
index 46eff8bfb2003a4ed9216c86a57c23faaf7a2367..d0fadce61ccc38c35cf307dbd6b8d30dfe3227f7 100644
--- a/source/RobotAPI/components/units/RobotUnit/NJointControllers/NJointTCPController.h
+++ b/source/RobotAPI/components/units/RobotUnit/NJointControllers/NJointTCPController.h
@@ -68,7 +68,7 @@ namespace armarx
     {
     public:
         using ConfigPtrT = NJointTCPControllerConfigPtr;
-        NJointTCPController(NJointControllerDescriptionProviderInterfacePtr prov, const NJointControllerConfigPtr& config, const VirtualRobot::RobotPtr&);
+        NJointTCPController(RobotUnitPtr prov, const NJointControllerConfigPtr& config, const VirtualRobot::RobotPtr&);
 
         // NJointControllerInterface interface
         std::string getClassName(const Ice::Current&) const override;
@@ -84,7 +84,7 @@ namespace armarx
 
         static NJointTCPControllerConfigPtr GenerateConfigFromVariants(const StringVariantBaseMap& values);
         NJointTCPController(
-            NJointControllerDescriptionProviderInterfacePtr prov,
+            RobotUnitPtr prov,
             NJointTCPControllerConfigPtr config,
             const boost::shared_ptr<VirtualRobot::Robot>& r);
 
diff --git a/source/RobotAPI/components/units/RobotUnit/NJointControllers/NJointTrajectoryController.cpp b/source/RobotAPI/components/units/RobotUnit/NJointControllers/NJointTrajectoryController.cpp
index c988cec09e2d59ad93e63eb38dde3d7eeb3d5306..9071e66b2e4cb6b01d6cce20bff7dd2a3ff0db19 100644
--- a/source/RobotAPI/components/units/RobotUnit/NJointControllers/NJointTrajectoryController.cpp
+++ b/source/RobotAPI/components/units/RobotUnit/NJointControllers/NJointTrajectoryController.cpp
@@ -7,15 +7,15 @@ namespace armarx
 {
     NJointControllerRegistration<NJointTrajectoryController> registrationControllerNJointTrajectoryController("NJointTrajectoryController");
 
-    NJointTrajectoryController::NJointTrajectoryController(NJointControllerDescriptionProviderInterfacePtr prov, const NJointControllerConfigPtr& config, const VirtualRobot::RobotPtr& robot)
+    NJointTrajectoryController::NJointTrajectoryController(RobotUnitPtr prov, const NJointControllerConfigPtr& config, const VirtualRobot::RobotPtr& robot)
     {
         cfg = NJointTrajectoryControllerConfigPtr::dynamicCast(config);
         ARMARX_CHECK_EXPRESSION_W_HINT(cfg, "Needed type: NJointTrajectoryControllerConfigPtr");
 
         for (std::string jointName : cfg->jointNames)
         {
-            ControlTargetBase* ct = prov->getControlTarget(jointName, ControlModes::Velocity1DoF);
-            const SensorValueBase* sv = prov->getSensorValue(jointName);
+            ControlTargetBase* ct = useControlTarget(jointName, ControlModes::Velocity1DoF);
+            const SensorValueBase* sv = useSensorValue(jointName);
             targets.insert(std::make_pair(jointName, ct->asA<ControlTarget1DoFActuatorVelocity>()));
             sensors.insert(std::make_pair(jointName, sv->asA<SensorValue1DoFActuatorPosition>()));
         }
diff --git a/source/RobotAPI/components/units/RobotUnit/NJointControllers/NJointTrajectoryController.h b/source/RobotAPI/components/units/RobotUnit/NJointControllers/NJointTrajectoryController.h
index 5de238702fdc2b06dc40b84d6a9315a0e0b1fc9b..755428ec0b82b271338bf7c8ba3c9dedb0e41eb2 100644
--- a/source/RobotAPI/components/units/RobotUnit/NJointControllers/NJointTrajectoryController.h
+++ b/source/RobotAPI/components/units/RobotUnit/NJointControllers/NJointTrajectoryController.h
@@ -24,7 +24,7 @@ namespace armarx
         public NJointTrajectoryControllerInterface
     {
     public:
-        NJointTrajectoryController(NJointControllerDescriptionProviderInterfacePtr prov, const NJointControllerConfigPtr& config, const VirtualRobot::RobotPtr&);
+        NJointTrajectoryController(RobotUnitPtr prov, const NJointControllerConfigPtr& config, const VirtualRobot::RobotPtr&);
 
         // NJointControllerInterface interface
         std::string getClassName(const Ice::Current&) const override;
diff --git a/source/RobotAPI/components/units/RobotUnit/RobotSynchronization.cpp b/source/RobotAPI/components/units/RobotUnit/RobotSynchronization.cpp
deleted file mode 100644
index 5f8857e1a34184fd3617fdd97065299aa96a6728..0000000000000000000000000000000000000000
--- a/source/RobotAPI/components/units/RobotUnit/RobotSynchronization.cpp
+++ /dev/null
@@ -1,78 +0,0 @@
-/*
- * This file is part of ArmarX.
- *
- * 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    RobotAPI::RobotUnit::RobotSynchronization
- * @author     Stefan Reither ( stef dot reither at web dot de )
- * @date       2017
- * @copyright  http://www.gnu.org/licenses/gpl-2.0.txt
- *             GNU General Public License
- */
-
-#include "RobotSynchronization.h"
-#include <RobotAPI/interface/units/RobotUnit/RobotUnitInterface.h>
-#include "SensorValues/SensorValue1DoFActuator.h"
-
-#include "RobotUnit.h"
-
-using namespace armarx;
-
-RobotSynchronization::RobotSynchronization(RobotUnit* robotUnit, VirtualRobot::RobotPtr& robot, const std::vector<std::string>& synchronizingJoints)
-{
-    this->robotUnit = robotUnit;
-    this->robot = robot;
-    Ice::StringSeq names = robotUnit->getSensorDeviceNames(GlobalIceCurrent);
-
-    for (std::string name : names)
-    {
-        // skip, if the current sensor device does not correspond to a joint.
-        if (!this->robot->hasRobotNode(name))
-        {
-            continue;
-        }
-
-        ConstSensorDevicePtr device = robotUnit->getSensorDevice(name);
-
-        // skip, if the sensor value of the current sensor device can't provide a position.
-        if (!device->getSensorValue()->isA<SensorValue1DoFActuatorPosition>())
-        {
-            continue;
-        }
-
-        std::vector<std::string>::const_iterator it = std::find(synchronizingJoints.begin(), synchronizingJoints.end(), name);
-        if (it == synchronizingJoints.end())
-        {
-            continue;
-        }
-        else
-        {
-            jointSensorDeviceMap[*it] = device;
-        }
-    }
-}
-
-void RobotSynchronization::sync()
-{
-    if (robotUnit->getRobotUnitState() == RobotUnitState::InitializingUnits || robotUnit->getRobotUnitState() == RobotUnitState::Running)
-    {
-        for (auto const& entry : jointSensorDeviceMap)
-        {
-            const SensorValueBase* sv = entry.second->getSensorValue();
-
-            ARMARX_CHECK_EXPRESSION(sv->asA<SensorValue1DoFActuatorPosition>());
-            robot->getRobotNode(entry.first)->setJointValueNoUpdate(sv->asA<SensorValue1DoFActuatorPosition>()->position);
-        }
-        robot->applyJointValues();
-    }
-}
diff --git a/source/RobotAPI/components/units/RobotUnit/RobotSynchronization.h b/source/RobotAPI/components/units/RobotUnit/RobotSynchronization.h
deleted file mode 100644
index 2b65c5f57414e5ef8ba15d1d8ed2230325814090..0000000000000000000000000000000000000000
--- a/source/RobotAPI/components/units/RobotUnit/RobotSynchronization.h
+++ /dev/null
@@ -1,52 +0,0 @@
-/*
- * This file is part of ArmarX.
- *
- * 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    RobotAPI::RobotUnit::RobotSynchronization
- * @author     Stefan Reither ( stef dot reither at web dot de )
- * @date       2017
- * @copyright  http://www.gnu.org/licenses/gpl-2.0.txt
- *             GNU General Public License
- */
-
-#pragma once
-
-#include <VirtualRobot/Robot.h>
-#include "Devices/SensorDevice.h"
-
-#include <string>
-#include <vector>
-
-namespace armarx
-{
-    class RobotUnit;
-    class SensorValue1DoFActuatorPosition;
-
-    TYPEDEF_PTRS_SHARED(RobotSynchronization);
-    /**
-     * @brief The RobotSynchronization class
-     */
-    class RobotSynchronization
-    {
-    public:
-        RobotSynchronization(RobotUnit* robotUnit, VirtualRobot::RobotPtr& robot, const std::vector<std::string>& synchronizingJoints);
-        ~RobotSynchronization() {}
-        void sync();
-
-    private:
-        std::map<std::string, ConstSensorDevicePtr> jointSensorDeviceMap;
-        RobotUnit* robotUnit = NULL;
-        VirtualRobot::RobotPtr robot;
-    };
-}
diff --git a/source/RobotAPI/components/units/RobotUnit/RobotUnit.cpp b/source/RobotAPI/components/units/RobotUnit/RobotUnit.cpp
index 5791b8bcfacce0fe292dfd0778b6ac9610f27bc5..e3ad39c38ffba9e7241da8ed69b85a8028ca7dc9 100644
--- a/source/RobotAPI/components/units/RobotUnit/RobotUnit.cpp
+++ b/source/RobotAPI/components/units/RobotUnit/RobotUnit.cpp
@@ -22,3276 +22,6 @@
 
 #include "RobotUnit.h"
 
-#include <algorithm>
-
-#include <boost/algorithm/string/predicate.hpp>
-
-#include <VirtualRobot/XML/RobotIO.h>
-#include <VirtualRobot/Nodes/ForceTorqueSensor.h>
-#include <VirtualRobot/Robot.h>
-#include <VirtualRobot/RobotNodeSet.h>
-#include <VirtualRobot/Visualization/VisualizationNode.h>
-#include <VirtualRobot/Obstacle.h>
-#include <VirtualRobot/SceneObjectSet.h>
-#include <VirtualRobot/Nodes/RobotNode.h>
-#include <ArmarXCore/core/system/cmake/CMakePackageFinder.h>
-#include <ArmarXCore/observers/variant/TimestampVariant.h>
-#include <ArmarXCore/core/IceManager.h>
-#include <ArmarXCore/core/IceGridAdmin.h>
-#include <ArmarXCore/core/util/FileSystemPathBuilder.h>
-#include <ArmarXCore/core/system/ArmarXDataPath.h>
-
-#include "Units/ForceTorqueSubUnit.h"
-#include "Units/InertialMeasurementSubUnit.h"
-#include "Units/KinematicSubUnit.h"
-#include "Units/PlatformSubUnit.h"
-#include "SensorValues/SensorValue1DoFActuator.h"
-#include "Units/TCPControllerSubUnit.h"
-#include "Units/TrajectoryControllerSubUnit.h"
-
-namespace std
-{
-    std::string to_string(armarx::RobotUnitState s)
-    {
-        switch (s)
-        {
-            case armarx::RobotUnitState::PreComponentInitialization:
-                return "PreComponentInitialization";
-            case armarx::RobotUnitState::InitializingDevices:
-                return "InitializingDevices";
-            case armarx::RobotUnitState::InitializingUnits:
-                return "InitializingUnits";
-            case armarx::RobotUnitState::WaitingForRTThreadInitialization:
-                return "WaitingForRTThreadInitialization";
-            case armarx::RobotUnitState::Running:
-                return "Running";
-            case armarx::RobotUnitState::Exiting:
-                return "Exiting";
-        }
-        throw std::invalid_argument {"Unknown state " + std::to_string(static_cast<std::size_t>(s))};
-    }
-}
-
 namespace armarx
 {
-    class RobotUnitEmergencyStopMaster :
-        virtual public ManagedIceObject,
-        virtual public EmergencyStopMasterInterface
-    {
-    public:
-        RobotUnitEmergencyStopMaster(RobotUnit* robotUnit, std::string emergencyStopTopicName) :
-            robotUnit {robotUnit},
-                  emergencyStopTopicName {emergencyStopTopicName}
-        {}
-
-        void setEmergencyStopState(EmergencyStopState state, const Ice::Current& = GlobalIceCurrent) final override
-        {
-            robotUnit->setEmergencyStopState(state);
-            emergencyStopTopic->reportEmergencyStopState(state);
-        }
-        EmergencyStopState getEmergencyStopState(const Ice::Current& = GlobalIceCurrent) const final override
-        {
-            return robotUnit->getEmergencyStopState();
-        }
-
-    protected:
-        void onInitComponent() final override
-        {
-            armarx::ManagedIceObject::offeringTopic(emergencyStopTopicName);
-        }
-        void onConnectComponent() final override
-        {
-            emergencyStopTopic = armarx::ManagedIceObject::getTopic<EmergencyStopListenerPrx>(emergencyStopTopicName);
-            setEmergencyStopState(EmergencyStopState::eEmergencyStopInactive);
-        }
-
-        std::string getDefaultName() const final override
-        {
-            return "EmergencyStopMaster";
-        }
-
-    protected:
-        RobotUnit* const robotUnit;
-        const std::string emergencyStopTopicName;
-        EmergencyStopListenerPrx emergencyStopTopic;
-    };
-
-    namespace detail
-    {
-        std::function<std::string(const std::string&)> makeDebugObserverNameFixer(const std::string& prefix)
-        {
-            return
-                [prefix](const std::string & name)
-            {
-                std::string s = prefix + name;
-                std::replace(s.begin(), s.end(), '.', '_');
-                std::replace(s.begin(), s.end(), ':', '_');
-                return s;
-            };
-        }
-    }
-
-    const std::string armarx::RobotUnit::rtThreadTimingsSensorDeviceName = "RTThreadTimings";
-
-    const std::set<RobotUnitState> armarx::RobotUnit::devicesReadyStates
-    {
-        RobotUnitState::InitializingUnits,
-        RobotUnitState::WaitingForRTThreadInitialization,
-        RobotUnitState::Running
-    };
-    armarx::RobotUnit::GuardType armarx::RobotUnit::getGuard() const
-    {
-        if (std::this_thread::get_id() == rtThreadId)
-        {
-            throw std::logic_error {"Attempted to lock mutex in RT thread"};
-        }
-        return GuardType {dataMutex};
-    }
-
-    void armarx::RobotUnit::checkNJointControllerClassName(const std::string& className) const
-    {
-        if (!NJointControllerRegistry::has(className))
-        {
-            std::stringstream ss;
-            ss << "Requested controller class '" << className << "' unknown! Known classes:" << NJointControllerRegistry::getKeys()
-               << " (If this class exists in a different lib then load it via loadLibFromPath(path) or loadLibFromPackage(package, lib))";
-            ARMARX_ERROR << ss.str();
-            throw InvalidArgumentException {ss.str()};
-        }
-    }
-
-    void armarx::RobotUnit::addControlDevice(const ControlDevicePtr& cd)
-    {
-        auto guard = getGuard();
-        throwIfStateIsNot(RobotUnitState::InitializingDevices, __FUNCTION__);
-        controlDevices.add(cd->getDeviceName(), cd);
-        ARMARX_INFO << "added ControlDevice " << cd->getDeviceName();
-    }
-
-    void armarx::RobotUnit::addSensorDevice(const SensorDevicePtr& sd)
-    {
-        auto guard = getGuard();
-        throwIfStateIsNot(RobotUnitState::InitializingDevices, __FUNCTION__);
-        if (!sd)
-        {
-            std::stringstream ss;
-            ss << "armarx::RobotUnit::addSensorDevice: SensorDevice is nullptr";
-            ARMARX_ERROR << ss.str();
-            throw InvalidArgumentException {ss.str()};
-        }
-        if (!sd->getSensorValue())
-        {
-            std::stringstream ss;
-            ss << "armarx::RobotUnit::addSensorDevice: SensorDevice " << sd->getDeviceName()
-               << " has null SensorValue (this is not allowed)";
-            ARMARX_ERROR << ss.str();
-            throw InvalidArgumentException {ss.str()};
-        }
-        if (sd->getDeviceName() == rtThreadTimingsSensorDeviceName)
-        {
-            if (!std::dynamic_pointer_cast<RTThreadTimingsSensorDevice>(sd))
-            {
-                throw InvalidArgumentException
-                {
-                    "You tried to add a SensorDevice with the name " + sd->getDeviceName() +
-                    " which does not derive from RTThreadTimingsSensorDevice. (Don't do this)"
-                };
-            }
-            //this checks if we already added such a device (do this before setting timingSensorDevice)
-            sensorDevices.add(sd->getDeviceName(), sd);
-            rtThreadTimingsSensorDevice = std::dynamic_pointer_cast<RTThreadTimingsSensorDevice>(sd);
-        }
-        else
-        {
-            sensorDevices.add(sd->getDeviceName(), sd);
-        }
-        ARMARX_INFO << "added SensorDevice " << sd->getDeviceName() << " (valuetype = " << sd->getSensorValueType() << ")";
-    }
-
-    void armarx::RobotUnit::finishDeviceInitialization()
-    {
-        auto beg = MicroNow();
-        auto guard = getGuard();
-        throwIfStateIsNot(RobotUnitState::InitializingDevices, __FUNCTION__);
-        if (!sensorDevices.has(rtThreadTimingsSensorDeviceName))
-        {
-            addSensorDevice(createRTThreadTimingSensorDevice());
-        }
-        state = RobotUnitState::InitializingUnits;
-        //check added devices
-        ARMARX_DEBUG << "checking ControlDevices:";
-        for (const ControlDevicePtr& controlDevice : controlDevices.values())
-        {
-            ARMARX_CHECK_EXPRESSION(controlDevice);
-            ARMARX_DEBUG << "----" << controlDevice->getDeviceName();
-            if (!controlDevice->hasJointController(ControlModes::EmergencyStop))
-            {
-                std::stringstream s;
-                s << "ControlDevice " << controlDevice->getDeviceName()
-                  << " has no JointController with ControlMode " << ControlModes::EmergencyStop
-                  << " (to fix this, add a JointController with this ControlMode to the ControlDevice).\nAvailable controllers: "
-                  <<  controlDevice->getControlModes();
-                ARMARX_ERROR << "--------" << s.str();
-                throw LogicError {s.str()};
-
-            }
-            if (!controlDevice->hasJointController(ControlModes::StopMovement))
-            {
-                std::stringstream s;
-                s << "ControlDevice " << controlDevice->getDeviceName()
-                  << " has no JointController with ControlMode \"" << ControlModes::StopMovement
-                  << "\" (to fix this, add a JointController with this ControlMode to the ControlDevice) \nAvailable controllers: "
-                  << controlDevice->getControlModes();
-                ARMARX_ERROR << "--------" << s.str();
-                throw LogicError {s.str()};
-            }
-        }
-        ARMARX_DEBUG << "checking sensor devices:";
-        for (const SensorDevicePtr& sensorDevice : sensorDevices.values())
-        {
-            ARMARX_CHECK_EXPRESSION(sensorDevice);
-            ARMARX_DEBUG << "----" << sensorDevice->getDeviceName();
-            if (!sensorDevice->getSensorValue())
-            {
-                std::stringstream s;
-                s << "SensorDevice " << sensorDevice->getSensorValue() << " has null SensorValue";
-                ARMARX_ERROR << "--------" << s.str();
-                throw LogicError {s.str()};
-            }
-            ARMARX_CHECK_EXPRESSION(sensorDevice);
-        }
-
-        ARMARX_DEBUG << "initializing buffers:";
-        {
-            ARMARX_DEBUG << "----initializing controller buffers";
-            controllersActivated.reinitAllBuffers(JointAndNJointControllers {getNumberOfControlDevices()});
-            JointAndNJointControllers ctrlinitReq(getNumberOfControlDevices());
-            for (std::size_t i = 0 ; i < getNumberOfControlDevices(); ++i)
-            {
-                ctrlinitReq.jointControllers.at(i) = controlDevices.at(i)->rtGetJointStopMovementController();
-            }
-            controllersRequested.reinitAllBuffers(ctrlinitReq);
-            controllersRequested.commitWrite();//to make sure the diry bit is activated (to trigger rt switch)
-        }
-        ARMARX_DEBUG << "copying device ptrs to const ptr map";
-        {
-            for (const auto& dev : controlDevices.values())
-            {
-                controlDevicesConstPtr[dev->getDeviceName()] = dev;
-            }
-            for (const auto& dev : sensorDevices.values())
-            {
-                sensorDevicesConstPtr[dev->getDeviceName()] = dev;
-                const SensorValue1DoFActuatorPosition* sv = dev->getSensorValue()->asA<SensorValue1DoFActuatorPosition>();
-                if (sv && rtRobot->hasRobotNode(dev->getDeviceName()))
-                {
-                    nodePositionSensorMap[rtRobot->getRobotNode(dev->getDeviceName())] = sv;
-                }
-            }
-        }
-
-        ARMARX_VERBOSE << "ControlDevices:\n" << controlDevices.keys();
-        ARMARX_VERBOSE << "SensorDevices:\n" << sensorDevices.keys();
-        ctrlModeGroups.groupIndices.assign(getNumberOfControlDevices(), IndexSentinel());
-
-        if (!ctrlModeGroups.groupsMerged.empty())
-        {
-            ARMARX_DEBUG << "Remove control devs from ControlDeviceHardwareControlModeGroups ("
-                         << ctrlModeGroups.groups.size() << ")";
-            const auto groupsMerged = ctrlModeGroups.groupsMerged;
-            for (const auto& dev : groupsMerged)
-            {
-                if (controlDevices.has(dev))
-                {
-                    continue;
-                }
-                ctrlModeGroups.groupsMerged.erase(dev);
-                for (auto& group : ctrlModeGroups.groups)
-                {
-                    group.erase(dev);
-                }
-                ARMARX_DEBUG << "----removing nonexistent device: " << dev;
-            }
-            //remove empty groups
-            std::vector<std::set<std::string>> cleanedGroups;
-            cleanedGroups.reserve(ctrlModeGroups.groups.size());
-            for (auto& group : ctrlModeGroups.groups)
-            {
-                const auto sz = group.size();
-                if (sz == 1)
-                {
-                    ARMARX_DEBUG << "----removing group with one dev: " << *group.begin();
-                }
-                else if (sz > 1)
-                {
-                    cleanedGroups.emplace_back(std::move(group));
-                }
-            }
-            ctrlModeGroups.groups = cleanedGroups;
-            ARMARX_DEBUG << "----number of groups left: " << ctrlModeGroups.groups.size();
-        }
-        if (!ctrlModeGroups.groupsMerged.empty())
-        {
-            ARMARX_DEBUG << "Checking control modes for ControlDeviceHardwareControlModeGroups ("
-                         << ctrlModeGroups.groups.size() << ")";
-            ctrlModeGroups.deviceIndices.resize(ctrlModeGroups.groups.size());
-            //iterate over groups
-            for (std::size_t groupIdx = 0; groupIdx < ctrlModeGroups.groups.size(); ++groupIdx)
-            {
-                const std::set<std::string>& group = ctrlModeGroups.groups.at(groupIdx);
-                ctrlModeGroups.deviceIndices.at(groupIdx).reserve(group.size());
-                ARMARX_CHECK_EXPRESSION(!group.empty());
-                ARMARX_DEBUG << "----Group " << groupIdx << " size: " << group.size();
-                //gets a map of ControlMode->HardwareControlMode for the given device
-                const auto getControlModeToHWControlMode = [&](const std::string & devname)
-                {
-                    std::map<std::string, std::string> controlModeToHWControlMode;
-                    const ControlDevicePtr& cd = controlDevices.at(devname);
-                    for (const auto& jointCtrl : cd->getJointControllers())
-                    {
-                        controlModeToHWControlMode[jointCtrl->getControlMode()] = jointCtrl->getHardwareControlMode();
-                    }
-                    return controlModeToHWControlMode;
-                };
-                //get modes of first dev
-                const auto controlModeToHWControlMode = getControlModeToHWControlMode(*group.begin());
-                //check other devs
-                for (const auto& devname : group)
-                {
-                    ARMARX_CHECK_EXPRESSION_W_HINT(
-                        controlDevices.has(devname),
-                        "The ControlDeviceHardwareControlModeGroups property contains device names not existent in the robot: "
-                        << devname << "\navailable:\n" << controlDevices.keys()
-                    );
-                    //Assert all devices in a group have the same control modes with the same hw controle modes
-                    const auto controlModeToHWControlModeForDevice = getControlModeToHWControlMode(devname);
-                    ARMARX_CHECK_EXPRESSION_W_HINT(
-                        controlModeToHWControlModeForDevice == controlModeToHWControlMode,
-                        "Error for control modes of device '" << devname << "'\n"
-                        << "it has the modes: " << controlModeToHWControlModeForDevice
-                        << "\n but should have the modes: " << controlModeToHWControlMode
-                    );
-                    //insert the device index into the device indices
-                    const auto devIdx = controlDevices.index(devname);
-                    ctrlModeGroups.deviceIndices.at(groupIdx).emplace_back(devIdx);
-                    //insert the group index into the group indices (+ check the current group index is the sentinel
-                    ARMARX_CHECK_EXPRESSION(ctrlModeGroups.groupIndices.size() > devIdx);
-                    ARMARX_CHECK_EXPRESSION(ctrlModeGroups.groupIndices.at(devIdx) == IndexSentinel());
-                    ctrlModeGroups.groupIndices.at(devIdx) = groupIdx;
-                    ARMARX_DEBUG << "------- " << devname;
-                }
-            }
-        }
-        ARMARX_INFO << "finishDeviceInitialization...done! " << (MicroNow() - beg).count() << " us";
-    }
-
-    void armarx::RobotUnit::initializeDefaultUnits()
-    {
-        auto beg = MicroNow();
-        {
-            auto guard = getGuard();
-            throwIfStateIsNot(RobotUnitState::InitializingUnits, __FUNCTION__);
-            ARMARX_INFO << "initializing default units";
-            initializeKinematicUnit();
-            ARMARX_DEBUG << "KinematicUnit initialized";
-            initializePlatformUnit();
-            ARMARX_DEBUG << "PlatformUnit initialized";
-            initializeForceTorqueUnit();
-            ARMARX_DEBUG << "ForceTorqueUnit initialized";
-            initializeInertialMeasurementUnit();
-            ARMARX_DEBUG << "InertialMeasurementUnit initialized";
-            initializeTrajectoryControllerUnit();
-            ARMARX_DEBUG << "TrajectoryControllerUnit initialized";
-            initializeTcpControllerUnit();
-            ARMARX_DEBUG << "TcpControllerUnit initialized";
-        }
-        ARMARX_INFO << "initializing default units...done! " << (MicroNow() - beg).count() << " us";
-    }
-
-    void armarx::RobotUnit::initializeKinematicUnit()
-    {
-        using UnitT = KinematicSubUnit;
-        using IfaceT = KinematicUnitInterface;
-
-        auto guard = getGuard();
-        throwIfStateIsNot(RobotUnitState::InitializingUnits, __FUNCTION__);
-        //check if unit is already added
-        if (getUnit(IfaceT::ice_staticId()))
-        {
-            return;
-        }
-        //add ctrl et al
-        std::map<std::string, UnitT::ActuatorData> devs;
-        for (const ControlDevicePtr& controlDevice : controlDevices.values())
-        {
-            ARMARX_CHECK_EXPRESSION(controlDevice);
-            const auto& controlDeviceName = controlDevice->getDeviceName();
-            if (!controlDevice->hasTag(ControlDeviceTags::CreateNoDefaultController))
-            {
-                UnitT::ActuatorData ad;
-                ad.name = controlDeviceName;
-                ad.sensorDeviceIndex =
-                    sensorDevices.has(controlDeviceName) ?
-                    sensorDevices.index(controlDeviceName) :
-                    std::numeric_limits<std::size_t>::max();
-                /// TODO use better kinematic unit controllers (posThroughVel + ramps)
-#define initializeKinematicUnit_tmp_helper(mode, CtargT, ctrl)                                                          \
-    {                                                                                                                   \
-        const auto& controlMode = mode;                                                                                 \
-        NJointKinematicUnitPassThroughControllerPtr& pt = ctrl;                                                           \
-        JointController* jointCtrl = controlDevice->getJointController(controlMode);                                           \
-        if (jointCtrl && jointCtrl->getControlTarget()->isA<CtargT>())                                                            \
-        {                                                                                                               \
-            NJointKinematicUnitPassThroughControllerConfigPtr config = new NJointKinematicUnitPassThroughControllerConfig;  \
-            config->controlMode=controlMode;                                                                            \
-            config->deviceName=controlDeviceName;                                                                       \
-            const NJointControllerPtr& nJointCtrl = createNJointController(                                                       \
-                                                    "NJointKinematicUnitPassThroughController",                                   \
-                                                    "NJointKU_PTCtrl_"+controlDeviceName+"_"+controlMode,                         \
-                                                    config,                                                                     \
-                                                    false, true);                                                               \
-            pt = NJointKinematicUnitPassThroughControllerPtr::dynamicCast(nJointCtrl);                                          \
-            ARMARX_CHECK_EXPRESSION(pt);                                                                                \
-        }                                                                                                               \
-    }
-                initializeKinematicUnit_tmp_helper(ControlModes::Position1DoF, ControlTarget1DoFActuatorPosition, ad.ctrlPos)
-                initializeKinematicUnit_tmp_helper(ControlModes::Velocity1DoF, ControlTarget1DoFActuatorVelocity, ad.ctrlVel)
-                initializeKinematicUnit_tmp_helper(ControlModes::Torque1DoF, ControlTarget1DoFActuatorTorque, ad.ctrlTor)
-#undef initializeKinematicUnit_tmp_helper
-
-
-                if (ad.ctrlPos || ad.ctrlTor || ad.ctrlVel)
-                {
-                    devs[controlDeviceName] = std::move(ad);
-                }
-            }
-        }
-        if (devs.empty())
-        {
-            ARMARX_IMPORTANT << "No joint devices found - skipping adding of KinematicUnit";
-            return;
-        }
-        ARMARX_CHECK_EXPRESSION_W_HINT(!devs.empty(), "no 1DoF ControlDevice found with matching SensorDevice");
-        //add it
-        const std::string configName = getProperty<std::string>("KinematicUnitName");
-        const std::string confPre = getConfigDomain() + "." + configName + ".";
-        Ice::PropertiesPtr properties = getIceProperties()->clone();
-        //properties->setProperty(confPre + "MinimumLoggingLevel", getProperty<std::string>("MinimumLoggingLevel").getValue());
-        //fill properties
-        properties->setProperty(confPre + "RobotNodeSetName", robotNodeSetName);
-        properties->setProperty(confPre + "RobotFileName", robotFileName);
-        properties->setProperty(confPre + "RobotFileNameProject", robotProjectName);
-        ARMARX_DEBUG << "creating unit " << configName << " using these properties: " << properties->getPropertiesForPrefix("");
-        IceInternal::Handle<UnitT> unit = Component::create<UnitT>(properties, configName, getConfigDomain());
-
-        //fill devices (sensor + controller)
-        unit->setupData(
-            getProperty<std::string>("RobotFileName").getValue(),
-            robot->clone(),
-            std::move(devs),
-            ctrlModeGroups.groups,
-            ctrlModeGroups.groupsMerged,
-            this
-        );
-        //add
-        addUnit(std::move(unit));
-    }
-
-    void armarx::RobotUnit::initializePlatformUnit()
-    {
-        using UnitT = PlatformSubUnit;
-        using IfaceT = PlatformUnitInterface;
-
-        auto guard = getGuard();
-        throwIfStateIsNot(RobotUnitState::InitializingUnits, __FUNCTION__);
-        //check if unit is already added
-        if (getUnit(IfaceT::ice_staticId()))
-        {
-            return;
-        }
-        //is there a platform dev?
-        if (getRobotPlatformName().empty())
-        {
-            ARMARX_INFO << "no platform unit created since no platform name was given";
-            return;
-        }
-        if (!controlDevices.has(getRobotPlatformName()))
-        {
-            ARMARX_WARNING << "no platform unit created since the platform control device with name '"
-                           << getRobotPlatformName() << "' was not found";
-            return;
-        }
-        const ControlDevicePtr& controlDevice = controlDevices.at(robotPlatformName);
-        const SensorDevicePtr&  sensorDevice = sensorDevices.at(robotPlatformName);
-        JointController* jointVel = controlDevice->getJointController(ControlModes::HolonomicPlatformVelocity);
-        ARMARX_CHECK_EXPRESSION(jointVel);
-        ARMARX_CHECK_EXPRESSION(sensorDevice->getSensorValue()->asA<SensorValueHolonomicPlatform>());
-        //add it
-        const std::string configName = getProperty<std::string>("PlatformUnitName");
-        const std::string confPre = getConfigDomain() + "." + configName + ".";
-        Ice::PropertiesPtr properties = getIceProperties()->clone();
-        //properties->setProperty(confPre + "MinimumLoggingLevel", getProperty<std::string>("MinimumLoggingLevel").getValue());
-        //fill properties
-        properties->setProperty(confPre + "PlatformName", robotPlatformName);
-        ARMARX_DEBUG << "creating unit " << configName << " using these properties: " << properties->getPropertiesForPrefix("");
-        IceInternal::Handle<UnitT> unit = Component::create<UnitT>(properties, configName, getConfigDomain());
-        //config
-        NJointHolonomicPlatformUnitVelocityPassThroughControllerConfigPtr config = new NJointHolonomicPlatformUnitVelocityPassThroughControllerConfig;
-        config->initialVelocityX = 0;
-        config->initialVelocityY = 0;
-        config->initialVelocityRotation = 0;
-        config->platformName = robotPlatformName;
-        auto ctrl = NJointHolonomicPlatformUnitVelocityPassThroughControllerPtr::dynamicCast(
-                        createNJointController(
-                            "NJointHolonomicPlatformUnitVelocityPassThroughController", configName + "_VelPTContoller",
-                            config, false, true
-                        )
-                    );
-        ARMARX_CHECK_EXPRESSION(ctrl);
-        unit->pt = ctrl;
-        unit->platformSensorIndex = sensorDevices.index(robotPlatformName);
-        //add
-        addUnit(std::move(unit));
-    }
-
-    void armarx::RobotUnit::initializeForceTorqueUnit()
-    {
-        using UnitT = ForceTorqueSubUnit;
-        using IfaceT = ForceTorqueUnitInterface;
-
-        auto guard = getGuard();
-        throwIfStateIsNot(RobotUnitState::InitializingUnits, __FUNCTION__);
-        //check if unit is already added
-        if (getUnit(IfaceT::ice_staticId()))
-        {
-            return;
-        }
-        //check if it is required
-        std::vector<ForceTorqueSubUnit::DeviceData> ftdevs;
-        for (const SensorDevicePtr& ftSensorDevice : sensorDevices.values())
-        {
-            if (ftSensorDevice->getSensorValue()->isA<SensorValueForceTorque>())
-            {
-                ForceTorqueSubUnit::DeviceData ftSensorData;
-                ftSensorData.sensorIndex = sensorDevices.index(ftSensorDevice->getDeviceName());
-                ftSensorData.deviceName = ftSensorDevice->getDeviceName();
-                ftSensorData.frame = ftSensorDevice->getReportingFrame();
-                ARMARX_CHECK_EXPRESSION_W_HINT(
-                    !ftSensorData.frame.empty(),
-                    "The sensor device '" << ftSensorData.deviceName << "' (index: " << ftSensorData.sensorIndex
-                    << ") reports force torque values but returns an empty string as reporting frame"
-                );
-                ARMARX_CHECK_EXPRESSION_W_HINT(
-                    getRobot()->hasRobotNode(ftSensorData.frame),
-                    "The sensor device '" << ftSensorData.deviceName << "' (index: " << ftSensorData.sensorIndex
-                    << ") reports force torque values but returns a reporting frame '" << ftSensorData.frame
-                    << "' which is not present in the robot '" << getRobot()->getName() << "'"
-                );
-                ftdevs.emplace_back(std::move(ftSensorData));
-            }
-        }
-        if (ftdevs.empty())
-        {
-            ARMARX_IMPORTANT << "no force torque unit created since there are no force torque sensor devices";
-            return;
-        }
-        //add it
-        const std::string configName = getProperty<std::string>("ForceTorqueUnitName");
-        const std::string confPre = getConfigDomain() + "." + configName + ".";
-        Ice::PropertiesPtr properties = getIceProperties()->clone();
-        //properties->setProperty(confPre + "MinimumLoggingLevel", getProperty<std::string>("MinimumLoggingLevel").getValue());
-        //fill properties
-        properties->setProperty(confPre + "AgentName", robot->getName());
-        properties->setProperty(confPre + "ForceTorqueTopicName", getProperty<std::string>("ForceTorqueTopicName").getValue());
-        ARMARX_DEBUG << "creating unit " << configName << " using these properties: " << properties->getPropertiesForPrefix("");
-        IceInternal::Handle<UnitT> unit = Component::create<UnitT>(properties, configName, getConfigDomain());
-        unit->devs = ftdevs;
-        //add
-        addUnit(std::move(unit));
-    }
-
-    void RobotUnit::initializeTrajectoryControllerUnit()
-    {
-        auto guard = getGuard();
-        throwIfStateIsNot(RobotUnitState::InitializingUnits, __FUNCTION__);
-        using UnitT = TrajectoryControllerSubUnit;
-        if (!getProperty<bool>("CreateTrajectoryPlayer").getValue())
-        {
-            return;
-        }
-
-        //check if unit is already added
-        if (getUnit(UnitT::ice_staticId()) || !trajectoryControllerSubUnit)
-        {
-            return;
-        }
-        (TrajectoryControllerSubUnitPtr::dynamicCast(trajectoryControllerSubUnit))->setup(this);
-        addUnit(trajectoryControllerSubUnit);
-    }
-
-    void RobotUnit::initializeTcpControllerUnit()
-    {
-        auto guard = getGuard();
-        throwIfStateIsNot(RobotUnitState::InitializingUnits, __FUNCTION__);
-
-        if (!getProperty<bool>("CreateTrajectoryPlayer").getValue())
-        {
-            return;
-        }
-        using UnitT = TCPControllerSubUnit;
-
-        //check if unit is already added
-        if (getUnit(UnitT::ice_staticId()))
-        {
-            return;
-        }
-        (TCPControllerSubUnitPtr::dynamicCast(tcpControllerSubUnit))->setup(this, robot->clone());
-        addUnit(tcpControllerSubUnit);
-    }
-    void armarx::RobotUnit::initializeInertialMeasurementUnit()
-    {
-        using UnitT = InertialMeasurementSubUnit;
-        using IfaceT = InertialMeasurementUnitInterface;
-
-        auto guard = getGuard();
-        throwIfStateIsNot(RobotUnitState::InitializingUnits, __FUNCTION__);
-        //check if unit is already added
-        if (getUnit(IfaceT::ice_staticId()))
-        {
-            return;
-        }
-        //check if it is required
-        std::map<std::string, std::size_t> imudevs;
-        for (auto i : getIndices(sensorDevices.keys()))
-        {
-            const SensorDevicePtr& sensorDevice = sensorDevices.at(i);
-            if (sensorDevice->getSensorValue()->isA<SensorValueIMU>())
-            {
-                imudevs[sensorDevice->getDeviceName()] = i;
-            }
-        }
-        if (imudevs.empty())
-        {
-            ARMARX_IMPORTANT << "no inertial measurement unit created since there are no imu sensor devices";
-            return;
-        }
-        //add it
-        const std::string configName = getProperty<std::string>("InertialMeasurementUnitName");
-        const std::string confPre = getConfigDomain() + "." + configName + ".";
-        Ice::PropertiesPtr properties = getIceProperties()->clone();
-        //properties->setProperty(confPre + "MinimumLoggingLevel", getProperty<std::string>("MinimumLoggingLevel").getValue());
-        //fill properties
-        properties->setProperty(confPre + "IMUTopicName", getProperty<std::string>("IMUTopicName").getValue());
-        IceInternal::Handle<UnitT> unit = Component::create<UnitT>(properties, configName, getConfigDomain());
-        unit->devs = imudevs;
-        //add
-        addUnit(std::move(unit));
-    }
-
-    void armarx::RobotUnit::addUnit(ManagedIceObjectPtr unit)
-    {
-        auto guard = getGuard();
-        throwIfStateIsNot(RobotUnitState::InitializingUnits, __FUNCTION__);
-        getArmarXManager()->addObjectAsync(unit, "", true, false);
-        //maybe add it to the sub units
-        RobotUnitSubUnitPtr rsu = RobotUnitSubUnitPtr::dynamicCast(unit);
-        if (rsu)
-        {
-            subUnits.emplace_back(std::move(rsu));
-        }
-        units.emplace_back(std::move(unit));
-    }
-
-    void armarx::RobotUnit::finishUnitInitialization()
-    {
-
-        auto beg = MicroNow();
-        auto guard = getGuard();
-        throwIfStateIsNot(RobotUnitState::InitializingUnits, __FUNCTION__);
-        state = RobotUnitState::WaitingForRTThreadInitialization;
-        //start publisher
-        std::size_t pubtimestep = getProperty<std::size_t>("PublishPeriodMs");
-        if (!pubtimestep)
-        {
-            pubtimestep = 1;
-        }
-        publishNewSensorDataTime = TimeUtil::GetTime();
-        publisherTask = new PublisherTaskT([&] {publish({});}, pubtimestep, false, getName() + "_PublisherTask");
-        ARMARX_INFO << "starting publisher with timestep " << pubtimestep;
-        publisherTask->setDelayWarningTolerance(100);
-        publisherTask->start();
-
-        std::size_t rtLoggingTimestep = getProperty<std::size_t>("RTLoggingPeriodMs");
-        rtLogging.enabled = rtLoggingTimestep;
-        rtLogging.loggingTaskTimestep = rtLoggingTimestep;
-        ARMARX_CHECK_GREATER(getControlThreadTargetPeriod().toMicroSeconds(), 0);
-        if (isRtLoggingEnabled())
-        {
-            //init buffer
-            {
-                std::size_t messageBufferSize = getProperty<std::size_t>("RTLoggingMessageBufferSize");
-                std::size_t messageBufferNumberEntries = getProperty<std::size_t>("RTLoggingMessageNumber");
-                std::size_t messageBufferMaxSize = getProperty<std::size_t>("RTLoggingMaxMessageBufferSize");
-                std::size_t messageBufferMaxNumberEntries = getProperty<std::size_t>("RTLoggingMaxMessageNumber");
-
-                rtLogging.keepBacklogFor = IceUtil::Time::milliSeconds(getProperty<std::size_t>("RTLoggingKeepIterationsForMs"));
-
-                ARMARX_CHECK_LESS_EQUAL(messageBufferSize, messageBufferMaxSize);
-                ARMARX_CHECK_LESS_EQUAL(messageBufferNumberEntries, messageBufferMaxNumberEntries);
-
-                std::size_t cThreadPeriodUs = static_cast<std::size_t>(getControlThreadTargetPeriod().toMicroSeconds());
-                std::size_t lThreadPeriodUs = rtLoggingTimestep * 1000;
-
-                std::size_t nBuffers = (lThreadPeriodUs / cThreadPeriodUs + 1) * 100;
-                const auto bufferSize = controlThreadOutputBuffer.initialize(
-                                            nBuffers, controlDevices, sensorDevices,
-                                            messageBufferSize, messageBufferNumberEntries,
-                                            messageBufferMaxSize, messageBufferMaxNumberEntries);
-                ARMARX_INFO << "RTLogging activated! using "
-                            << nBuffers << "buffers "
-                            << "(buffersize = " << bufferSize << " bytes)";
-            }
-            //init logging names
-            {
-                //sensorDevices
-                rtLogging.controlDeviceValueLoggingNames.reserve(controlDevices.size());
-                for (const auto& cd : controlDevices.values())
-                {
-                    rtLogging.controlDeviceValueLoggingNames.emplace_back();
-                    auto& namesForDev = rtLogging.controlDeviceValueLoggingNames.back();
-                    namesForDev.reserve(cd->getJointControllers().size());
-                    for (auto jointC : cd->getJointControllers())
-                    {
-                        const auto names = jointC->getControlTarget()->getDataFieldNames();
-                        namesForDev.emplace_back();
-                        auto& fullNames = namesForDev.back();
-                        fullNames.reserve(names.size());
-                        for (const auto& name :  names)
-                        {
-                            fullNames.emplace_back(
-                                "ctrl." +
-                                cd->getDeviceName() + "." +
-                                jointC->getControlMode() + "." +
-                                name);
-                        }
-                    }
-                }
-                //sensorDevices
-                rtLogging.sensorDeviceValueLoggingNames.reserve(sensorDevices.size());
-                for (const auto& sd : sensorDevices.values())
-                {
-                    const auto names = sd->getSensorValue()->getDataFieldNames();
-                    rtLogging.sensorDeviceValueLoggingNames.emplace_back();
-                    auto& fullNames = rtLogging.sensorDeviceValueLoggingNames.back();
-                    fullNames.reserve(names.size());
-                    for (const auto& name :  names)
-                    {
-                        fullNames.emplace_back(
-                            "sens." +
-                            sd->getDeviceName() + "." +
-                            name);
-                    }
-                }
-            }
-            //start logging thread is done in rtinit
-            //maybe add the default log
-            {
-                const auto loggingpath = getProperty<std::string>("RTLoggingDefaultLog").getValue();
-                if (!loggingpath.empty())
-                {
-                    rtLogging.defaultLogHandle = startRtLogging(loggingpath, getLoggingNames());
-                }
-            }
-        }
-        else
-        {
-            //no rt logging
-            ARMARX_INFO << "RTLogging deactivated!";
-            controlThreadOutputBuffer.initialize(0, controlDevices, sensorDevices, 0, 0, 0, 0);
-        }
-
-        startSelfCollisionAvoidance();
-        if (isRtLoggingEnabled())
-        {
-            rtLogging.task = new RTLoggingTaskT([&] {rtLogging.doLogging();}, rtLogging.loggingTaskTimestep, false, getName() + "_RTLoggingTask");
-            ARMARX_INFO << "starting rt logging with timestep " << rtLogging.loggingTaskTimestep;
-            rtLogging.task->setDelayWarningTolerance(rtLogging.loggingTaskTimestep * 10);
-            rtLogging.task->start();
-        }
-
-        ARMARX_INFO << "finishUnitInitialization...done! " << (MicroNow() - beg).count() << " us";
-    }
-
-    void armarx::RobotUnit::initRTThread()
-    {
-        auto guard = getGuard();
-        throwIfStateIsNot(RobotUnitState::WaitingForRTThreadInitialization, __FUNCTION__);
-        rtThreadId = std::this_thread::get_id();
-        rtLogging.rtThreadId = LogSender::getThreadId();
-        state = RobotUnitState::Running;
-        ControlThreadOutputBuffer::RtLoggingInstance = &controlThreadOutputBuffer;
-    }
-
-    bool armarx::RobotUnit::rtSwitchControllerSetup()
-    {
-        rtThreadTimingsSensorDevice->rtMarkRtSwitchControllerSetupStart();
-        ARMARX_ON_SCOPE_EXIT { rtThreadTimingsSensorDevice->rtMarkRtSwitchControllerSetupEnd(); };
-        // !emergencyStop && !rtIsInEmergencyStop -> normal control flow
-        // !emergencyStop &&  rtIsInEmergencyStop -> force switch to reactivate old ( + reset flag)
-        //  emergencyStop && !rtIsInEmergencyStop -> deactivate all + set flag
-        //  emergencyStop &&  rtIsInEmergencyStop -> nothing to do
-
-        if (emergencyStop)
-        {
-            if (rtIsInEmergencyStop)
-            {
-                return false;
-            }
-            rtIsInEmergencyStop = true;
-            bool updatedActive = false;
-            //deactivate all nJointCtrl
-            for (auto& nJointCtrl : rtGetActivatedNJointControllers())
-            {
-                if (nJointCtrl)
-                {
-                    RtSetNJointControllerDeactivatedStatus(nJointCtrl);
-                    nJointCtrl = nullptr;
-                    updatedActive = true;
-                }
-            }
-            //set all JointCtrl to emergency stop (except stop movement)
-            for (std::size_t i = 0; i < rtGetNumberOfControlDevices(); ++i)
-            {
-                ControlDevicePtr& controlDevice = controlDevices.at(i);
-                const auto active = controlDevice->rtGetActiveJointController();
-                const auto stopMov = controlDevice->rtGetJointStopMovementController();
-                const auto emergency = controlDevice->rtGetJointEmergencyStopController();
-                if (active != stopMov && active != emergency)
-                {
-                    controlDevice->rtSetActiveJointController(emergency);
-                    rtGetActivatedJointControllers().at(i) = emergency;
-                    updatedActive = true;
-                }
-            }
-            if (updatedActive)
-            {
-                rtGetActivatedControllers().resetAssignement();
-                rtWriteActivatedControllers();
-            }
-            return updatedActive;
-        }
-
-        if (!rtRequestedControllersChanged() && !rtIsInEmergencyStop)
-        {
-            return false;
-        }
-        rtIsInEmergencyStop = false;
-
-        //handle nJointCtrl
-        {
-            //"merge"
-            std::size_t n = rtGetNumberOfControlDevices();
-            std::size_t idxAct = 0;
-            std::size_t idxReq = 0;
-            for (std::size_t i = 0; i < 2 * n; ++i)
-            {
-                //skip nullptrs in act
-                while (idxAct < n && !rtGetActivatedNJointControllers().at(idxAct))
-                {
-                    ++idxAct;
-                }
-                const NJointControllerPtr& req = idxReq < n ? rtGetRequestedNJointControllers().at(idxReq) : nullptr; //may be null
-                const NJointControllerPtr& act = idxAct < n ? rtGetActivatedNJointControllers().at(idxAct) : nullptr; //may be null if it is the last
-                std::size_t reqId = req ? req->rtGetId() : std::numeric_limits<std::size_t>::max();
-                std::size_t actId = act ? act->rtGetId() : std::numeric_limits<std::size_t>::max();
-
-                if (reqId < actId)
-                {
-                    //new ctrl
-                    RtSetNJointControllerActivatedStatus(req);
-                    ++idxReq;
-                }
-                else if (reqId > actId)
-                {
-                    RtSetNJointControllerDeactivatedStatus(act);
-                    ++idxAct;
-                }
-                else //if(reqId == actId)
-                {
-                    //same ctrl or both null ctrl
-                    ++idxReq;
-                    ++idxAct;
-                }
-                if (idxAct >= n && !req)
-                {
-                    break;
-                }
-            }
-            rtGetActivatedNJointControllers() = rtGetRequestedNJointControllers();
-        }
-
-        //handle Joint Ctrl
-        {
-            for (std::size_t i = 0; i < rtGetNumberOfControlDevices(); ++i)
-            {
-                auto& controlDevice = controlDevices.at(i);
-                const auto requestedJointCtrl = rtGetRequestedJointControllers().at(i);
-                controlDevice->rtSetActiveJointController(requestedJointCtrl);
-                rtGetActivatedJointControllers().at(i) = requestedJointCtrl;
-            }
-        }
-        rtGetActivatedJointToNJointControllerAssignement() = rtGetRequestedControllers().jointToNJointControllerAssignement;
-        rtWriteActivatedControllers();
-        return true;
-    }
-
-    void armarx::RobotUnit::rtDeactivateAssignedNJointControllerBecauseOfError(std::size_t ctrlDevIndex, bool writeActivatedControlers)
-    {
-        std::size_t nJointCtrlIndex = rtGetActivatedJointToNJointControllerAssignement().at(ctrlDevIndex);
-        ARMARX_CHECK_EXPRESSION_W_HINT(
-            nJointCtrlIndex < rtGetNumberOfControlDevices(),
-            nJointCtrlIndex << " < " << rtGetNumberOfControlDevices() <<
-            ": no NJoint controller controls this device (name = "
-            << controlDevices.at(ctrlDevIndex)->getDeviceName()
-            << ", ControlMode = " << rtGetActivatedJointControllers().at(ctrlDevIndex)->getControlMode() << ")!" << "\n"
-            << VAROUT(rtGetActivatedJointControllers()) << "\n"
-            << VAROUT(rtGetActivatedNJointControllers())
-        );
-
-        rtDeactivateNJointControllerBecauseOfError(nJointCtrlIndex, false);
-
-        if (writeActivatedControlers)
-        {
-            rtWriteActivatedControllers();
-        }
-    }
-
-    void armarx::RobotUnit::rtDeactivateNJointControllerBecauseOfError(std::size_t nJointCtrlIndex, bool writeActivatedControlers)
-    {
-        const NJointControllerPtr& nJointCtrl = rtGetActivatedNJointControllers().at(nJointCtrlIndex);
-        RtSetNJointControllerDeactivatedBecauseOfErrorStatus(nJointCtrl);
-        for (auto ctrlDevIdx : nJointCtrl->rtGetControlDeviceUsedIndices())
-        {
-            const ControlDevicePtr& controlDevice = controlDevices.at(ctrlDevIdx);
-            JointController* es = controlDevice->rtGetJointEmergencyStopController();
-            controlDevice->rtSetActiveJointController(es);
-            rtGetActivatedJointControllers().at(ctrlDevIdx) = es;
-            ARMARX_CHECK_EXPRESSION(rtGetActivatedJointToNJointControllerAssignement().at(ctrlDevIdx) == nJointCtrlIndex);
-            rtGetActivatedJointToNJointControllerAssignement().at(ctrlDevIdx) = IndexSentinel();
-        }
-        rtGetActivatedNJointControllers().at(nJointCtrlIndex) = nullptr;
-        //check ControlDeviceHardwareControlModeGroups
-        {
-            for (auto ctrlDevIdx : nJointCtrl->rtGetControlDeviceUsedIndices())
-            {
-                const auto groupIdx = ctrlModeGroups.groupIndices.at(ctrlDevIdx);
-                if (groupIdx == IndexSentinel())
-                {
-                    continue;
-                }
-                ControlDevice*  const dev  = controlDevices.at(ctrlDevIdx).get();
-                JointController* const jointCtrl = dev->rtGetActiveJointController();
-                const auto hwModeHash = jointCtrl->rtGetHardwareControlModeHash();
-                //this device is in a group!
-                // -> check all other devices
-                for (const auto otherIdx : ctrlModeGroups.deviceIndices.at(groupIdx))
-                {
-                    ControlDevice*  const otherDev  = controlDevices.at(otherIdx).get();
-                    JointController* const otherJointCtrl = otherDev->rtGetActiveJointController();
-                    const auto otherHwModeHash = otherJointCtrl->rtGetHardwareControlModeHash();
-                    if (hwModeHash == otherHwModeHash)
-                    {
-                        //the assigend ctrl has the same hwMode -> don't do anything
-                        continue;
-                    }
-                    const auto otherNJointCtrl1Idx = rtGetActivatedJointToNJointControllerAssignement().at(otherIdx);
-                    if (otherNJointCtrl1Idx == IndexSentinel())
-                    {
-                        //the hwmodes are different! (hence the other ctrl must be in stop movement
-                        ARMARX_CHECK_EXPRESSION(otherJointCtrl == otherDev->rtGetJointStopMovementController());
-                        //we need to activate the es contoller
-                        JointController* const es = otherDev->rtGetJointEmergencyStopController();
-                        otherDev->rtSetActiveJointController(es);
-                        ARMARX_CHECK_EXPRESSION(es->rtGetHardwareControlModeHash() == hwModeHash);
-                        rtGetActivatedJointControllers().at(otherIdx) = es;
-                        continue;
-                    }
-                    //the devs NJoint controller needs to be deactivated
-                    rtDeactivateAssignedNJointControllerBecauseOfError(otherIdx, false);
-                }
-            }
-        }
-        rtDeactivatedNJointControllerBecauseOfError(nJointCtrl);
-
-        if (writeActivatedControlers)
-        {
-            rtWriteActivatedControllers();
-        }
-    }
-
-    void armarx::RobotUnit::rtRunNJointControllers(const IceUtil::Time& sensorValuesTimestamp, const IceUtil::Time& timeSinceLastIteration)
-    {
-        rtThreadTimingsSensorDevice->rtMarkRtRunNJointControllersStart();
-        for (std::size_t nJointCtrlIndex = 0; nJointCtrlIndex < rtGetActivatedNJointControllers().size(); ++nJointCtrlIndex)
-        {
-            NJointController* nJointCtrl = rtGetActivatedNJointControllers().at(nJointCtrlIndex);
-            try
-            {
-                if (nJointCtrl)
-                {
-                    auto start = MicroNow();
-                    nJointCtrl->rtSwapBufferAndRun(sensorValuesTimestamp, timeSinceLastIteration);
-                    auto duration = MicroNow() - start;
-                    if (duration.count() > 500)
-                    {
-                        ARMARX_ERROR << deactivateSpam(5) << "The NJointController " << nJointCtrl->getClassName() << " took " << duration.count() << " µs to run!";
-                    }
-                    else if (duration.count() > 50)
-                    {
-                        ARMARX_RT_LOGF_WARN("An NJointController took %d µs to run!", duration.count()).deactivateSpam(5);
-                    }
-                }
-            }
-            catch (...)
-            {
-                ARMARX_ERROR << "NJoint Controller " << nJointCtrl->getInstanceName()
-                             << " threw an exception and is now deactivated: "
-                             << GetHandledExceptionString();
-                rtDeactivateNJointControllerBecauseOfError(nJointCtrlIndex, false);
-            }
-        }
-        rtWriteActivatedControllers();
-        rtThreadTimingsSensorDevice->rtMarkRtRunNJointControllersEnd();
-    }
-
-    void armarx::RobotUnit::rtRunJointControllers(const IceUtil::Time& sensorValuesTimestamp, const IceUtil::Time& timeSinceLastIteration)
-    {
-        rtThreadTimingsSensorDevice->rtMarkRtRunJointControllersStart();
-        for (const ControlDevicePtr& device : this->controlDevices.values())
-        {
-            device->rtRun(sensorValuesTimestamp, timeSinceLastIteration);
-        }
-        rtThreadTimingsSensorDevice->rtMarkRtRunJointControllersEnd();
-    }
-
-    void armarx::RobotUnit::rtReadSensorDeviceValues(const IceUtil::Time& sensorValuesTimestamp, const IceUtil::Time& timeSinceLastIteration)
-    {
-        rtThreadTimingsSensorDevice->rtMarkRtReadSensorDeviceValuesStart();
-        for (const SensorDevicePtr& device : this->sensorDevices.values())
-        {
-            device->rtReadSensorValues(sensorValuesTimestamp, timeSinceLastIteration);
-        }
-        rtThreadTimingsSensorDevice->rtMarkRtReadSensorDeviceValuesEnd();
-    }
-
-    void armarx::RobotUnit::rtHandleInvalidTargets()
-    {
-        rtThreadTimingsSensorDevice->rtMarkRtHandleInvalidTargetsStart();
-        bool oneIsInvalid = 0;
-        for (std::size_t i = 0; i < rtGetNumberOfControlDevices(); ++i)
-        {
-            if (!rtGetActivatedJointControllers().at(i)->rtIsTargetVaild())
-            {
-                rtDeactivateAssignedNJointControllerBecauseOfError(i, false);
-                oneIsInvalid = true;
-            }
-        }
-        if (oneIsInvalid)
-        {
-            rtWriteActivatedControllers();
-        }
-        rtThreadTimingsSensorDevice->rtMarkRtHandleInvalidTargetsEnd();
-    }
-
-    void armarx::RobotUnit::rtResetAllTargets()
-    {
-        rtThreadTimingsSensorDevice->rtMarkRtResetAllTargetsStart();
-        for (const ControlDevicePtr& controlDev : controlDevices.values())
-        {
-            controlDev->rtGetActiveJointController()->rtResetTarget();
-        }
-        rtThreadTimingsSensorDevice->rtMarkRtResetAllTargetsEnd();
-    }
-
-    ConstSensorDevicePtr armarx::RobotUnit::getSensorDevice(const std::string& sensorDeviceName) const
-    {
-        auto guard = getGuard();
-        throwIfDevicesNotReady(__FUNCTION__);
-        return sensorDevices.at(sensorDeviceName, SensorDevice::NullPtr);
-    }
-
-    ConstControlDevicePtr armarx::RobotUnit::getControlDevice(const std::string& deviceName) const
-    {
-        auto guard = getGuard();
-        throwIfDevicesNotReady(__FUNCTION__);
-        return controlDevices.at(deviceName, ControlDevice::NullPtr);
-    }
-
-    ControlTargetBase* armarx::RobotUnit::getControlTarget(const std::string& deviceName, const std::string& controlMode)
-    {
-        static const std::string fname = __FUNCTION__;
-        auto guard = getGuard();
-        throwIfDevicesNotReady(__FUNCTION__);
-        if (std::this_thread::get_id() != initNJointThreadId)
-        {
-            throw std::logic_error
-            {
-                fname + ": Must be only called during instantiation of a NJoint controller from the instantiated controler " +
-                "(Don't try to call this function outside of a NJointController's  constructor)"
-            };
-        }
-        if (initNJointControllerUsedJointController.find(deviceName) != initNJointControllerUsedJointController.end())
-        {
-            throw std::logic_error
-            {
-                fname + ": Must not request two ControlTargets for the same device. (got = " +
-                initNJointControllerUsedJointController.at(deviceName)->getControlMode() + ", requested " + controlMode + ") " +
-                "(You can only have a ControlDevice in one ControlMode. " +
-                "To check all available ControlModes for this device, get the ControlDevice via getControlDevice(" + deviceName + ") and querry it)"
-            };
-        }
-        // we should allow these modes for debugging reasons + there is no real reason to forbid them
-        //if (controlMode == ControlModes::EmergencyStop)
-        //{
-        //    throw std::invalid_argument {"armarx::RobotUnit::getControlTarget: Can't get target for the control mode " + ControlModes::EmergencyStop};
-        //}
-        //if (controlMode == ControlModes::StopMovement)
-        //{
-        //    throw std::invalid_argument {"armarx::RobotUnit::getControlTarget: Can't get target for the control mode " + ControlModes::StopMovement};
-        //}
-        ControlDevicePtr controlDevice = controlDevices.at(deviceName, ControlDevice::NullPtr);
-        if (!controlDevice)
-        {
-            return nullptr;
-        }
-        if (!controlDevice->hasJointController(controlMode))
-        {
-            return nullptr;
-        }
-        //there is a device and a target as was requested:
-        JointController* jointCtrl = controlDevice->getJointController(controlMode);
-        initNJointControllerUsedJointController[deviceName] = jointCtrl;
-        return jointCtrl->getControlTarget();
-    }
-
-    NJointControllerInterfacePrx armarx::RobotUnit::createNJointControllerFromVariantConfig(
-        const std::string& className, const std::string& instanceName, const StringVariantBaseMap& variants, const Ice::Current&)
-    {
-        //no lock required
-        checkNJointControllerClassName(className);
-        if (!NJointControllerRegistry::get(className)->hasRemoteConfiguration())
-        {
-            std::stringstream ss;
-            ss << "Requested controller class '" << className << "' allows no remote configuration" << NJointControllerRegistry::getKeys()
-               << " (Implement 'static WidgetDescription::WidgetPtr " << className << "::GenerateConfigDescription()'"
-               << " and 'static NJointControllerConfigPtr " << className
-               << "::GenerateConfigFromVariants(const StringVariantBaseMap&)' to allow remote configuration";
-            ARMARX_ERROR << ss.str();
-            throw InvalidArgumentException {ss.str()};
-        }
-        return createNJointController(
-                   className, instanceName,
-                   NJointControllerRegistry::get(className)->GenerateConfigFromVariants(variants),
-                   GlobalIceCurrent/*to select ice overload*/);
-    }
-
-    const NJointControllerPtr& armarx::RobotUnit::createNJointController(
-        const std::string& className,
-        const std::string& instanceName,
-        const NJointControllerConfigPtr& config,
-        bool deletable,
-        bool internal)
-    {
-        auto guard = getGuard();
-        throwIfDevicesNotReady(__FUNCTION__);
-        if (instanceName.empty())
-        {
-            ARMARX_ERROR << "The instance name is empty! (give a unique name)";
-            throw InvalidArgumentException {"The instance name is empty! (give a unique name)"};
-        }
-        //check if we would be able to create the class
-        checkNJointControllerClassName(className);
-        auto& factory = NJointControllerRegistry::get(className);
-
-        //check if the instance name is already in use
-        if (nJointControllers.count(instanceName))
-        {
-            std::stringstream ss;
-            ss << "There already is a controller instance with the name '" << instanceName << "'. Use a different instance name instead."
-               << " Other used instance names are " << getNJointControllerNames();
-            ARMARX_ERROR << ss.str();
-            throw InvalidArgumentException {ss.str()};
-        }
-
-        //create the controller
-        ARMARX_CHECK_EXPRESSION(initNJointControllerUsedJointController.empty());//in case someone broke things
-        initNJointThreadId = std::this_thread::get_id();
-        ARMARX_ON_SCOPE_EXIT
-        {
-            initNJointControllerUsedJointController.clear();
-            initNJointThreadId = std::thread::id{};
-        };
-        ARMARX_CHECK_EXPRESSION(factory);
-        NJointControllerPtr nJointCtrl {factory->create(NJointControllerDescriptionProviderInterfacePtr::dynamicCast(RobotUnitPtr {this}), config, robot)};
-
-        std::vector<char> ctrlDeviceUsedBitmap(getNumberOfControlDevices(), false);
-        std::vector<std::size_t> ctrlDeviceUsedIndices;
-        ctrlDeviceUsedIndices.reserve(getNumberOfControlDevices());
-        for (const auto& cd2targ : initNJointControllerUsedJointController)
-        {
-            auto idx = controlDevices.index(cd2targ.first);
-            ctrlDeviceUsedBitmap.at(idx) = true;
-            ctrlDeviceUsedIndices.emplace_back(idx);
-        }
-        InitNJointControler(
-            nJointCtrl,
-            this,
-            nJointControllerNextId++,
-            initNJointControllerUsedJointController,
-            std::move(ctrlDeviceUsedBitmap),
-            std::move(ctrlDeviceUsedIndices),
-            deletable, internal);
-        getArmarXManager()->addObjectAsync(nJointCtrl, instanceName, false, false);
-        nJointControllers[instanceName] = std::move(nJointCtrl);
-        ARMARX_CHECK_EXPRESSION(listenerPrx);
-        listenerPrx->nJointControllerCreated(instanceName);
-        return nJointControllers.at(instanceName);
-    }
-
-    void armarx::RobotUnit::setActivateControllersRequest(std::set<NJointControllerPtr, NJointController::IdComp>&& ctrls)
-    {
-        auto guard = getGuard();
-        throwIfDevicesNotReady(__FUNCTION__);
-        //erase nullptr
-        ctrls.erase(nullptr);
-        ARMARX_CHECK_EXPRESSION(ctrls.size() <= getNumberOfControlDevices());
-        const std::set<NJointControllerPtr, NJointController::IdComp> setOfRequestedCtrls
-        {
-            getRequestedNJointControllers().begin(),
-            getRequestedNJointControllers().end()
-        };
-        if (setOfRequestedCtrls == ctrls)
-        {
-            //redirty the flag to swap in the same set again
-            controllersRequested.commitWrite();
-            return;
-        }
-        JointAndNJointControllers request {getNumberOfControlDevices()};
-        std::size_t idx = 0;
-        for (const NJointControllerPtr& nJointCtrl : ctrls)
-        {
-            request.nJointControllers.at(idx++) = nJointCtrl.get();
-            //add Joint for this ctrl
-            for (const auto& cd2cm : nJointCtrl->getControlDeviceUsedControlModeMap())
-            {
-                std::size_t jointCtrlIndex = controlDevices.index(cd2cm.first);
-                if (request.jointControllers.at(jointCtrlIndex))
-                {
-                    std::stringstream ss;
-                    ss << "RobotUnit:setActivateControllersRequest controllers to activate are in conflict!\ncontrollers:";
-                    for (const auto& ctrl : ctrls)
-                    {
-                        ss << "\n" << ctrl->getInstanceName();
-                    }
-                    ARMARX_ERROR << ss.str();
-                    throw InvalidArgumentException {ss.str()};
-                }
-                request.jointControllers.at(jointCtrlIndex) = controlDevices.at(jointCtrlIndex)->getJointController(cd2cm.second);
-            }
-        }
-        for (auto i : getIndices(request.jointControllers))
-        {
-            JointController*& jointCtrl = request.jointControllers.at(i);
-            if (!jointCtrl)
-            {
-                JointController* jointCtrlOld = getRequestedJointControllers().at(i);
-                if (jointCtrlOld == controlDevices.at(i)->getJointStopMovementController())
-                {
-                    //don't replace this controller with emergency stop
-                    jointCtrl = jointCtrlOld;
-                }
-                else
-                {
-                    //no one controls this device -> emergency stop
-                    jointCtrl = controlDevices.at(i)->getJointEmergencyStopController();
-                }
-            }
-        }
-        writeRequestedControllers(std::move(request));
-        ARMARX_INFO << "requested controllers:\n" << getRequestedNJointControllerNames();
-    }
-
-    void armarx::RobotUnit::deleteNJointControllers(const Ice::StringSeq& names, const Ice::Current&)
-    {
-        ARMARX_VERBOSE << "requesting controller deletion for:\n" << names;
-        if (names.empty())
-        {
-            return;
-        }
-        auto guard = getGuard();
-        throwIfDevicesNotReady(__FUNCTION__);
-        auto ctrlsToActVec = getNJointControllersNotNull(names); //also checks if these controllers exist
-        ARMARX_DEBUG << "all controllers requested to delete exist" << std::flush;
-        //check if all can be deleted
-        for (const auto& nJointCtrl : ctrlsToActVec)
-        {
-            if (!nJointCtrl->isDeletable())
-            {
-                throw LogicError
-                {
-                    "The NJointController '" + nJointCtrl->getInstanceName() +
-                    "' can't be deleted since this operation is not allowed for this controller! (no NJointController was deleted)"
-                };
-            }
-        }
-        for (const auto& nJointCtrl : ctrlsToActVec)
-        {
-            if (nJointCtrl->isControllerActive() || nJointCtrl->isControllerRequested())
-            {
-                throw LogicError
-                {
-                    "The NJointController '" + nJointCtrl->getInstanceName() +
-                    "' can't be deleted since it is active or requested! (no NJointController was deleted)"
-                };
-            }
-        }
-        for (const auto& nJointCtrl : ctrlsToActVec)
-        {
-            const auto name = nJointCtrl->getInstanceName();
-            //deletion is done in a different thread since this call may be done by the controller (protection against use after free)
-            nJointControllersToBeDeleted[name] = std::move(nJointCtrl);
-            nJointControllers.erase(name);
-            ARMARX_VERBOSE << "added NJointController '" << name << "' to be deleted";
-        }
-    }
-
-    void armarx::RobotUnit::activateNJointControllers(const Ice::StringSeq& names, const Ice::Current&)
-    {
-        ARMARX_VERBOSE << "requesting controller activation for:\n" << names;
-        if (names.empty())
-        {
-            return;
-        }
-        auto guard = getGuard();
-        throwIfDevicesNotReady(__FUNCTION__);
-        auto ctrlsToActVec = getNJointControllersNotNull(names); //also checks if these controllers exist
-        ARMARX_DEBUG << "all requested controllers exist" << std::flush;
-        std::set<NJointControllerPtr, NJointController::IdComp> ctrlsToAct {ctrlsToActVec.begin(), ctrlsToActVec.end()};
-        ARMARX_CHECK_EXPRESSION(!ctrlsToAct.count(nullptr));
-        std::set<NJointControllerPtr, NJointController::IdComp> ctrls {getRequestedNJointControllers().begin(), getRequestedNJointControllers().end()};
-        ctrls.erase(nullptr);
-        //check for conflict
-        std::vector<char> inuse;
-        //check requested controllers
-        {
-            auto r = NJointController::AreNotInConflict(ctrlsToAct.begin(), ctrlsToAct.end());
-            if (!r)
-            {
-                std::stringstream ss;
-                ss << "armarx::RobotUnit::activateNJointControllers: requested controllers are in conflict!\ncontrollers:\n" << names;
-                ARMARX_ERROR << ss.str();
-                throw InvalidArgumentException {ss.str()};
-            }
-            inuse = std::move(r.get());
-        }
-        ARMARX_DEBUG << "all requested controllers are conflict free" << std::flush;
-        auto printInUse = ARMARX_STREAM_PRINTER
-        {
-            for (const auto c : inuse)
-            {
-                out << (c ? 1 : 0);
-            }
-        };
-        ARMARX_DEBUG << "inuse field (request)\n" << printInUse;
-        //add already active controllers if they are conflict free
-        {
-            if (ctrls.empty())
-            {
-                ARMARX_DEBUG << "no already requested NJointControllers";
-            }
-            for (const NJointControllerPtr& nJointCtrl : ctrls)
-            {
-                if (ctrlsToAct.count(nJointCtrl))
-                {
-                    continue;
-                }
-                auto r = nJointCtrl->isNotInConflictWith(inuse);
-                if (r)
-                {
-                    ARMARX_DEBUG << "keeping  already requested NJointController '"
-                                 << nJointCtrl->getInstanceName() << "' in   list of requested controllers";
-                    ctrlsToAct.insert(nJointCtrl);
-                    inuse = std::move(r.get());
-                }
-                else
-                {
-                    ARMARX_INFO << "removing already requested NJointController '"
-                                << nJointCtrl->getInstanceName() << "' from list of requested controllers";
-                }
-            }
-            ARMARX_DEBUG << "inuse field (all)\n" << printInUse;
-        }
-        setActivateControllersRequest(std::move(ctrlsToAct));
-    }
-
-    void armarx::RobotUnit::deactivateNJointControllers(const Ice::StringSeq& names, const Ice::Current&)
-    {
-        ARMARX_VERBOSE << "requesting controller deactivation for:\n" << names;
-        if (names.empty())
-        {
-            return;
-        }
-        auto guard = getGuard();
-        throwIfDevicesNotReady(__FUNCTION__);
-        auto ctrlsDeacVec = getNJointControllersNotNull(names); //also checks if these controllers exist
-        std::set<NJointControllerPtr, NJointController::IdComp> ctrls {getRequestedNJointControllers().begin(), getRequestedNJointControllers().end()};
-        for (const auto& nJointCtrlToDeactivate : ctrlsDeacVec)
-        {
-            ctrls.erase(nJointCtrlToDeactivate);
-        }
-        setActivateControllersRequest(std::move(ctrls));
-    }
-
-    void armarx::RobotUnit::switchNJointControllerSetup(const Ice::StringSeq& newSetup, const Ice::Current&)
-    {
-        auto guard = getGuard();
-        throwIfDevicesNotReady(__FUNCTION__);
-        auto ctrlsToActVec = getNJointControllersNotNull(newSetup); //also checks if these controllers exist
-        setActivateControllersRequest({ctrlsToActVec.begin(), ctrlsToActVec.end()});
-    }
-
-    void armarx::RobotUnit::publish(StringVariantBaseMap additionalMap, StringVariantBaseMap timingMap)
-    {
-        auto begPublish = Now();
-        static const int spamdelay = 30;
-
-        if (state != RobotUnitState::Running)
-        {
-            ARMARX_DEBUG << deactivateSpam(spamdelay) << "skipping publishing in state " << state;
-            return;
-        }
-        auto guard = getGuard();
-
-        throwIfStateIsNot(RobotUnitState::Running, __FUNCTION__);
-
-        //get batch proxies
-        auto debugObserverBatchPrx = debugObserverPrx->ice_batchOneway();
-        auto listenerBatchPrx = listenerPrx->ice_batchOneway();
-        //delete NJoint queued for deletion
-        {
-            for (auto& pair : nJointControllersToBeDeleted)
-            {
-                listenerBatchPrx->nJointControllerDeleted(pair.first);
-                getArmarXManager()->removeObjectNonBlocking(pair.second);
-                ARMARX_VERBOSE << "deleted NJointController " << pair.first;
-            }
-            nJointControllersToBeDeleted.clear();
-        }
-        //swap buffers in
-        const bool haveActivatedControllersChanged = activatedControllersChanged();
-        const bool haveSensorAndControlValsChanged = sensorAndControlBufferChanged();
-        //setup datastructures
-        const auto& controlThreadOutputBuffer =  getSensorAndControlBuffer();
-        const auto& activatedControllers   = getActivatedControllers();
-        const auto& requestedControllers   = getRequestedControllers();
-
-        const auto timestamp = controlThreadOutputBuffer.sensorValuesTimestamp;
-
-        const auto numSensorDevices  = getNumberOfSensorDevices();
-        const auto numControlDevices = getNumberOfControlDevices();
-
-        const bool publishToObserver = !(publishIterationCount % debugObserverSkipIterations);
-        const bool debugObserverPublishControlTargetsThisIteration = ObserverPublishControlTargets;
-        const bool debugObserverPublishSensorValuesThisIteration = ObserverPublishSensorValues;
-        StringVariantBaseMap ctrlDevMap, sensorDevMap;
-        //publish publishing meta state
-        additionalMap["haveActivatedControllersChanged"] = new TimedVariant {haveActivatedControllersChanged, timestamp};
-        additionalMap["haveSensorAndControlValsChanged"] = new TimedVariant {haveSensorAndControlValsChanged, timestamp};
-        additionalMap["publishToObserver"              ] = new TimedVariant {publishToObserver, timestamp};
-        //update
-        if (haveSensorAndControlValsChanged)
-        {
-            //update units
-            timingMap["publishTimings_UnitUpdate"] = new TimedVariant
-            {
-                ARMARX_STOPWATCH(TimestampVariant)
-                {
-                    ARMARX_DEBUG << deactivateSpam(spamdelay) << "updating units with new sensor values";
-                    publishNewSensorDataTime = TimeUtil::GetTime();
-                    for (RobotUnitSubUnitPtr& rsu : subUnits)
-                    {
-                        if (rsu && rsu->getObjectScheduler() && rsu->getProxy())
-                        {
-                            timingMap["publishTimings_UnitUpdate_" + rsu->getName()] = new TimedVariant
-                            {
-                                ARMARX_STOPWATCH(TimestampVariant){rsu->update(controlThreadOutputBuffer, activatedControllers);},
-                                timestamp
-                            };
-                        }
-                    }
-                },
-                timestamp
-            };
-            //publish sensor updates
-
-            timingMap["publishTimings_SensorUpdates"] = new TimedVariant
-            {
-                ARMARX_STOPWATCH(TimestampVariant)
-                {
-                    for (std::size_t sensidx = 0 ; sensidx < numSensorDevices; ++sensidx)
-                    {
-                        const SensorDevice& sensDev = *(sensorDevices.at(sensidx));
-                        const SensorValueBase& sensVal = *(controlThreadOutputBuffer.sensors.at(sensidx));
-                        auto variants = sensVal.toVariants(timestamp);
-
-                        if (!variants.empty())
-                        {
-                            if (debugObserverPublishSensorValuesThisIteration && publishToObserver)
-                            {
-                                transformMapKeys(
-                                    variants, sensorDevMap,
-                                    detail::makeDebugObserverNameFixer(sensDev.getDeviceName() + "_" + sensVal.getSensorValueType(true) + "_")
-                                );
-                            }
-                            SensorDeviceStatus status;
-                            status.deviceName = sensDev.getDeviceName();
-                            status.sensorValue = std::move(variants);
-                            status.timestampUSec = MicroNow().count();
-                            listenerBatchPrx->sensorDeviceStatusChanged(status);
-                        }
-                    }
-                },
-                timestamp
-            };
-        }
-        else
-        {
-            const double sensSecondsAgo = (TimeUtil::GetTime() - publishNewSensorDataTime).toSecondsDouble();
-            if (sensSecondsAgo > 1)
-            {
-                ARMARX_WARNING << deactivateSpam(spamdelay) << "armarx::RobotUnit::publish: Last sensor value update is "
-                               << sensSecondsAgo << " seconds ago!";
-            }
-        }
-        if (haveSensorAndControlValsChanged || haveActivatedControllersChanged)
-        {
-            timingMap["publishTimings_ControlUpdates"] = new TimedVariant
-            {
-                ARMARX_STOPWATCH(TimestampVariant)
-                {
-                    for (std::size_t ctrlidx = 0 ; ctrlidx < numControlDevices; ++ctrlidx)
-                    {
-                        const ControlDevice& ctrlDev = *(controlDevices.at(ctrlidx));
-
-                        StringToStringVariantBaseMapMap variants;
-                        for (const auto& ctrlVal : controlThreadOutputBuffer.control.at(ctrlidx))
-                        {
-                            const auto& controlMode = ctrlVal->getControlMode();
-                            variants[controlMode] = ctrlVal->toVariants(timestamp);
-                            if (
-                                haveSensorAndControlValsChanged &&
-                                !variants[controlMode].empty() &&
-                                debugObserverPublishControlTargetsThisIteration  &&
-                                publishToObserver
-                            )
-                            {
-                                transformMapKeys(
-                                    variants[controlMode], ctrlDevMap,
-                                    detail::makeDebugObserverNameFixer(ctrlDev.getDeviceName() + "_" + controlMode + "_")
-                                );
-                            }
-                        }
-                        ControlDeviceStatus status;
-                        const auto activeJointCtrl = activatedControllers.jointControllers.at(ctrlidx);
-                        status.activeControlMode = activeJointCtrl ? activeJointCtrl->getControlMode() : std::string {"!!JointController is nullptr!!"};
-                        status.deviceName = ctrlDev.getDeviceName();
-                        ARMARX_CHECK_EXPRESSION(requestedControllers.jointControllers.at(ctrlidx));
-                        status.requestedControlMode = requestedControllers.jointControllers.at(ctrlidx)->getControlMode();
-                        status.controlTargetValues = std::move(variants);
-                        status.timestampUSec = MicroNow().count();
-                        listenerBatchPrx->controlDeviceStatusChanged(status);
-                    }
-                },
-                timestamp
-            };
-        }
-        //call publish hook + publish NJointController changes
-        timingMap["publishTimings_NJointControllerUpdates"] = new TimedVariant
-        {
-            ARMARX_STOPWATCH(TimestampVariant)
-            {
-                for (const auto& pair : nJointControllers)
-                {
-                    const NJointControllerPtr& nJointCtrl = pair.second;
-                    timingMap["publishTimings_NJointControllerUpdates_" + nJointCtrl->getInstanceName()] = new TimedVariant
-                    {
-                        ARMARX_STOPWATCH(TimestampVariant)
-                        {
-                            //run some hook for active (used for visu)
-                            PublishNJointController(nJointCtrl, controlThreadOutputBuffer, debugDrawerPrx, debugObserverBatchPrx);
-                            if (
-                                GetNJointControllerStatusReportedActive(nJointCtrl) != nJointCtrl->isControllerActive() ||
-                                GetNJointControllerStatusReportedRequested(nJointCtrl) != nJointCtrl->isControllerRequested()
-                            )
-                            {
-                                UpdateNJointControllerStatusReported(nJointCtrl);
-                                listenerBatchPrx->nJointControllerStatusChanged(nJointCtrl->getControllerStatus());
-                            }
-                        },
-                        timestamp
-                    };
-                }
-            },
-            timestamp
-        };
-
-        //report new class names
-        timingMap["publishTimings_ClassNameUpdates"] = new TimedVariant
-        {
-            ARMARX_STOPWATCH(TimestampVariant)
-            {
-                const auto classNames = NJointControllerRegistry::getKeys();
-                if (lastReportedClasses.size() != classNames.size())
-                {
-                    for (const auto& name : classNames)
-                    {
-                        if (!lastReportedClasses.count(name))
-                        {
-                            listenerBatchPrx->nJointControllerClassAdded(name);
-                            lastReportedClasses.emplace(name);
-                        }
-                    }
-                }
-            },
-            timestamp
-        };
-        timingMap["publishTimings_RobotUnitListenerFlush"] = new TimedVariant
-        {
-            ARMARX_STOPWATCH(TimestampVariant){listenerBatchPrx->ice_flushBatchRequests();}, timestamp
-        };
-
-        if (publishToObserver)
-        {
-            timingMap["publishTimings_LastRobotUnitObserverFlush"] =
-                new TimedVariant {TimestampVariant{lastRobotUnitObserverFlush.count()}, timestamp};
-            timingMap["publishTimings_LastPublishLoop"] = new TimedVariant {TimestampVariant{lastPublishLoop.count()}, timestamp};
-            lastRobotUnitObserverFlush = ARMARX_STOPWATCH()
-            {
-                if (robotUnitObs->getState() >= eManagedIceObjectStarted)
-                {
-                    robotUnitObs->offerOrUpdateDataFieldsFlatCopy(robotUnitObs->additionalChannel, additionalMap);
-                    robotUnitObs->updateChannel(robotUnitObs->additionalChannel);
-                    robotUnitObs->offerOrUpdateDataFieldsFlatCopy(robotUnitObs->timingChannel, timingMap);
-                    robotUnitObs->updateChannel(robotUnitObs->timingChannel);
-                    robotUnitObs->offerOrUpdateDataFieldsFlatCopy(robotUnitObs->controlDevicesChannel, ctrlDevMap);
-                    robotUnitObs->updateChannel(robotUnitObs->controlDevicesChannel);
-                    robotUnitObs->offerOrUpdateDataFieldsFlatCopy(robotUnitObs->sensorDevicesChannel, sensorDevMap);
-                    robotUnitObs->updateChannel(robotUnitObs->sensorDevicesChannel);
-
-                }
-                debugObserverBatchPrx->ice_flushBatchRequests();
-            };
-        }
-        else
-        {
-            lastRobotUnitObserverFlush = std::chrono::microseconds {0};
-        }
-
-        //warn if there are unset jointCtrl controllers
-        {
-            const auto& jointCtrls = getActivatedJointControllers();
-            if (std::any_of(jointCtrls.begin(), jointCtrls.end(), [](const JointController * jointCtrl)
-        {
-            return !jointCtrl;
-        }))
-            {
-                ARMARX_WARNING << "armarx::RobotUnit::publish: Some activated JointControllers are reported to be nullptr! "
-                               << "(did you forget to call rtSwitchControllerSetup()?)";
-            }
-        }
-        ++publishIterationCount;
-        lastPublishLoop = MicroToNow(begPublish);
-    }
-
-    void armarx::RobotUnit::removeAllUnits()
-    {
-        subUnits.clear();
-        for (ManagedIceObjectPtr& unit : units)
-        {
-            getArmarXManager()->removeObjectBlocking(unit->getName());
-        }
-        units.clear();
-    }
-
-    void armarx::RobotUnit::finishRunning()
-    {
-        ARMARX_DEBUG << "RobotUnit::finishRunning()";
-        if (state == RobotUnitState::Exiting)
-        {
-            ARMARX_ERROR << "armarx::RobotUnit::finishRunning called multiple times!";
-        }
-
-        rtLogging.defaultLogHandle = nullptr;
-        if (rtLogging.task)
-        {
-            ARMARX_DEBUG << "shutting down rt logging task";
-            rtLogging.task->stop();
-            while (rtLogging.task->isFunctionExecuting() || rtLogging.task->isRunning())
-            {
-                ARMARX_FATAL << deactivateSpam(0.1) << "RT LOGGING TASK IS RUNNING AFTER IT WAS STOPPED!";
-            }
-            rtLogging.task = nullptr;
-            ARMARX_DEBUG << "shutting down rt logging task done";
-        }
-
-        if (publisherTask)
-        {
-            ARMARX_DEBUG << "shutting down publisher task";
-            publisherTask->stop();
-            auto tPublisherStopped = Now();
-            while (publisherTask->isFunctionExecuting() || publisherTask->isRunning())
-            {
-                ARMARX_FATAL << deactivateSpam(0.1) << "PUBLISHER TASK IS RUNNING AFTER IT WAS STOPPED!";
-            }
-            publisherTask = nullptr;
-            //since the drawer queues draw events and we want to clear the layers, we have to sleep here
-            std::this_thread::sleep_until(tPublisherStopped + std::chrono::milliseconds {100});
-            ARMARX_DEBUG << "shutting down publisher task done";
-        }
-
-        auto guard = getGuard();
-        try
-        {
-            throwIfStateIsNot(RobotUnitState::Running, __FUNCTION__, true);
-            state = RobotUnitState::Exiting;
-            //const ptr maps
-            controlDevicesConstPtr.clear();
-            sensorDevicesConstPtr.clear();
-            //publisher
-
-
-            //RT
-            ARMARX_DEBUG << "joining rt thread";
-            joinRTThread();
-            ARMARX_DEBUG << "joining rt thread...done";
-            //call deac publishing of all active NJoint
-            for (const auto& pair : nJointControllers)
-            {
-                ARMARX_DEBUG << "forcing deactivation of publishing for " << pair.first;
-                DeactivateNJointControllerPublishing(pair.second, debugDrawerPrx, debugObserverPrx);
-            }
-            //units
-            ARMARX_DEBUG << "removing units";
-            removeAllUnits();
-            ARMARX_DEBUG << "removing units...done";
-            //NJoint queued for deletion (some could still be in the queue)
-            {
-                ARMARX_DEBUG << "remove NJointControllers queued for deletion";
-                for (auto& n2NJointCtrl : nJointControllersToBeDeleted)
-                {
-                    NJointControllerPtr& nJointCtrl = n2NJointCtrl.second;
-                    getArmarXManager()->removeObjectBlocking(nJointCtrl->getName());
-                }
-                nJointControllersToBeDeleted.clear();
-                ARMARX_DEBUG << "remove NJointControllers queued for deletion...done";
-            }
-            //NJoint
-            {
-                ARMARX_DEBUG << "remove NJointControllers";
-                for (auto& n2NJointCtrl : nJointControllers)
-                {
-                    NJointControllerPtr& nJointCtrl = n2NJointCtrl.second;
-                    getArmarXManager()->removeObjectBlocking(nJointCtrl->getName());
-                }
-                nJointControllers.clear();
-                ARMARX_DEBUG << "remove NJointControllers...done";
-            }
-            //clear devices
-            sensorDevices.clear();
-            controlDevices.clear();
-            //robot
-            if (robot.use_count() != 1)
-            {
-                ARMARX_WARNING << "The robot's smart pointer use count is " << robot.use_count();
-            }
-            robot.reset();
-            ARMARX_INFO << "RobotUnit finished running";
-        }
-        catch (Ice::Exception& e)
-        {
-            ARMARX_ERROR << "exception in RobotUnit::finishRunning!\nwhat:\n"
-                         << e.what()
-                         << "\n\tname: " << e.ice_name()
-                         << "\n\tfile: " << e.ice_file()
-                         << "\n\tline: " << e.ice_line()
-                         << "\n\tstack: " << e.ice_stackTrace();
-        }
-        catch (std::exception& e)
-        {
-            ARMARX_ERROR << "exception in RobotUnit::finishRunning!\nwhat:\n" << e.what();
-        }
-        catch (...)
-        {
-            ARMARX_ERROR << "exception in RobotUnit::finishRunning!";
-        }
-        ARMARX_DEBUG << "RobotUnit::finishRunning()...done";
-    }
-
-    NJointControllerClassDescription armarx::RobotUnit::getNJointControllerClassDescription(
-        const std::string& className, const Ice::Current&) const
-    {
-        while (state == RobotUnitState::PreComponentInitialization || state == RobotUnitState::InitializingDevices)
-        {
-            //this phase should only last short so busy waiting is ok
-            std::this_thread::sleep_for(std::chrono::milliseconds(50));
-        }
-        auto guard = getGuard();
-        throwIfDevicesNotReady(__FUNCTION__);
-        checkNJointControllerClassName(className);
-        NJointControllerClassDescription data;
-        data.className = className;
-        if (NJointControllerRegistry::get(className)->hasRemoteConfiguration())
-        {
-            data.configDescription =
-                NJointControllerRegistry::get(className)->GenerateConfigDescription(robot, controlDevicesConstPtr, sensorDevicesConstPtr);
-        }
-        return data;
-    }
-
-    NJointControllerClassDescriptionSeq armarx::RobotUnit::getNJointControllerClassDescriptions(const Ice::Current&) const
-    {
-        std::size_t tries = 200;
-        while (state == RobotUnitState::PreComponentInitialization || state == RobotUnitState::InitializingDevices)
-        {
-            //this phase should only last short so busy waiting is ok
-            std::this_thread::sleep_for(std::chrono::milliseconds(50));
-            if (! --tries)
-            {
-                throw RuntimeError {"RobotUnit::getNJointControllerClassDescriptions: it took too long to for the unit to get in a valid state"};
-            }
-        }
-        auto guard = getGuard();
-        NJointControllerClassDescriptionSeq r;
-        r.reserve(NJointControllerRegistry::getKeys().size());
-        for (const auto& key : NJointControllerRegistry::getKeys())
-        {
-            r.emplace_back(getNJointControllerClassDescription(key));
-        }
-        return r;
-    }
-
-    NJointControllerInterfacePrx armarx::RobotUnit::getNJointController(const std::string& name, const Ice::Current&) const
-    {
-        NJointControllerPtr ctrl;
-        {
-            auto guard = getGuard();
-            auto it = nJointControllers.find(name);
-            if (it == nJointControllers.end())
-            {
-                return nullptr;
-            }
-            ctrl = it->second;
-        }
-        return NJointControllerInterfacePrx::uncheckedCast(ctrl->getProxy(-1, true));
-    }
-
-    NJointControllerStatus armarx::RobotUnit::getNJointControllerStatus(const std::string& name, const Ice::Current&) const
-    {
-        auto guard = getGuard();
-        throwIfDevicesNotReady(__FUNCTION__);
-        return getNJointControllerNotNull(name)->getControllerStatus();
-    }
-
-    NJointControllerStatusSeq armarx::RobotUnit::getNJointControllerStatuses(const Ice::Current&) const
-    {
-        auto guard = getGuard();
-        if (!areDevicesReady())
-        {
-            return {};
-        }
-        NJointControllerStatusSeq r;
-        r.reserve(nJointControllers.size());
-        for (const auto& nJointCtrl : nJointControllers)
-        {
-            r.emplace_back(nJointCtrl.second->getControllerStatus());
-        }
-        return r;
-    }
-
-    NJointControllerDescription armarx::RobotUnit::getNJointControllerDescription(const std::string& name, const Ice::Current&) const
-    {
-        NJointControllerPtr nJointCtrl;
-        {
-            auto guard = getGuard();
-            throwIfDevicesNotReady(__FUNCTION__);
-            nJointCtrl = getNJointControllerNotNull(name);
-        }
-        return nJointCtrl->getControllerDescription();
-    }
-
-    NJointControllerDescriptionSeq armarx::RobotUnit::getNJointControllerDescriptions(const Ice::Current&) const
-    {
-        std::map<std::string, NJointControllerPtr> nJointControllersCopy;
-        {
-            auto guard = getGuard();
-            if (!areDevicesReady())
-            {
-                return {};
-            }
-            nJointControllersCopy = nJointControllers;
-        }
-        NJointControllerDescriptionSeq r;
-        r.reserve(nJointControllersCopy.size());
-        for (const auto& nJointCtrl : nJointControllersCopy)
-        {
-            r.emplace_back(nJointCtrl.second->getControllerDescription());
-        }
-        return r;
-    }
-
-    NJointControllerDescriptionWithStatus armarx::RobotUnit::getNJointControllerDescriptionWithStatus(
-        const std::string& name, const Ice::Current&) const
-    {
-        NJointControllerPtr nJointCtrl;
-        {
-            auto guard = getGuard();
-            throwIfDevicesNotReady(__FUNCTION__);
-            nJointCtrl = getNJointControllerNotNull(name);
-        }
-        return nJointCtrl->getControllerDescriptionWithStatus();
-    }
-
-    NJointControllerDescriptionWithStatusSeq armarx::RobotUnit::getNJointControllerDescriptionsWithStatuses(const Ice::Current&) const
-    {
-        std::map<std::string, NJointControllerPtr> nJointControllersCopy;
-        {
-            auto guard = getGuard();
-            if (!areDevicesReady())
-            {
-                return {};
-            }
-            nJointControllersCopy = nJointControllers;
-        }
-        NJointControllerDescriptionWithStatusSeq r;
-        r.reserve(nJointControllersCopy.size());
-        for (const auto& nJointCtrl : nJointControllersCopy)
-        {
-            r.emplace_back(nJointCtrl.second->getControllerDescriptionWithStatus());
-        }
-        return r;
-    }
-
-    Ice::StringSeq armarx::RobotUnit::getControlDeviceNames(const Ice::Current&) const
-    {
-        auto guard = getGuard();
-        throwIfDevicesNotReady(__FUNCTION__);
-        return controlDevices.keys();
-    }
-
-    ControlDeviceDescription armarx::RobotUnit::getControlDeviceDescription(std::size_t idx) const
-    {
-        auto guard = getGuard();
-        throwIfDevicesNotReady(__FUNCTION__);
-        const ControlDevicePtr& controlDevice = controlDevices.at(idx);
-        ControlDeviceDescription data;
-        data.deviceName = controlDevice->getDeviceName();
-        data.tags.assign(controlDevice->getTags().begin(), controlDevice->getTags().end());
-        for (const auto& jointCtrl : controlDevice->getJointControllers())
-        {
-            data.contolModeToTargetType[jointCtrl->getControlMode()].targetType = jointCtrl->getControlTarget()->getControlTargetType();
-            data.contolModeToTargetType[jointCtrl->getControlMode()].hardwareControlMode = jointCtrl->getHardwareControlMode();
-        }
-        return data;
-    }
-
-    ControlDeviceDescription armarx::RobotUnit::getControlDeviceDescription(const std::string& name, const Ice::Current&) const
-    {
-        auto guard = getGuard();
-        throwIfDevicesNotReady(__FUNCTION__);
-        if (!controlDevices.has(name))
-        {
-            std::stringstream ss;
-            ss << "armarx::RobotUnit::getControlDeviceDescription: There is no ControlDevice '" << name
-               << "'. There are these ControlDevices: " << controlDevices.keys();
-            throw InvalidArgumentException {ss.str()};
-        }
-        return getControlDeviceDescription(controlDevices.index(name));
-    }
-
-    ControlDeviceDescriptionSeq armarx::RobotUnit::getControlDeviceDescriptions(const Ice::Current&) const
-    {
-        auto guard = getGuard();
-        if (!areDevicesReady())
-        {
-            return {};
-        }
-        ControlDeviceDescriptionSeq r;
-        r.reserve(getNumberOfControlDevices());
-        for (auto idx : getIndices(controlDevices.values()))
-        {
-            r.emplace_back(getControlDeviceDescription(idx));
-        }
-        return r;
-    }
-
-    ControlDeviceStatus armarx::RobotUnit::getControlDeviceStatus(std::size_t idx) const
-    {
-        auto guard = getGuard();
-        throwIfDevicesNotReady(__FUNCTION__);
-        const ControlDevicePtr& controlDevice = controlDevices.at(idx);
-        ControlDeviceStatus status;
-        const auto activeJointCtrl = getActivatedJointControllers().at(idx);
-        status.activeControlMode = activeJointCtrl ? activeJointCtrl->getControlMode() : std::string {"!!JointController is nullptr!!"};
-        status.deviceName = controlDevice->getDeviceName();
-        ARMARX_CHECK_EXPRESSION(getRequestedJointControllers().at(idx));
-        status.requestedControlMode = getRequestedJointControllers().at(idx)->getControlMode();
-        for (const auto& targ : getSensorAndControlBuffer().control.at(idx))
-        {
-            status.controlTargetValues[targ->getControlMode()] = targ->toVariants(getSensorAndControlBuffer().sensorValuesTimestamp);
-        }
-        status.timestampUSec = MicroNow().count();
-        return status;
-    }
-
-    ControlDeviceStatus armarx::RobotUnit::getControlDeviceStatus(const std::string& name, const Ice::Current&) const
-    {
-        auto guard = getGuard();
-        throwIfDevicesNotReady(__FUNCTION__);
-        if (!controlDevices.has(name))
-        {
-            std::stringstream ss;
-            ss << "armarx::RobotUnit::getControlDeviceStatus: There is no ControlDevice '" << name
-               << "'. There are these ControlDevices: " << controlDevices.keys();
-            throw InvalidArgumentException {ss.str()};
-        }
-        return getControlDeviceStatus(controlDevices.index(name));
-    }
-
-    ControlDeviceStatusSeq armarx::RobotUnit::getControlDeviceStatuses(const Ice::Current&) const
-    {
-        auto guard = getGuard();
-        if (!areDevicesReady())
-        {
-            return {};
-        }
-        ControlDeviceStatusSeq r;
-        r.reserve(getNumberOfControlDevices());
-        for (auto idx : getIndices(controlDevices.values()))
-        {
-            r.emplace_back(getControlDeviceStatus(idx));
-        }
-        return r;
-    }
-
-    Ice::StringSeq armarx::RobotUnit::getSensorDeviceNames(const Ice::Current&) const
-    {
-        auto guard = getGuard();
-        throwIfDevicesNotReady(__FUNCTION__);
-        return sensorDevices.keys();
-    }
-
-    SensorDeviceDescription armarx::RobotUnit::getSensorDeviceDescription(std::size_t idx) const
-    {
-        auto guard = getGuard();
-        throwIfDevicesNotReady(__FUNCTION__);
-        const SensorDevicePtr& sensorDevice = sensorDevices.at(idx);
-        SensorDeviceDescription data;
-        data.deviceName = sensorDevice->getDeviceName();
-        data.tags.assign(sensorDevice->getTags().begin(), sensorDevice->getTags().end());
-        data.sensorValueType = sensorDevice->getSensorValueType();
-        return data;
-    }
-
-    SensorDeviceDescription armarx::RobotUnit::getSensorDeviceDescription(const std::string& name, const Ice::Current&) const
-    {
-        auto guard = getGuard();
-        throwIfDevicesNotReady(__FUNCTION__);
-        if (!sensorDevices.has(name))
-        {
-            std::stringstream ss;
-            ss << "armarx::RobotUnit::getSensorDeviceDescription: There is no SensorDevice '" << name
-               << "'. There are these SensorDevices: " << sensorDevices.keys();
-            throw InvalidArgumentException {ss.str()};
-        }
-        return getSensorDeviceDescription(sensorDevices.index(name));
-    }
-
-    SensorDeviceDescriptionSeq armarx::RobotUnit::getSensorDeviceDescriptions(const Ice::Current&) const
-    {
-        auto guard = getGuard();
-        if (!areDevicesReady())
-        {
-            return {};
-        }
-        SensorDeviceDescriptionSeq r;
-        r.reserve(getNumberOfSensorDevices());
-        for (auto idx : getIndices(sensorDevices.values()))
-        {
-            r.emplace_back(getSensorDeviceDescription(idx));
-        }
-        return r;
-    }
-
-    SensorDeviceStatus armarx::RobotUnit::getSensorDeviceStatus(std::size_t idx) const
-    {
-        auto guard = getGuard();
-        throwIfDevicesNotReady(__FUNCTION__);
-        const SensorDevicePtr& sensorDevice = sensorDevices.at(idx);
-        SensorDeviceStatus status;
-        status.deviceName = sensorDevice->getDeviceName();
-        status.sensorValue = getSensorAndControlBuffer().sensors.at(idx)->toVariants(getSensorAndControlBuffer().sensorValuesTimestamp);
-        status.timestampUSec = MicroNow().count();
-        return status;
-    }
-
-    SensorDeviceStatus armarx::RobotUnit::getSensorDeviceStatus(const std::string& name, const Ice::Current&) const
-    {
-        auto guard = getGuard();
-        throwIfDevicesNotReady(__FUNCTION__);
-        if (!sensorDevices.has(name))
-        {
-            std::stringstream ss;
-            ss << "armarx::RobotUnit::getSensorDeviceStatus: There is no SensorDevice '" << name
-               << "'. There are these SensorDevices: " << sensorDevices.keys();
-            throw InvalidArgumentException {ss.str()};
-        }
-        return getSensorDeviceStatus(sensorDevices.index(name));
-    }
-
-    SensorDeviceStatusSeq armarx::RobotUnit::getSensorDeviceStatuses(const Ice::Current&) const
-    {
-        auto guard = getGuard();
-        if (!areDevicesReady())
-        {
-            return {};
-        }
-        SensorDeviceStatusSeq r;
-        r.reserve(getNumberOfSensorDevices());
-        for (auto idx : getIndices(sensorDevices.values()))
-        {
-            r.emplace_back(getSensorDeviceStatus(idx));
-        }
-        return r;
-    }
-
-    std::vector<armarx::NJointControllerPtr> armarx::RobotUnit::getNJointControllersNotNull(const std::vector<std::string>& names) const
-    {
-        auto guard = getGuard();
-        throwIfDevicesNotReady(__FUNCTION__);
-        std::vector<NJointControllerPtr> ctrl;
-        ctrl.reserve(names.size());
-        for (const auto& name : names)
-        {
-            ctrl.emplace_back(getNJointControllerNotNull(name));
-        }
-        return ctrl;
-    }
-    const NJointControllerPtr& armarx::RobotUnit::getNJointControllerNotNull(const std::string& name) const
-    {
-        auto guard = getGuard();
-        throwIfDevicesNotReady(__FUNCTION__);
-        auto it = nJointControllers.find(name);
-        if (it == nJointControllers.end())
-        {
-            std::stringstream ss;
-            ss << "RobotUnit: there is no NJointController with name '" << name
-               << "'. Existing NJointControllers are: " << getNJointControllerNames();
-            throw InvalidArgumentException {ss.str()};
-        }
-        if (!it->second)
-        {
-            std::stringstream ss;
-            ss << "RobotUnit: The NJointController with name '" << name
-               << "'. Is a nullptr! This should never be the case (invariant)!  \nMap:\n" << nJointControllers;
-            ARMARX_FATAL << ss.str();
-            throw InvalidArgumentException {ss.str()};
-        }
-        return it->second;
-    }
-
-    StringNJointControllerPrxDictionary armarx::RobotUnit::getAllNJointControllers(const Ice::Current&) const
-    {
-        std::map<std::string, NJointControllerPtr> nJointControllersCopy;
-        {
-            auto guard = getGuard();
-            //copy to keep lock retention time low
-            nJointControllersCopy = nJointControllers;
-        }
-        StringNJointControllerPrxDictionary result;
-        for (const auto& pair : nJointControllersCopy)
-        {
-            result[pair.first] = NJointControllerInterfacePrx::uncheckedCast(pair.second->getProxy(-1, true));
-        }
-        return result;
-    }
-
-    Ice::ObjectProxySeq armarx::RobotUnit::getUnits(const Ice::Current&) const
-    {
-        std::vector<ManagedIceObjectPtr> unitsCopy;
-        {
-            auto guard = getGuard();
-            //copy to keep lock retention time low
-            unitsCopy = units;
-        }
-        Ice::ObjectProxySeq r;
-        r.reserve(unitsCopy.size());
-        for (const ManagedIceObjectPtr& unit : unitsCopy)
-        {
-            r.emplace_back(unit->getProxy(-1, true));
-        }
-        return r;
-    }
-
-    const ManagedIceObjectPtr& armarx::RobotUnit::getUnit(const std::string& staticIceId) const
-    {
-        auto guard = getGuard();
-        for (const ManagedIceObjectPtr& unit : units)
-        {
-            if (unit->ice_isA(staticIceId))
-            {
-                return unit;
-            }
-        }
-        return ManagedIceObject::NullPtr;
-    }
-
-    Ice::ObjectPrx armarx::RobotUnit::getUnit(const std::string& staticIceId, const Ice::Current&) const
-    {
-        //no lock required
-        ManagedIceObjectPtr unit = getUnit(staticIceId);
-        if (unit)
-        {
-            return unit->getProxy(-1, true);
-        }
-        return nullptr;
-    }
-
-    const VirtualRobot::RobotPtr& armarx::RobotUnit::getRobot() const
-    {
-        auto guard = getGuard();
-        throwIfStateIsNot(
-        {
-            RobotUnitState::InitializingDevices,
-            RobotUnitState::InitializingUnits,
-            RobotUnitState::WaitingForRTThreadInitialization,
-            RobotUnitState::Running
-        },
-        __FUNCTION__
-        );
-        ARMARX_CHECK_EXPRESSION(robot);
-        return robot;
-    }
-
-    std::string armarx::RobotUnit::getRobotName() const
-    {
-        auto guard = getGuard();
-        throwIfStateIsNot(
-        {
-            RobotUnitState::InitializingDevices,
-            RobotUnitState::InitializingUnits,
-            RobotUnitState::WaitingForRTThreadInitialization,
-            RobotUnitState::Running
-        },
-        __FUNCTION__
-        );
-        return getRobot()->getName();
-    }
-
-    std::size_t armarx::RobotUnit::getNumberOfControlDevices() const
-    {
-        auto guard = getGuard();
-        throwIfDevicesNotReady(__FUNCTION__);
-        return controlDevices.size();
-    }
-
-    std::size_t armarx::RobotUnit::getNumberOfSensorDevices() const
-    {
-        auto guard = getGuard();
-        throwIfDevicesNotReady(__FUNCTION__);
-        return sensorDevices.size();
-    }
-
-    const DebugDrawerInterfacePrx& armarx::RobotUnit::getDebugDrawerProxy() const
-    {
-        auto guard = getGuard();
-        throwIfDevicesNotReady(__FUNCTION__);
-        return debugDrawerPrx;
-    }
-
-    const RobotUnitListenerPrx& armarx::RobotUnit::getListenerProxy() const
-    {
-        auto guard = getGuard();
-        throwIfDevicesNotReady(__FUNCTION__);
-        return listenerPrx;
-    }
-
-    void armarx::RobotUnit::icePropertiesInitialized()
-    {
-        robotUnitObs = Component::create<RobotUnitObserver>(getIceProperties(), "", getConfigDomain());
-        addPropertyUser(PropertyUserPtr::dynamicCast(robotUnitObs));
-
-        Ice::PropertiesPtr properties = getIceProperties()->clone();
-        const std::string& configDomain = "ArmarX";
-        // create TCPControlSubUnit
-
-        {
-            const std::string configNameTCPControlUnit = getProperty<std::string>("TCPControlUnitName");
-            tcpControllerSubUnit = Component::create<TCPControllerSubUnit>(properties, configNameTCPControlUnit, configDomain);
-            addPropertyUser(PropertyUserPtr::dynamicCast(tcpControllerSubUnit));
-        }
-
-        // create TrajectoryControllerSubUnit
-
-        {
-            const std::string configNameTrajectoryControllerUnit = getProperty<std::string>("TrajectoryControllerUnitName");
-            const std::string confPre = configDomain + "." + configNameTrajectoryControllerUnit + ".";
-            properties->setProperty(confPre + "KinematicUnitName", getProperty<std::string>("KinematicUnitName").getValue());
-            trajectoryControllerSubUnit = Component::create<TrajectoryControllerSubUnit>(properties, configNameTrajectoryControllerUnit, configDomain);
-            addPropertyUser(PropertyUserPtr::dynamicCast(trajectoryControllerSubUnit));
-        }
-    }
-
-
-    RemoteReferenceCounterBasePtr armarx::RobotUnit::startRtLoggingWithAliasNames(const std::string& formatString, const StringStringDictionary& aliasNames, const Ice::Current&)
-    {
-        if (!isRtLoggingEnabled())
-        {
-            throw LogicError {"RtLogging is disabled in the config! (set RTLoggingPeriodMs to a non zero value"};
-        }
-        FileSystemPathBuilder pb {formatString};
-        std::lock_guard<std::mutex> guard {rtLogging.mutex};
-        if (rtLogging.entries.count(pb.getPath()))
-        {
-            throw InvalidArgumentException {"There already is a logger for the path '" + pb.getPath() + "'"};
-        }
-        auto ptr = std::make_shared<RtLogging::Entry>();
-        rtLogging.entries[pb.getPath()] = ptr;
-        RtLogging::Entry& e = *ptr;
-        e.filename = pb.getPath();
-        pb.createParentDirectories();
-        e.stream.open(e.filename);
-        if (!e.stream)
-        {
-            rtLogging.entries.erase(pb.getPath());
-            throw LogicError {"RtLogging could not open filestream for '" + pb.getPath() + "'"};
-        }
-
-        std::stringstream header;
-        header << "marker;iteration;timestamp";
-        auto logDev = [&](const std::string & dev)
-        {
-            for (const auto& pair : aliasNames)
-            {
-                std::string name = pair.first;
-                if (boost::starts_with(dev + "$", name))
-                {
-                    if ((name.size() > 0 && name.back() == '$'))
-                    {
-                        name.resize(name.size() - 1);
-                    }
-                    const std::string& alias = pair.second.empty() ? name : pair.second;
-                    header << ";" << alias << dev.substr(name.size());
-                    return true;
-                }
-            }
-            return false;
-        };
-
-        //get logged sensor device values
-        {
-            e.loggedSensorDeviceValues.reserve(rtLogging.sensorDeviceValueLoggingNames.size());
-            for (const auto& svfields : rtLogging.sensorDeviceValueLoggingNames)
-            {
-                e.loggedSensorDeviceValues.emplace_back();
-                auto& svfieldsFlags = e.loggedSensorDeviceValues.back(); //vv
-                svfieldsFlags.reserve(svfields.size());
-                for (const auto& field : svfields)
-                {
-                    svfieldsFlags.emplace_back(logDev(field));
-                }
-            }
-        }
-        //get logged control device values
-        {
-            e.loggedControlDeviceValues.reserve(rtLogging.controlDeviceValueLoggingNames.size());
-            for (const auto& sjctrls : rtLogging.controlDeviceValueLoggingNames)
-            {
-                e.loggedControlDeviceValues.emplace_back();
-                auto& sjctrlsFlags = e.loggedControlDeviceValues.back(); //vv
-                sjctrlsFlags.reserve(sjctrls.size());
-                for (const auto& ctargfields : sjctrls)
-                {
-
-                    sjctrlsFlags.emplace_back();
-                    auto& ctargfieldsFlags = sjctrlsFlags.back(); //v
-                    ctargfieldsFlags.reserve(ctargfields.size());
-
-                    for (const auto& field : ctargfields)
-                    {
-                        ctargfieldsFlags.emplace_back(logDev(field));
-                    }
-                }
-            }
-        }
-
-        //write header
-        e.stream << header.str() << std::flush; // newline is written at the beginning of each log line
-        //create and return handle
-        auto block = getArmarXManager()->createRemoteReferenceCount(
-                         [ptr]()
-        {
-            ARMARX_DEBUG_S << "RobotUnit: stop RtLogging for file " << ptr->filename;
-            ptr->stopLogging = true;
-        }, e.filename);
-        auto counter = block->getReferenceCounter();
-        block->activateCounting();
-        ARMARX_DEBUG_S << "RobotUnit: start RtLogging for file " << ptr->filename;
-        return counter;
-    }
-
-    RemoteReferenceCounterBasePtr armarx::RobotUnit::startRtLogging(const std::string& formatString, const Ice::StringSeq& loggingNames, const Ice::Current&)
-    {
-        StringStringDictionary alias;
-        for (const auto& name : loggingNames)
-        {
-            alias.emplace(name, "");
-        }
-        return startRtLoggingWithAliasNames(formatString, alias);
-    }
-
-    void armarx::RobotUnit::addMarkerToRtLog(const RemoteReferenceCounterBasePtr& token, const std::string& marker, const Ice::Current&)
-    {
-        if (!isRtLoggingEnabled())
-        {
-            throw LogicError {"RtLogging is disabled in the config! (set RTLoggingPeriodMs to a non zwero value"};
-        }
-        std::lock_guard<std::mutex> guard {rtLogging.mutex};
-        if (!rtLogging.entries.count(token->getId()))
-        {
-            throw InvalidArgumentException {"addMarkerToRtLog called for a nonexistent log"};
-        }
-        rtLogging.entries.at(token->getId())->marker = marker;
-    }
-
-    void armarx::RobotUnit::stopRtLogging(const armarx::RemoteReferenceCounterBasePtr& token, const Ice::Current&)
-    {
-        if (!isRtLoggingEnabled())
-        {
-            throw LogicError {"RtLogging is disabled in the config! (set RTLoggingPeriodMs to a non zwero value"};
-        }
-        std::lock_guard<std::mutex> guard {rtLogging.mutex};
-        if (!rtLogging.entries.count(token->getId()))
-        {
-            throw InvalidArgumentException {"addMarkerToRtLog called for a nonexistent log"};
-        }
-        ARMARX_DEBUG_S << "RobotUnit: stop RtLogging for file " << rtLogging.entries.at(token->getId())->filename;
-        rtLogging.entries.at(token->getId())->stopLogging = true;
-    }
-
-    Ice::StringSeq armarx::RobotUnit::getLoggingNames(const Ice::Current&) const
-    {
-        Ice::StringSeq result;
-        for (const auto& strs : rtLogging.sensorDeviceValueLoggingNames)
-        {
-            result.insert(result.end(), strs.begin(), strs.end());
-        }
-        for (const auto& strvecss : rtLogging.controlDeviceValueLoggingNames)
-        {
-            for (const auto& strs : strvecss)
-            {
-                result.insert(result.end(), strs.begin(), strs.end());
-            }
-        }
-        return result;
-    }
-
-    void armarx::RobotUnit::writeRecentIterationsToFile(const std::string& formatString, const Ice::Current&) const
-    {
-        if (!isRtLoggingEnabled())
-        {
-            throw LogicError {"RtLogging is disabled in the config! (set RTLoggingPeriodMs to a non zero value"};
-        }
-        std::lock_guard<std::mutex> guard {rtLogging.mutex};
-        FileSystemPathBuilder pb {formatString};
-        pb.createParentDirectories();
-        std::ofstream outCSV {pb.getPath() + ".csv"};
-        if (!outCSV)
-        {
-            throw LogicError {"writeRecentIterationsToFile could not open filestream for '" + pb.getPath() + ".csv'"};
-        }
-        std::ofstream outMsg {pb.getPath() + ".messages"};
-        if (!outMsg)
-        {
-            throw LogicError {"writeRecentIterationsToFile could not open filestream for '" + pb.getPath() + ".messages'"};
-        }
-        ARMARX_INFO << "writing the last " << rtLogging.backlog.size() << " iterations to " << pb.getPath() << ".{csv, messages}";
-        //write csv header
-        {
-            outCSV << "iteration;timestamp";
-            for (const auto& vs : rtLogging.sensorDeviceValueLoggingNames)
-            {
-                for (const auto& s : vs)
-                {
-                    outCSV << ";" << s;
-                }
-            }
-            for (const auto& vvs : rtLogging.controlDeviceValueLoggingNames)
-            {
-                for (const auto& vs : vvs)
-                {
-                    for (const auto& s : vs)
-                    {
-                        outCSV << ";" << s;
-                    }
-                }
-            }
-            outCSV << std::endl;
-        }
-
-        for (const detail::ControlThreadOutputBufferEntry& iteration : rtLogging.backlog)
-        {
-            //write csv data
-            {
-                outCSV  << iteration.iteration << ";" << iteration.sensorValuesTimestamp;
-                //sens
-                {
-                    for (const SensorValueBase* val : iteration.sensors)
-                    {
-                        for (std::size_t idxField = 0; idxField < val->getNumberOfDataFields(); ++ idxField)
-                        {
-                            outCSV  << ";" << val->getDataFieldAsString(idxField);
-                        }
-                    }
-                }
-                //ctrl
-                {
-                    for (const auto& vals : iteration.control)
-                    {
-                        for (const ControlTargetBase* val : vals)
-                        {
-                            for (std::size_t idxField = 0; idxField < val->getNumberOfDataFields(); ++ idxField)
-                            {
-                                outCSV  << ";" << val->getDataFieldAsString(idxField);
-                            }
-                        }
-                    }
-                }
-                outCSV << std::endl;
-            }
-            //write message data
-            {
-                for (const detail::RtMessageLogEntryBase* msg : iteration.messages.getEntries())
-                {
-                    if (!msg)
-                    {
-                        break;
-                    }
-                    outMsg << "[" << msg->getTime().toDateTime() << "] iteration "
-                           << iteration.iteration << ":\n"
-                           << msg->format() << std::endl;
-                }
-                outMsg << "\nmessages lost: " << iteration.messages.messagesLost
-                       << " (required additional "
-                       << iteration.messages.requiredAdditionalBufferSpace << " bytes, "
-                       << iteration.messages.requiredAdditionalEntries << " message entries)\n" << std::endl;
-            }
-        }
-    }
-
-    const RobotUnit::SelfCollisionAvoidanceData& RobotUnit::getSelfCollisionAvoidanceData() const
-    {
-        return selfCollisionAvoidanceData;
-    }
-
-    const VirtualRobot::RobotPtr& RobotUnit::getRtRobot() const
-    {
-        return rtRobot;
-    }
-
-    void armarx::RobotUnit::startSelfCollisionAvoidance()
-    {
-        // fill self collision avoidance data
-        // clone robot
-        //        VirtualRobot::CollisionCheckerPtr cc(new VirtualRobot::CollisionChecker());
-        selfCollisionAvoidanceData.robot = this->robot->clone(robot->getName() + "_Clone_SelfCollisionAvoidance");
-
-        selfCollisionAvoidanceData.minDistance = getProperty<float>("MinSelfDistance").getValue();
-
-        // set collision models
-        std::map<std::string, VirtualRobot::SceneObjectSetPtr> colModels;
-        const std::string colModelsString = getProperty<std::string>("SelfCollisionModelPairs").getValue();
-        std::vector<std::string> entries;
-        if (!colModelsString.empty())
-        {
-            entries = armarx::Split(colModelsString, ";", true, true);
-        }
-        for (std::string entry : entries)
-        {
-            // Removing parentheses
-            boost::trim_if(entry, boost::is_any_of("{}"));
-            std::string first = armarx::Split(entry, ",", true, true)[0];
-            std::string second = armarx::Split(entry, ",", true, true)[1];
-
-            if (!selfCollisionAvoidanceData.robot->hasRobotNodeSet(first) && first != "FLOOR")
-            {
-                ARMARX_WARNING << "No RobotNodeSet with name '" << first << "' defined in " << robotFileName << ". Skipping.";
-                continue;
-            }
-            if (!selfCollisionAvoidanceData.robot->hasRobotNodeSet(second) && second != "FLOOR")
-            {
-                ARMARX_WARNING << "No RobotNodeSet with name '" << second << "' defined in " << robotFileName << ". Skipping.";
-                continue;
-            }
-
-            selfCollisionAvoidanceData.modelPairs.push_back(std::make_pair(first, second));
-
-            auto inflateNodeSet = [&](VirtualRobot::RobotNodeSetPtr nodeset)
-            {
-                for (int i = 0; i < static_cast<int>(nodeset->getSize()); ++i)
-                {
-                    if (nodeset->getNode(i)->getCollisionModel())
-                    {
-                        nodeset->getNode(i)->getCollisionModel()->inflateModel(selfCollisionAvoidanceData.minDistance / 2.f);
-                    }
-                    else
-                    {
-                        ARMARX_WARNING << "Self Collision Avoidance: No collision model found for '" << nodeset->getNode(i)->getName() << "'";
-                    }
-                }
-            };
-
-            if (colModels.find(first) == colModels.end() && first != "FLOOR")
-            {
-                inflateNodeSet(selfCollisionAvoidanceData.robot->getRobotNodeSet(first));
-                colModels[first] = selfCollisionAvoidanceData.robot->getRobotNodeSet(first);
-            }
-            if (colModels.find(second) == colModels.end() && second != "FLOOR")
-            {
-                inflateNodeSet(selfCollisionAvoidanceData.robot->getRobotNodeSet(second));
-                colModels[second] = selfCollisionAvoidanceData.robot->getRobotNodeSet(second);
-            }
-        }
-
-        // Adding scene-object representing the floor, to avoid collisions with the floor
-        VirtualRobot::SceneObjectSetPtr boxSet(new VirtualRobot::SceneObjectSet("FLOOR"));
-        float floorHeight = 10.0f;
-        VirtualRobot::ObstaclePtr boxOb = VirtualRobot::Obstacle::createBox(20000, 20000, floorHeight);
-        boxOb->getCollisionModel()->inflateModel(selfCollisionAvoidanceData.minDistance / 2);
-        Eigen::Matrix4f globalPose = Eigen::Matrix4f::Identity();
-
-        boxOb->setGlobalPose(globalPose);
-        boxSet->addSceneObject(boxOb);
-        colModels["FLOOR"] = boxSet;
-
-        selfCollisionAvoidanceData.collisionModels = colModels;
-
-        // Setup robot synchronization
-        this->selfCollisionAvoidanceRobotSynchronization.reset(new RobotSynchronization(this, selfCollisionAvoidanceData.robot, selfCollisionAvoidanceData.robot->getRobotNodeNames()));
-
-        // start the task
-        int colChecksPerSecond = getProperty<int>("SelfCollisionChecksPerSecond").getValue();
-        int intervalMs = (1.0 / (float) colChecksPerSecond) * 1000;
-        selfCollisionAvoidanceTask = new PeriodicTask<RobotUnit>(this, &RobotUnit::updateSelfCollisionAvoidance, intervalMs, false, "SelfCollisionAvoidance");
-        selfCollisionAvoidanceTask->setDelayWarningTolerance(200);
-        selfCollisionAvoidanceTask->start();
-
-        // logging
-        std::string validCollisionModelsString;
-        for (auto it = selfCollisionAvoidanceData.collisionModels.begin(); it != selfCollisionAvoidanceData.collisionModels.end(); ++it)
-        {
-            validCollisionModelsString += it->first;
-            validCollisionModelsString += " ";
-        }
-        ARMARX_IMPORTANT << "Started Self Collision Avoidance:" <<
-                         "\nRobot: " << selfCollisionAvoidanceData.robot->getName() <<
-                         "\nMin. allowed distance: " << selfCollisionAvoidanceData.minDistance << " mm" <<
-                         "\nCollision models: " << validCollisionModelsString <<
-                         "\nCollision checks per second: " << colChecksPerSecond << " (every " << intervalMs << " ms)";
-    }
-
-    void armarx::RobotUnit::stopSelfCollisionAvoidance()
-    {
-        ARMARX_IMPORTANT << "Stopping Self Collision Avoidance.";
-        if (selfCollisionAvoidanceTask)
-        {
-            selfCollisionAvoidanceTask->stop();
-        }
-    }
-
-    void armarx::RobotUnit::updateSelfCollisionAvoidance()
-    {
-        if (emergencyStop || !getProperty<bool>("EnableSelfCollisionAvoidance").getValue())
-        {
-            return;
-        }
-        if (!devicesReadyStates.count(state) || state != RobotUnitState::Running)
-        {
-            ARMARX_VERBOSE << deactivateSpam(1) << "Self Distance Check: Waiting for device initialization.";
-            return;
-        }
-
-        auto startTime = std::chrono::high_resolution_clock::now();
-
-        // update joint values
-        selfCollisionAvoidanceRobotSynchronization->sync();
-
-        // check distances between all collision models
-        std::vector<VirtualRobot::SceneObjectSetPtr> conflictingColModels;
-        std::string distancesString("All collision states:\n");
-        bool anyCollision = false;
-        for (auto it = selfCollisionAvoidanceData.modelPairs.begin(); it != selfCollisionAvoidanceData.modelPairs.end(); ++it)
-        {
-            bool collision = selfCollisionAvoidanceData.robot->getCollisionChecker()->checkCollision(selfCollisionAvoidanceData.collisionModels[it->first], selfCollisionAvoidanceData.collisionModels[it->second]);
-            anyCollision |= collision;
-            distancesString += "---- " + it->first + " <-> " + it->second + " in Collision: " + (collision ? "True" : "False") +  "\n";
-            if (collision)
-            {
-                conflictingColModels.push_back(selfCollisionAvoidanceData.collisionModels[it->first]);
-                conflictingColModels.push_back(selfCollisionAvoidanceData.collisionModels[it->second]);
-            }
-        }
-
-        auto endTime = std::chrono::high_resolution_clock::now();
-        std::chrono::duration<double> duration = std::chrono::duration_cast<std::chrono::duration<double>>(endTime - startTime);
-
-        if (anyCollision)
-        {
-            // collision
-            std::string conflictingColModelsString = "";
-            for (std::size_t i = 0; i < conflictingColModels.size(); i++)
-            {
-                conflictingColModelsString += conflictingColModels.at(i)->getName() + ((i % 2) ? ";" : "<->");
-            }
-
-            ARMARX_WARNING << "Self Distance Check: Collision. Entering EmergencyStop." <<
-                           "\nmin. allowed distance: " << selfCollisionAvoidanceData.minDistance << " mm" <<
-                           "\nConflicting collision models: " << conflictingColModelsString <<
-                           "\n" << distancesString <<
-                           "\nComputation time: " << (duration.count() * 1000) << " ms (max. allowed duration (as specified): " << (1000.0 / getProperty<int>("SelfCollisionChecksPerSecond").getValue()) << " ms)";;
-
-            setEmergencyStopState(EmergencyStopState::eEmergencyStopActive);
-            getEmergencyStopMaster()->setEmergencyStopState(EmergencyStopState::eEmergencyStopActive);
-            // since at least one of the NJoint-Controllers is going to cause a collision, we just kick them all.
-            setActivateControllersRequest({});
-        }
-        else
-        {
-            // no collision
-            ARMARX_DEBUG << deactivateSpam(5) << "Self Distance Check: OK." <<
-                         "\nmin. allowed distance: " << selfCollisionAvoidanceData.minDistance << " mm" <<
-                         "\n" << distancesString <<
-                         "\nComputation time: " << (duration.count() * 1000) << " ms (max. allowed duration (as specified): " << (1000.0 / getProperty<int>("SelfCollisionChecksPerSecond").getValue()) << " ms)";
-        }
-
-    }
-
-    void armarx::RobotUnit::icePropertiesUpdated(const std::set<std::string>& changedProperties)
-    {
-
-        if (changedProperties.count("ObserverPublishSensorValues"))
-        {
-            ObserverPublishSensorValues = getProperty<bool>("ObserverPublishSensorValues").getValue();
-        }
-        if (changedProperties.count("ObserverPublishControlTargets"))
-        {
-            ObserverPublishControlTargets = getProperty<bool>("ObserverPublishControlTargets").getValue();
-        }
-        if (changedProperties.count("ObserverPrintEveryNthIterations"))
-        {
-            debugObserverSkipIterations = getProperty<std::uint64_t>("ObserverPrintEveryNthIterations").getValue();
-        }
-    }
-
-    void armarx::RobotUnit::onInitComponent()
-    {
-        ARMARX_DEBUG << "armarx::RobotUnit::onInitComponent()";
-        //        EmergencyStopMaster::onInitComponent();
-        {
-            auto guard = getGuard();
-            getArmarXManager()->increaseSchedulers(static_cast<int>(getProperty<std::uint64_t>("AdditionalObjectSchedulerCount").getValue()));
-
-            throwIfStateIsNot(RobotUnitState::PreComponentInitialization, __FUNCTION__);
-            robotUnitListenerTopicName = getProperty<std::string>("RobotUnitListenerTopicName").getValue();
-            offeringTopic(getListenerTopicName());
-            offeringTopic(getProperty<std::string>("DebugDrawerUpdatesTopicName").getValue());
-
-            ObserverPublishSensorValues = getProperty<bool>("ObserverPublishSensorValues").getValue();
-            ObserverPublishControlTargets = getProperty<bool>("ObserverPublishControlTargets").getValue();
-
-            //load robot
-            {
-                robotNodeSetName            = getProperty<std::string>("RobotNodeSetName").getValue();
-                robotProjectName            = getProperty<std::string>("RobotFileNameProject").getValue();
-                robotFileName               = getProperty<std::string>("RobotFileName").getValue();
-                robotPlatformName           = getProperty<std::string>("PlatformName").getValue();
-                debugObserverSkipIterations = getProperty<std::uint64_t>("ObserverPrintEveryNthIterations").getValue();
-                if (debugObserverSkipIterations < 1)
-                {
-                    debugObserverSkipIterations = 1;
-                }
-                Ice::StringSeq includePaths;
-                if (!robotProjectName.empty())
-                {
-                    CMakePackageFinder finder(robotProjectName);
-                    Ice::StringSeq projectIncludePaths;
-                    auto pathsString = finder.getDataDir();
-                    boost::split(projectIncludePaths,
-                                 pathsString,
-                                 boost::is_any_of(";,"),
-                                 boost::token_compress_on);
-                    includePaths.insert(includePaths.end(), projectIncludePaths.begin(), projectIncludePaths.end());
-                }
-                if (!ArmarXDataPath::getAbsolutePath(robotFileName, robotFileName, includePaths))
-                {
-                    throw UserException("Could not find robot file " + robotFileName);
-                }
-                // read the robot
-                try
-                {
-                    robot = VirtualRobot::RobotIO::loadRobot(robotFileName, VirtualRobot::RobotIO::eFull);
-                    rtRobot = VirtualRobot::RobotIO::loadRobot(robotFileName, VirtualRobot::RobotIO::eStructure);
-                    rtRobot->setUpdateCollisionModel(false);
-                    rtRobot->setUpdateVisualization(false);
-                    rtRobot->setThreadsafe(false);
-                }
-                catch (VirtualRobot::VirtualRobotException& e)
-                {
-                    throw UserException(e.what());
-                }
-                ARMARX_INFO << "Loaded robot:"
-                            << "\n\tProject      : " << robotProjectName
-                            << "\n\tRobot file   : " << robotFileName
-                            << "\n\tRobotNodeSet : " << robotNodeSetName
-                            << "\n\tNodeNames    : " << robot->getRobotNodeSet(robotNodeSetName)->getNodeNames();
-            }
-            //ControlDeviceHardwareControlModeGroups
-            const std::string controlDeviceHardwareControlModeGroupsStr = getProperty<std::string>("ControlDeviceHardwareControlModeGroups").getValue();
-            if (!controlDeviceHardwareControlModeGroupsStr.empty())
-            {
-                const auto numGroups = std::count(
-                                           controlDeviceHardwareControlModeGroupsStr.begin(),
-                                           controlDeviceHardwareControlModeGroupsStr.end(), ';'
-                                       ) + 1;
-                ctrlModeGroups.groups.reserve(numGroups);
-                std::vector<std::string> strGroups;
-                strGroups.reserve(numGroups);
-                boost::algorithm::split(strGroups, controlDeviceHardwareControlModeGroupsStr, boost::is_any_of(";"));
-                for (const auto& gstr : strGroups)
-                {
-                    std::vector<std::string> strElems;
-                    boost::algorithm::split(strElems, gstr, boost::is_any_of(","));
-                    std::set<std::string> group;
-                    for (auto& device : strElems)
-                    {
-                        boost::algorithm::trim(device);
-                        ARMARX_CHECK_EXPRESSION_W_HINT(
-                            !device.empty(),
-                            "The ControlDeviceHardwareControlModeGroups property contains empty device names"
-                        );
-                        ARMARX_CHECK_EXPRESSION_W_HINT(
-                            !ctrlModeGroups.groupsMerged.count(device),
-                            "The ControlDeviceHardwareControlModeGroups property contains duplicate device names: " << device
-                        );
-                        ctrlModeGroups.groupsMerged.emplace(device);
-                        group.emplace(std::move(device));
-                    }
-                    if (!group.empty())
-                    {
-                        ARMARX_DEBUG << "adding device group:\n"
-                                     << ARMARX_STREAM_PRINTER
-                        {
-                            for (const auto& elem : group)
-                            {
-                                out << "    " << elem << "\n";
-                            }
-                        };
-                        ctrlModeGroups.groups.emplace_back(std::move(group));
-                    }
-                }
-            }
-            ARMARX_CHECK_EXPRESSION(robot);
-            state = RobotUnitState::InitializingDevices;
-        }
-        ARMARX_DEBUG << "armarx::RobotUnit::onInitComponent(): onInitRobotUnit()";
-        onInitRobotUnit();
-        getArmarXManager()->addObject(robotUnitObs);
-        ARMARX_DEBUG << "armarx::RobotUnit::onInitComponent(): add emergency stop master";
-        {
-            emergencyStopMaster = new RobotUnitEmergencyStopMaster {this,  getProperty<std::string>("EmergencyStopTopic").getValue()};
-            ManagedIceObjectPtr obj = ManagedIceObjectPtr::dynamicCast(emergencyStopMaster);
-            ARMARX_CHECK_EXPRESSION_W_HINT(obj, "RobotUnitEmergencyStopMaster");
-            getArmarXManager()->addObject(obj, getProperty<std::string>("EmergencyStopMasterName").getValue(), true);
-            auto prx = obj->getProxy(-1);
-            try
-            {
-                getArmarXManager()->getIceManager()->getIceGridSession()->getAdmin()->addObject(prx);
-            }
-            catch (const IceGrid::ObjectExistsException&)
-            {
-                getArmarXManager()->getIceManager()->getIceGridSession()->getAdmin()->updateObject(prx);
-            }
-            catch (std::exception& e)
-            {
-                ARMARX_WARNING << "add the robot unit as emergency stop master to the ice grid admin!\nThere was an exception:\n" << e.what();
-            }
-        }
-        ARMARX_DEBUG << "armarx::RobotUnit::onInitComponent()...done!";
-    }
-
-    void armarx::RobotUnit::onConnectComponent()
-    {
-        ARMARX_DEBUG << "RobotUnit::onConnectComponent()";
-        listenerPrx = getTopic<RobotUnitListenerPrx>(getListenerTopicName());
-        debugDrawerPrx = getTopic<DebugDrawerInterfacePrx>(getProperty<std::string>("DebugDrawerUpdatesTopicName").getValue());
-        debugObserverPrx = getTopic<DebugObserverInterfacePrx>(getProperty<std::string>("DebugObserverTopicName").getValue());
-        onConnectRobotUnit();
-        ARMARX_DEBUG << "RobotUnit::onConnectComponent()...done!";
-    }
-
-    void armarx::RobotUnit::onDisconnectComponent()
-    {
-        ARMARX_DEBUG << "RobotUnit::onDisconnectComponent()";
-        stopSelfCollisionAvoidance();
-
-        // Disconnecting TCPController and TrajectoryController
-
-        onDisconnectRobotUnit();
-        ARMARX_DEBUG << "RobotUnit::onDisconnectComponent()...done!";
-    }
-
-    void armarx::RobotUnit::onExitComponent()
-    {
-        ARMARX_DEBUG << "RobotUnit::onExitComponent()";
-        ARMARX_DEBUG << "remove EmergencyStopMaster";
-        try
-        {
-            getArmarXManager()->removeObjectBlocking(ManagedIceObjectPtr::dynamicCast(emergencyStopMaster));
-            getArmarXManager()->getIceManager()->removeObject(getProperty<std::string>("EmergencyStopMasterName").getValue());
-        }
-        catch (...) {}
-        ARMARX_DEBUG << "onExitRobotUnit()";
-        onExitRobotUnit();
-        ARMARX_DEBUG << "finishRunning()";
-        finishRunning();
-        ARMARX_DEBUG << "RobotUnit::onExitComponent()...done!";
-    }
-
-    void armarx::RobotUnit::rtUpdateSensorAndControlBuffer(
-        const IceUtil::Time& sensorValuesTimestamp,
-        const IceUtil::Time& timeSinceLastIteration)
-    {
-        rtThreadTimingsSensorDevice->rtMarkRtUpdateSensorAndControlBufferStart();
-        SensorAndControl& sc = controlThreadOutputBuffer.getWriteBuffer();
-        sc.writeTimestamp = IceUtil::Time::now(); // this has to be in real time
-        sc.sensorValuesTimestamp = sensorValuesTimestamp;
-        sc.timeSinceLastIteration = timeSinceLastIteration;
-        for (std::size_t sensIdx = 0; sensIdx < rtGetNumberOfSensorDevices(); ++sensIdx)
-        {
-            sensorDevices.at(sensIdx)->getSensorValue()->_copyTo(sc.sensors.at(sensIdx));
-        }
-        for (std::size_t ctrlIdx = 0; ctrlIdx < controlDevices.size(); ++ctrlIdx)
-        {
-            ControlDevice& controlDevice = *controlDevices.at(ctrlIdx);
-            auto& tv = sc.control.at(ctrlIdx);
-            for (std::size_t targIdx = 0; targIdx < controlDevice.rtGetJointControllers().size(); ++targIdx)
-            {
-                JointController& jointCtrl = *controlDevice.rtGetJointControllers().at(targIdx);
-                jointCtrl.getControlTarget()->_copyTo(tv.at(targIdx));
-            }
-        }
-        controlThreadOutputBuffer.commitWrite();
-
-        for (auto& node : nodePositionSensorMap)
-        {
-            node.first->setJointValueNoUpdate(node.second->position);
-        }
-        rtRobot->applyJointValues();
-        rtThreadTimingsSensorDevice->rtMarkRtUpdateSensorAndControlBufferEnd();
-    }
-
-    void armarx::RobotUnit::writeRequestedControllers(JointAndNJointControllers&& setOfControllers)
-    {
-        auto guard = getGuard();
-        throwIfDevicesNotReady(__FUNCTION__);
-        //check NJoint
-        const auto& nJointCtrls = setOfControllers.nJointControllers;
-        std::set<NJointControllerPtr> nJointSet {nJointCtrls.begin(), nJointCtrls.end()};
-        nJointSet.erase(nullptr);
-        //# NJoint
-        const std::size_t nNJointCtrls = std::count_if(nJointCtrls.begin(), nJointCtrls.end(), [](const NJointControllerPtr & p)
-        {
-            return p;
-        });
-
-        ARMARX_CHECK_EXPRESSION(nNJointCtrls == nJointSet.size());
-        ARMARX_CHECK_EXPRESSION(nJointCtrls.size() == getNumberOfControlDevices());
-        //first nNJointCtrls not null
-        ARMARX_CHECK_EXPRESSION(std::all_of(nJointCtrls.begin(), nJointCtrls.begin() + nNJointCtrls, [](NJointController * p)
-        {
-            return p;
-        }));
-        //last getNumberOfControlDevices()-nNJointCtrls null
-        ARMARX_CHECK_EXPRESSION(std::all_of(nJointCtrls.begin() + nNJointCtrls, nJointCtrls.end(), [](NJointController * p)
-        {
-            return !p;
-        }));
-        //conflict free and sorted
-        ARMARX_CHECK_EXPRESSION(std::is_sorted(nJointCtrls.begin(), nJointCtrls.end(), NJointController::IdComp {}));
-        ARMARX_CHECK_EXPRESSION(NJointController::AreNotInConflict(nJointCtrls.begin(), nJointCtrls.begin() + nNJointCtrls));
-
-        //check JointCtrl
-        const auto& jointCtrls = setOfControllers.jointControllers;
-        ARMARX_CHECK_EXPRESSION(jointCtrls.size() == getNumberOfControlDevices());
-        ARMARX_CHECK_EXPRESSION(std::all_of(jointCtrls.begin(), jointCtrls.end(), [](JointController * p)
-        {
-            return p;
-        }));
-
-        //check groups
-        {
-            ARMARX_DEBUG << "check groups";
-            std::size_t grpIdx = 0;
-            for (const auto& group : ctrlModeGroups.groups)
-            {
-                ARMARX_CHECK_EXPRESSION(!group.empty());
-                const auto hwMode = setOfControllers.jointControllers.at(controlDevices.index(*group.begin()))->getHardwareControlMode();
-                ARMARX_DEBUG << "---- group " << grpIdx << " mode '" << hwMode << "'";
-                for (const auto& other : group)
-                {
-                    const auto& dev = controlDevices.index(other);
-                    ARMARX_CHECK_EXPRESSION(dev);
-                    const auto otherHwMode = setOfControllers.jointControllers.at(dev)->getHardwareControlMode();
-                    ARMARX_DEBUG << "-------- '" << other << "'' mode '" << otherHwMode << "'";
-                    ARMARX_CHECK_EXPRESSION(otherHwMode == hwMode);
-                }
-                ++grpIdx;
-            }
-        }
-        //setup assignement
-        {
-            ARMARX_DEBUG << "setup assignement index";
-            setOfControllers.resetAssignement();
-            for (std::size_t nJointCtrlIndex = 0; nJointCtrlIndex < setOfControllers.nJointControllers.size(); ++nJointCtrlIndex)
-            {
-                const NJointController* nJoint = setOfControllers.nJointControllers.at(nJointCtrlIndex);
-                if (!nJoint)
-                {
-                    break;
-                }
-                ARMARX_DEBUG << "---- " << nJoint->getInstanceName();
-                for (std::size_t jointIndex : nJoint->getControlDeviceUsedIndices())
-                {
-                    ARMARX_CHECK_EXPRESSION(setOfControllers.jointToNJointControllerAssignement.at(jointIndex) == IndexSentinel());
-                    setOfControllers.jointToNJointControllerAssignement.at(jointIndex) = nJointCtrlIndex;
-                }
-            }
-        }
-
-        {
-            ARMARX_DEBUG << "call checkSetOfControllersToActivate";
-            checkSetOfControllersToActivate(setOfControllers);
-        }
-        //set requested state
-        {
-            ARMARX_DEBUG << "set requested state for NJoint controllers";
-            for (const auto& name2NJoint : nJointControllers)
-            {
-                const NJointControllerPtr& nJoint = name2NJoint.second;
-                SetNJointControllerRequested(nJoint, nJointSet.count(nJoint));
-            }
-        }
-        controllersRequested.getWriteBuffer() = std::move(setOfControllers);
-        controllersRequested.commitWrite();
-    }
-
-    const JointAndNJointControllers& armarx::RobotUnit::getRequestedControllers() const
-    {
-        auto guard = getGuard();
-        throwIfDevicesNotReady(__FUNCTION__);
-        return controllersRequested.getWriteBuffer();
-    }
-
-    const std::vector<armarx::JointController*>& armarx::RobotUnit::getRequestedJointControllers() const
-    {
-        auto guard = getGuard();
-        throwIfDevicesNotReady(__FUNCTION__);
-        return getRequestedControllers().jointControllers;
-    }
-
-    const std::vector<armarx::NJointController*>& armarx::RobotUnit::getRequestedNJointControllers() const
-    {
-        auto guard = getGuard();
-        throwIfDevicesNotReady(__FUNCTION__);
-        return getRequestedControllers().nJointControllers;
-    }
-
-    bool armarx::RobotUnit::activatedControllersChanged() const
-    {
-        auto guard = getGuard();
-        throwIfDevicesNotReady(__FUNCTION__);
-        return controllersActivated.updateReadBuffer();
-    }
-
-    const JointAndNJointControllers& armarx::RobotUnit::getActivatedControllers() const
-    {
-        auto guard = getGuard();
-        throwIfDevicesNotReady(__FUNCTION__);
-        return controllersActivated.getReadBuffer();
-    }
-
-    const std::vector<armarx::JointController*>& armarx::RobotUnit::getActivatedJointControllers() const
-    {
-        auto guard = getGuard();
-        throwIfDevicesNotReady(__FUNCTION__);
-        return getActivatedControllers().jointControllers;
-    }
-
-    const std::vector<armarx::NJointController*>& armarx::RobotUnit::getActivatedNJointControllers() const
-    {
-        auto guard = getGuard();
-        throwIfDevicesNotReady(__FUNCTION__);
-        return getActivatedControllers().nJointControllers;
-    }
-
-    bool armarx::RobotUnit::sensorAndControlBufferChanged() const
-    {
-        auto guard = getGuard();
-        throwIfDevicesNotReady(__FUNCTION__);
-        return controlThreadOutputBuffer.updateReadBuffer();
-    }
-
-    const SensorAndControl& armarx::RobotUnit::getSensorAndControlBuffer() const
-    {
-        auto guard = getGuard();
-        throwIfDevicesNotReady(__FUNCTION__);
-        return controlThreadOutputBuffer.getReadBuffer();
-    }
-
-    std::ostream& operator<<(std::ostream& o, RobotUnitState s)
-    {
-        o << std::to_string(s);
-        return o;
-    }
-}
-
-void armarx::RobotUnit::RtLogging::doLogging()
-{
-    ARMARX_CHECK_EXPRESSION(enabled);
-    std::lock_guard<std::mutex> guard {mutex};
-    const auto now = IceUtil::Time::now();
-    // entries are removed last
-
-    //remove backlog entries
-    {
-        while (!backlog.empty() && backlog.front().writeTimestamp + keepBacklogFor < now)
-        {
-            backlog.pop_front();
-        }
-    }
-    //log all
-    {
-        ru->controlThreadOutputBuffer.foreachNewLoggingEntry([&](const ControlThreadOutputBuffer::Entry & data)
-        {
-            //base (marker;iteration;timestamp)
-            {
-                for (auto& pair : entries)
-                {
-                    Entry& e = *pair.second;
-                    e.stream << "\n"
-                             << e.marker << ";"
-                             << data.iteration << ";"
-                             << data.sensorValuesTimestamp.toMicroSeconds();
-                    e.marker.clear();
-                }
-            }
-            //sens
-            {
-                for (std::size_t idxDev = 0; idxDev < data.sensors.size(); ++ idxDev)
-                {
-                    const SensorValueBase* val = data.sensors.at(idxDev);
-                    for (std::size_t idxField = 0; idxField < val->getNumberOfDataFields(); ++ idxField)
-                    {
-                        const auto str = val->getDataFieldAsString(idxField);
-                        for (auto& pair : entries)
-                        {
-                            Entry& e = *pair.second;
-                            if (e.loggedSensorDeviceValues.at(idxDev).at(idxField))
-                            {
-                                pair.second->stream  << ";" << str;
-                            }
-                        }
-                    }
-                }
-            }
-            //ctrl
-            {
-                for (std::size_t idxDev = 0; idxDev < data.control.size(); ++ idxDev)
-                {
-                    const auto& vals = data.control.at(idxDev);
-                    for (std::size_t idxVal = 0; idxVal < vals.size(); ++idxVal)
-                    {
-                        const ControlTargetBase* val = vals.at(idxVal);
-                        for (std::size_t idxField = 0; idxField < val->getNumberOfDataFields(); ++ idxField)
-                        {
-                            const auto str = val->getDataFieldAsString(idxField);
-                            for (auto& pair : entries)
-                            {
-                                Entry& e = *pair.second;
-                                if (e.loggedControlDeviceValues.at(idxDev).at(idxVal).at(idxField))
-                                {
-                                    pair.second->stream  << ";" << str;
-                                }
-                            }
-                        }
-                    }
-                }
-            }
-            //store data to backlog
-            {
-                if (data.writeTimestamp + keepBacklogFor >= now)
-                {
-                    backlog.emplace_back(data, true); //true for minimal copy
-                }
-            }
-            //print + reset messages
-            {
-                for (const detail::RtMessageLogEntryBase* ptr : data.messages.getEntries())
-                {
-                    if (!ptr)
-                    {
-                        break;
-                    }
-                    ptr->print(rtThreadId);
-                }
-            }
-        });
-    }
-    ARMARX_DEBUG_S << ::deactivateSpam() << "the last " << backlog.size() << " iterations are stored";
-    //flush all files
-    {
-        for (auto& pair : entries)
-        {
-            pair.second->stream << std::flush;
-        }
-    }
-
-    //remove entries
-    {
-        std::vector<std::string> toRemove;
-        toRemove.reserve(entries.size());
-        for (auto& pair : entries)
-        {
-            if (pair.second->stopLogging)
-            {
-                //can't remove the current elemet
-                //(this would invalidate the current iterator)
-                toRemove.emplace_back(pair.first);
-            }
-        }
-        for (const auto& rem : toRemove)
-        {
-            entries.erase(rem);
-        }
-    }
 }
-
diff --git a/source/RobotAPI/components/units/RobotUnit/RobotUnit.h b/source/RobotAPI/components/units/RobotUnit/RobotUnit.h
index 9d16cc9a716a44e0d8bb87895907be8963cac2c8..30541f3206fa56f344b77c524dac669af4b2cedb 100644
--- a/source/RobotAPI/components/units/RobotUnit/RobotUnit.h
+++ b/source/RobotAPI/components/units/RobotUnit/RobotUnit.h
@@ -22,299 +22,58 @@
 
 #pragma once
 
-#include <thread>
-#include <atomic>
-#include <chrono>
-#include <mutex>
-#include <unordered_map>
-#include <memory>
-#include <fstream>
-
-#include <ArmarXCore/core/util/OnScopeExit.h>
-#include <ArmarXCore/core/Component.h>
-#include <ArmarXCore/core/ArmarXManager.h>
-#include <ArmarXCore/core/time/TimeUtil.h>
-#include <ArmarXCore/core/exceptions/local/ExpressionException.h>
-#include <ArmarXCore/core/util/algorithm.h>
-#include <ArmarXCore/core/util/TripleBuffer.h>
-#include <ArmarXCore/core/services/tasks/TaskUtil.h>
-#include <ArmarXCore/observers/DebugObserver.h>
-#include <ArmarXCore/interface/components/EmergencyStopInterface.h>
-
-#include <RobotAPI/interface/units/RobotUnit/RobotUnitInterface.h>
-
-#include <VirtualRobot/Robot.h>
-#include <VirtualRobot/SceneObjectSet.h>
-
-#include "Units/RobotUnitSubUnit.h"
-#include "JointControllers/JointController.h"
+#include "RobotUnitModules/RobotUnitModules.h"
 #include "NJointControllers/NJointController.h"
-#include "Devices/ControlDevice.h"
-#include "Devices/SensorDevice.h"
-#include "Devices/RTThreadTimingsSensorDevice.h"
-#include "util.h"
-#include "util/JointAndNJointControllers.h"
-#include "RobotUnitObserver.h"
-#include "RobotSynchronization.h"
 
 namespace armarx
 {
     TYPEDEF_PTRS_HANDLE(RobotUnit);
-    class RobotUnitObserver;
-    typedef IceInternal::Handle<RobotUnitObserver> RobotUnitObserverPtr;
 
-    class SensorValue1DoFActuatorPosition;
     /**
      * @class RobotUnitPropertyDefinitions
      * @brief
      */
     class RobotUnitPropertyDefinitions:
-        public ComponentPropertyDefinitions
+        public RobotUnitModule::UnitsPropertyDefinitions,
+        public RobotUnitModule::DevicesPropertyDefinitions,
+        public RobotUnitModule::LoggingPropertyDefinitions,
+        public RobotUnitModule::RobotDataPropertyDefinitions,
+        public RobotUnitModule::PublisherPropertyDefinitions,
+        public RobotUnitModule::ManagementPropertyDefinitions,
+        public RobotUnitModule::SelfCollisionCheckerPropertyDefinitions
     {
     public:
         RobotUnitPropertyDefinitions(std::string prefix):
-            ComponentPropertyDefinitions(prefix)
-        {
-            // ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// //
-            // ////////////////////////////////////////////////////////// General Config /////////////////////////////////////////////////////////// //
-            // ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// //
-            defineOptionalProperty<std::uint64_t>(
-                "AdditionalObjectSchedulerCount", 10,
-                "Number of ObjectSchedulers to be added");
-
-            defineRequiredProperty<std::string>(
-                "RobotFileName", "Robot file name, e.g. robot_model.xml");
-            defineOptionalProperty<std::string>(
-                "RobotFileNameProject", "",
-                "Project in which the robot filename is located (if robot is loaded from an external project)");
-
-            defineOptionalProperty<std::string>(
-                "RobotNodeSetName", "Robot",
-                "Robot node set name as defined in robot xml file, e.g. 'LeftArm'");
-            defineOptionalProperty<std::string>(
-                "PlatformName", "Platform",
-                "Name of the platform (will publish values on PlatformName + 'State')");
-
-            defineOptionalProperty<std::string>(
-                "ControlDeviceHardwareControlModeGroups", "",
-                "Groups of control devices for which the same hardware control mode has to be set. "
-                "For a control mode, the JointControllers of all devices in a group must have the identical hardware control mode. "
-                "The kinematic unit will change the control mode of all joints in a group,"
-                " if their current hw control mode does not match the new hw control mode. "
-                "This can be used if the robot has a multi DOF joint which is represented by multiple  1DOF control devices "
-                "(in such a case all of these 1DOF joints should have the same hw control mode, "
-                "except he multi DOF joint can handle different control modes at once). "
-                "Syntax: semicolon separated groups , each group is CSV of joints "
-                "e.g. j1,j2;j3,j4,j5 -> Group 1 = j1+j2 Group 2 = j3+j4+j5; No joint may be in two groups!"
-            );
-
-            // ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// //
-            // ////////////////////////////////////////////////////////// Emergency Stop /////////////////////////////////////////////////////////// //
-            // ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// //
-            defineOptionalProperty<std::string>(
-                "EmergencyStopMasterName", "EmergencyStopMaster",
-                "The name used to register as an EmergencyStopMaster");
-
-            defineOptionalProperty<std::string>(
-                "EmergencyStopTopic", "EmergencyStop",
-                "The name of the topic over which changes of the emergencyStopState are sent.");
-
-            // ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// //
-            // //////////////////////////////////////////////////////////// Publishing ///////////////////////////////////////////////////////////// //
-            // ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// //
-            defineOptionalProperty<std::string>(
-                "RobotUnitListenerTopicName", "RobotUnitListenerTopic",
-                "The topic receiving events for RobotUnitListener");
-            defineOptionalProperty<std::string>(
-                "DebugDrawerUpdatesTopicName", "DebugDrawerUpdates",
-                "The topic receiving events for debug drawing");
-            defineOptionalProperty<std::size_t>(
-                "PublishPeriodMs", 10,
-                "Milliseconds between each publish");
-
-            defineOptionalProperty<bool>(
-                "ObserverPublishSensorValues", true,
-                "Whether sensor values are send to the observer", PropertyDefinitionBase::eModifiable);
-            defineOptionalProperty<bool>(
-                "ObserverPublishControlTargets", true,
-                "Whether control targets are send to the observer", PropertyDefinitionBase::eModifiable);
-            defineOptionalProperty<std::string>(
-                "DebugObserverTopicName", "DebugObserver", "The topic where updates are send to");
-            defineOptionalProperty<std::uint64_t>(
-                "ObserverPrintEveryNthIterations", 1,
-                "Only every nth iteration data is send to the debug observer", PropertyDefinitionBase::eModifiable);
-
-            // ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// //
-            // /////////////////////////////////////////////////////////////// Units /////////////////////////////////////////////////////////////// //
-            // ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// //
-            defineOptionalProperty<std::string>(
-                "KinematicUnitName", "KinematicUnit",
-                "The name of the created kinematic unit");
-
-            defineOptionalProperty<std::string>(
-                "PlatformUnitName", "PlatformUnit",
-                "The name of the created platform unit");
-
-            defineOptionalProperty<std::string>(
-                "ForceTorqueUnitName", "ForceTorqueUnit",
-                "The name of the created force troque unit (empty = default)");
-            defineOptionalProperty<std::string>(
-                "ForceTorqueTopicName", "ForceTorqueValues",
-                "Name of the topic on which the force torque sensor values are provided");
-
-            defineOptionalProperty<std::string>(
-                "InertialMeasurementUnitName", "InertialMeasurementUnit",
-                "The name of the created inertial measurement unit (empty = default)");
-            defineOptionalProperty<std::string>(
-                "IMUTopicName", "IMUValues",
-                "Name of the IMU Topic.");
-
-            defineOptionalProperty<bool>(
-                "CreateTCPControlUnit", false,
-                "If true the TCPControl SubUnit is created and added");
-            defineOptionalProperty<std::string>(
-                "TCPControlUnitName", "TCPControlUnit",
-                "Name of the TCPControlUnit.");
-            defineOptionalProperty<bool>(
-                "CreateTrajectoryPlayer", true,
-                "If true the TrajectoryPlayer SubUnit is created and added");
-            defineOptionalProperty<std::string>(
-                "TrajectoryControllerUnitName", "TrajectoryPlayer",
-                "Name of the TrajectoryControllerUnit. The respective component outside of the RobotUnit is TrajectoryPlayer");
-
-            // ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// //
-            // //////////////////////////////////////////////////////////// Rt Logging ///////////////////////////////////////////////////////////// //
-            // ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// //
-            defineOptionalProperty<std::size_t>(
-                "RTLoggingPeriodMs", 10,
-                "Period of the rt-logging thread in milliseconds. "
-                "A high period can cause spikes in disk activity if data is logged to disk. "
-                "A low period causes more computation overhead and memory consumption. "
-                "If set to 0, all rt-logging is deactivated");
-
-            defineOptionalProperty<std::string>(
-                "RTLoggingDefaultLog", "",
-                "If rt logging is active and a file path is given, all data is logged to this file.");
-
-            defineOptionalProperty<std::size_t>(
-                "RTLoggingMessageNumber", 1000,
-                "Number of messages that can be logged in the control thread");
-            defineOptionalProperty<std::size_t>(
-                "RTLoggingMessageBufferSize", 1024 * 1024,
-                "Number of bytes that can be logged in the control thread");
-            defineOptionalProperty<std::size_t>(
-                "RTLoggingMaxMessageNumber", 16000,
-                "Max number of messages that can be logged in the control thread");
-            defineOptionalProperty<std::size_t>(
-                "RTLoggingMaxMessageBufferSize", 16 * 1024 * 1024,
-                "Max number of bytes that can be logged in the control thread");
-
-            defineOptionalProperty<std::size_t>(
-                "RTLoggingKeepIterationsForMs", 60 * 1000,
-                "All logging data (SensorValues, ControlTargets, Messages) is keept for this duration "
-                "and can be dunped in case of an error.");
-
-            // ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// //
-            // ////////////////////////////////////////////////////// Self Collision Avoidance ///////////////////////////////////////////////////// //
-            // ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// //
-            defineOptionalProperty<bool>(
-                "EnableSelfCollisionAvoidance", true,
-                "Whether self collision avoidance should be active or not.", PropertyDefinitionBase::eModifiable);
-            defineOptionalProperty<int>(
-                "SelfCollisionChecksPerSecond", 10,
-                "Frequency [Hz] of self collision checking (default = 10).", PropertyDefinitionBase::eConstant);
-            defineOptionalProperty<float>(
-                "MinSelfDistance", 20,
-                "Minimum allowed distance (mm) between each collision model before entering emergency stop (default = 20).",
-                PropertyDefinitionBase::eConstant);
-            defineOptionalProperty<std::string>(
-                "SelfCollisionModelPairs", "",
-                "Comma seperated list of pairs of collision models that should be checked against each other by collision avoidance \n"
-                "(e.g. {rnsColModel1,rnsColModel2};{rnsColModel3,rnsColModel4}; .... "
-                "says that rnsColModel1 will be only checked against rnsColModel2 and rnsColModel3 will only be checked against rnsColModel4). \n"
-                "Following predefined descriptors can be used: 'FLOOR' which represents a virtual collision model of the floor.", PropertyDefinitionBase::eConstant);
-
-            defineOptionalProperty<std::string>(
-                "TCPControlUnitName", "TCPControlUnit",
-                "Name of the TCPControlUnit.");
-            defineOptionalProperty<std::string>(
-                "TrajectoryControllerUnitName", "TrajectoryPlayer",
-                "Name of the TrajectoryControllerUnit. The respective component outside of the RobotUnit is TrajectoryPlayer");
-        }
+            UnitsPropertyDefinitions(prefix),
+            DevicesPropertyDefinitions(prefix),
+            LoggingPropertyDefinitions(prefix),
+            RobotDataPropertyDefinitions(prefix),
+            PublisherPropertyDefinitions(prefix),
+            ManagementPropertyDefinitions(prefix),
+            SelfCollisionCheckerPropertyDefinitions(prefix)
+        {}
     };
-
-    /// @brief The current state of the multi step initialization of a RobotUnit
-    enum class RobotUnitState : std::size_t
-    {
-        PreComponentInitialization,
-        InitializingDevices,
-        //ok to use devices/create controllers
-        InitializingUnits,
-        WaitingForRTThreadInitialization,
-        Running,
-        Exiting
-    };
-}
-namespace std
-{
-    std::string to_string(armarx::RobotUnitState s);
 }
 
 namespace armarx
 {
-    std::ostream& operator<<(std::ostream& o, RobotUnitState s);
-
-    /**
-     * @brief This class is a friend of NJointController.
-     *
-     * It encapsulates all access to privates of a NJointController
-     * to reduce the amount of code which could break invariants
-     * in NJointController and to collect all such code in one place
-     * to make this problem more manageable.
-     *
-     * Also the private functions of NJointController should not be made public to prevent
-     * other classes (e.g. KinematicSubUnit) or derived NJointControllers
-     * from accessing them
-     *
-     */
-    class RobotUnitNJointControllerAccess
-    {
-    protected:
-        static void RtSetNJointControllerActivatedStatus(const NJointControllerPtr& nJointCtrl);
-        static void RtSetNJointControllerDeactivatedStatus(const NJointControllerPtr& nJointCtrl);
-        static void RtSetNJointControllerDeactivatedBecauseOfErrorStatus(const NJointControllerPtr& nJointCtrl);
-        static void InitNJointControler(
-            const NJointControllerPtr& nJointCtrl,
-            RobotUnit* ru,
-            std::size_t ctrlId,
-            std::map<std::string, const JointController*> ctrlDeviceUsedJointController,
-            std::vector<char> ctrlDeviceUsedBitmap,
-            std::vector<std::size_t> ctrlDeviceUsedIndices,
-            bool deletable,
-            bool internal
-        ) noexcept;
-        static void PublishNJointController(
-            const NJointControllerPtr& nJointCtrl,
-            const SensorAndControl& sac,
-            const DebugDrawerInterfacePrx& draw,
-            const DebugObserverInterfacePrx& observer
-        );
-        bool GetNJointControllerStatusReportedActive(const NJointControllerPtr& nJointCtrl);
-        bool GetNJointControllerStatusReportedRequested(const NJointControllerPtr& nJointCtrl);
-        void UpdateNJointControllerStatusReported(const NJointControllerPtr& nJointCtrl);
-        void SetNJointControllerRequested(const NJointControllerPtr& nJointCtrl, bool requested);
-
-        void DeactivateNJointControllerPublishing(
-            const NJointControllerPtr& nJointCtrl,
-            const DebugDrawerInterfacePrx& draw,
-            const DebugObserverInterfacePrx& observer);
-    };
-
     /**
      * @brief The RobotUnit class manages a robot and its controllers.
      *
      * The \ref RobotUnit manages \ref NJointController and \ref JointController for a robot.
      * Controllers are executed in a control thread.
+     *
+     * \section Controllers
+     *
+     * \subsection RobotUnitCtrlsJoint Joint Controller
+     *
+     * \subsection RobotUnitCtrlsNJoint Multi Joint Controller
+     *
+     * \subsection RobotUnitControlModes Control Modes
+     * \subsubsection RobotUnitCtrlModesJointCtrl Control Modes of JointControlers
+     * \subsubsection RobotUnitCtrlModesHWCtrl Hardware Control Modes of JointControlers
+     * \subsubsection RobotUnitCtrlModeGroups Device Groups of Control Modes
+     *
      * \section Units
      * Units are created on an as needed basis.
      * (e.g. If there is a platform, a \ref PlatformSubUnit is created)
@@ -325,6 +84,7 @@ namespace armarx
      *  - \ref PlatformSubUnit
      *  - \ref ForceTorqueSubUnit
      *
+     * \section Publishing
      * \section RtLogging
      * Since the control thread (Section \ref softrt) should adhere soft rt properties,
      * no function executed in it is allowed to block.
@@ -340,7 +100,7 @@ namespace armarx
      *  - \ref ARMARX_RT_LOGF_ERROR
      *  - \ref ARMARX_RT_LOGF_FATAL
      *
-     * \warning These functions must only be called in the control thread after calling armarx::RobotUnit::initRTThread
+     * \warning These functions must only be called in the control thread after calling armarx::RobotUnit::finishControlThreadInitialization
      *
      * These macros work similar to printf and write their content to the corresponding
      * armarx logging stream.
@@ -406,520 +166,26 @@ namespace armarx
      */
     class RobotUnit :
         virtual public RobotUnitInterface,
-        virtual public Component,
-        virtual public NJointControllerDescriptionProviderInterface,
-        virtual private RobotUnitNJointControllerAccess
+        virtual public RobotUnitModule::Units,
+        virtual public RobotUnitModule::Logging,
+        virtual public RobotUnitModule::Devices,
+        virtual public RobotUnitModule::Publisher,
+        virtual public RobotUnitModule::RobotData,
+        virtual public RobotUnitModule::Management,
+        virtual public RobotUnitModule::ControlThread,
+        virtual public RobotUnitModule::SelfCollisionChecker,
+        virtual public RobotUnitModule::ControllerManagement,
+        virtual public RobotUnitModule::ControlThreadDataBuffer
     {
-    protected:
-        using PublisherTaskT = SimplePeriodicTask<std::function<void(void)>>;
-        using RTLoggingTaskT = SimplePeriodicTask<std::function<void(void)>>;
     public:
-        using MutexType = std::recursive_mutex;
-        using GuardType = std::unique_lock<MutexType>;
-        using ClockT = std::chrono::high_resolution_clock;
-        using TimePointT = std::chrono::high_resolution_clock::time_point;
-        // //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// //
-        // data
-        // //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// //
-        //devices
-    private:
-        /**
-         * @brief ControlDevices added to this unit
-         * data may only be added during and only be used after State::InitializingDevices
-         */
-        KeyValueVector<std::string, ControlDevicePtr> controlDevices;
-        /**
-         * @brief SensorDevices added to this unit
-         * data may only be added during and only be used after State::InitializingDevices
-         */
-        KeyValueVector<std::string, SensorDevicePtr > sensorDevices;
-
-        /// @brief const pointer to all ControlDevices (passed to GenerateConfigDescription of a NJointController)
-        std::map<std::string, ConstControlDevicePtr> controlDevicesConstPtr;
-        /// @brief const pointer to all SensorDevices (passed to GenerateConfigDescription of a NJointController)
-        std::map<std::string, ConstSensorDevicePtr> sensorDevicesConstPtr;
-
-        /// @brief a pointer to the RTThreadTimingsSensorDevice used to meassure timings in the rt loop
-        RTThreadTimingsSensorDevicePtr rtThreadTimingsSensorDevice;
-        /// @brief The device name of rtThreadTimingsSensorDevice
-        static const std::string rtThreadTimingsSensorDeviceName;
-        //[triple] buffers
-    private:
-        /// @brief Controllers the RT thread is supposed to activate (direction nonRT -> RT) (some NJoint controllers may be null)
-        /// data may only be used after State::InitializingDevices
-        /// all NJointController have to be sorted by id (null controllers are at the end)
-        WriteBufferedTripleBuffer<JointAndNJointControllers> controllersRequested;
-        /// @brief Controllers the RT thread is currently running (direction RT -> nonRT) (some NJoint controllers may be null)
-        /// data may only be used after State::InitializingDevices
-        /// all NJointController are sorted by id (null controllers may be anywhere)
-        WriteBufferedTripleBuffer<JointAndNJointControllers> controllersActivated;
-        /// @brief Transfers Data  (current sensor values and control targets) from the control thread to other threads (direction RT -> nonRT)
-        /// \warning DO NOT ACCESS EXCEPT YOU KNOW WHAT YOU ARE DOING!
-        ControlThreadOutputBuffer controlThreadOutputBuffer;
-        //(instantiating) NJoint controllers
-    private:
-        /// data may only be used after State::InitializingDevices
-        std::thread::id initNJointThreadId;
-        /// data may only be used after State::InitializingDevices
-        std::map<std::string, const JointController*> initNJointControllerUsedJointController;
-        /// @brief Holds all currently loaded NJoint controllers (index: [instancename])(May not be accessed in rt.)
-        std::map<std::string, NJointControllerPtr> nJointControllers;
-        /// @brief These controllers will be deleted in the next iteration of publish
-        std::map<std::string, NJointControllerPtr> nJointControllersToBeDeleted;
-        /// @brief the id of the next NJointController instance that is created
-        std::size_t nJointControllerNextId {0};
-
-        //listeners
-    private:
-        std::string robotUnitListenerTopicName;
-        RobotUnitListenerPrx listenerPrx;
-        DebugDrawerInterfacePrx debugDrawerPrx;
-
-        //publishing
-    private:
-        std::uint64_t publishIterationCount {0};
-
-        IceUtil::Time publishNewSensorDataTime;
-        PublisherTaskT::pointer_type publisherTask;
-        std::set<std::string> lastReportedClasses;
-
-        std::atomic_bool ObserverPublishSensorValues;
-        std::atomic_bool ObserverPublishControlTargets;
-        std::atomic<std::uint64_t> debugObserverSkipIterations;
-
-        std::chrono::microseconds lastRobotUnitObserverFlush;
-        std::chrono::microseconds lastPublishLoop;
-        DebugObserverInterfacePrx debugObserverPrx;
-        RobotUnitObserverPtr robotUnitObs;
-
-        ManagedIceObjectPtr tcpControllerSubUnit;
-        ManagedIceObjectPtr trajectoryControllerSubUnit;
-
-        //rt logging
-    private:
-        struct RtLogging
+        static RobotUnit& Instance()
         {
-            RtLogging(RobotUnit* ru): ru {ru} {}
-            struct Entry
-            {
-                std::atomic_bool stopLogging {false};
-                std::vector<std::vector<std::vector<char>>> loggedControlDeviceValues;
-                std::vector<std::vector<char>> loggedSensorDeviceValues;
-                std::ofstream stream;
-                std::string filename;
-                std::string marker;
-            };
-            mutable std::mutex mutex;
-            std::map<std::string, std::shared_ptr<Entry>> entries;
-            bool enabled {false};
-            std::vector<std::vector<std::vector<std::string>>> controlDeviceValueLoggingNames;
-            std::vector<std::vector<            std::string >> sensorDeviceValueLoggingNames;
-
-            RobotUnit* const ru;
-            RTLoggingTaskT::pointer_type task;
-
-            RemoteReferenceCounterBasePtr defaultLogHandle;
-
-            std::deque<detail::ControlThreadOutputBufferEntry> backlog;
-            IceUtil::Time keepBacklogFor;
-
-            std::size_t loggingTaskTimestep {0};
-
-            Ice::Int rtThreadId {0};
-            void doLogging();
-        };
-        RtLogging rtLogging;
-
-        //other
-    private:
-        /// @brief The RobotUnit's state
-        std::atomic<RobotUnitState> state {RobotUnitState::PreComponentInitialization};
-        /// @brief holds all units managed by the RobotUnit
-        std::vector<ManagedIceObjectPtr> units;
-        /// @brief holds a copy of all units managed by the RobotUnit derived from RobotUnitSubUnit
-        /// this is done to prevent casting
-        std::vector<RobotUnitSubUnitPtr> subUnits;
-        std::thread::id rtThreadId;
-        mutable MutexType dataMutex;
-        static const std::set<RobotUnitState> devicesReadyStates;
-
-        std::atomic_bool emergencyStop {false};
-        std::atomic_bool rtIsInEmergencyStop {false};
-        EmergencyStopMasterInterfacePtr emergencyStopMaster;
-
-        struct ControlDeviceHardwareControlModeGroups
-        {
-            /// @brief contains a vector per group.
-            /// Each vector contains the names of devices in this group.
-            std::vector<std::set<std::string>> groups;
-            /// @brief contains a vector per group.
-            /// Each vector contains the indices of devices in this group.
-            std::vector<std::vector<std::size_t>> deviceIndices;
-            /// @brief contains the names of all devices in any group
-            std::set<std::string> groupsMerged;
-            /// @brief contains the group index for each device (or the sentinel)
-            std::vector<std::size_t> groupIndices;
-        };
-        ControlDeviceHardwareControlModeGroups ctrlModeGroups;
-
-        struct SelfCollisionAvoidanceData
-        {
-            VirtualRobot::RobotPtr robot;
-            std::map<std::string, VirtualRobot::SceneObjectSetPtr> collisionModels;
-            float minDistance {0}; // min allowed distance (mm) between each collision model
-            std::vector<std::pair<std::string, std::string>> modelPairs; // list of pairs of collision models that should be checked agaisnt each other
-        };
-
-        //robot
-    private:
-        boost::shared_ptr<VirtualRobot::Robot> robot;
-        std::string robotNodeSetName;
-        std::string robotProjectName;
-        std::string robotFileName;
-        std::string robotPlatformName;
-
-        VirtualRobot::RobotPtr rtRobot;
-        VirtualRobot::RobotNodeSetPtr rtRobotJointSet;
-        std::map<VirtualRobot::RobotNodePtr, const SensorValue1DoFActuatorPosition*> nodePositionSensorMap;
-
-        SelfCollisionAvoidanceData selfCollisionAvoidanceData;
-        PeriodicTask<RobotUnit>::pointer_type selfCollisionAvoidanceTask;
-        void startSelfCollisionAvoidance();
-        void stopSelfCollisionAvoidance();
-        void updateSelfCollisionAvoidance();
-
-        RobotSynchronizationPtr selfCollisionAvoidanceRobotSynchronization;
-
-        // //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// //
-        // util
-        // //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// //
-    protected:
-        template<class ExceptT = LogicError>
-        inline void throwIfStateIsNot(const std::set<RobotUnitState>& sinit, const std::string& fnc, bool onlyWarn = false) const;
-        template<class ExceptT = LogicError>
-        inline void throwIfStateIsNot(RobotUnitState s, const std::string& fnc, bool onlyWarn = false) const;
-        template<class ExceptT = LogicError>
-        inline void throwIfDevicesNotReady(const std::string& fnc) const;
-
-        template<class Cont>
-        static Ice::StringSeq GetNonNullNames(const Cont& c);
-
-        GuardType getGuard() const;
-        inline const KeyValueVector<std::string, SensorDevicePtr>& getSensorDevices() const;
-        inline const KeyValueVector<std::string, ControlDevicePtr>& getControlDevices() const;
-
-        void checkNJointControllerClassName(const std::string& className) const;
-
-        //time
-        static TimePointT Now();
-        static std::chrono::microseconds MicroToNow(TimePointT last);
-        static std::chrono::microseconds MicroNow();
-
-        // //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// //
-        // other
-        // //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// //
-    public:
-        RobotUnit(): rtLogging {this} {}
-        /// @see PropertyUser::createPropertyDefinitions()
-        armarx::PropertyDefinitionsPtr createPropertyDefinitions() override;
-        std::string getDefaultName() const override;
-
-        static constexpr std::size_t IndexSentinel();
-    public:
-        void icePropertiesUpdated(const std::set<std::string>& changedProperties) override;
-    protected:
-        virtual void onInitRobotUnit();
-        virtual void onConnectRobotUnit();
-        virtual void onDisconnectRobotUnit();
-        /// @brief called in RobotUnit::onExitComponent() before calling RobotUnit::finishRunning
-        virtual void onExitRobotUnit();
-        void onInitComponent()       final override;
-        void onConnectComponent()    final override;
-        void onDisconnectComponent() final override;
-        void onExitComponent()       final override;
-    private:
-        // //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// //
-        // TripleBuffer
-        // //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// //
-    protected:
-        //rt requested
-        bool rtRequestedControllersChanged() const;
-        const JointAndNJointControllers&       rtGetRequestedControllers()     const;
-        const std::vector<JointController*>& rtGetRequestedJointControllers() const;
-        const std::vector<NJointController*>& rtGetRequestedNJointControllers() const;
-        // rt activated
-        void rtWriteActivatedControllers();
-        JointAndNJointControllers&       rtGetActivatedControllers();
-        std::vector<JointController*>& rtGetActivatedJointControllers();
-        std::vector<NJointController*>& rtGetActivatedNJointControllers();
-        std::vector<std::size_t>&     rtGetActivatedJointToNJointControllerAssignement();
-        // rt sensor and control
-        //declaration further down
-        //void rtUpdateSensorAndControlBuffer(const IceUtil::Time& sensorValuesTimestamp, const IceUtil::Time& timeSinceLastIteration);
-
-        // non rt requested
-    private:
-        void writeRequestedControllers(JointAndNJointControllers&& setOfControllers);
-        const JointAndNJointControllers&       getRequestedControllers()     const;
-        const std::vector<JointController*>& getRequestedJointControllers() const;
-        const std::vector<NJointController*>& getRequestedNJointControllers() const;
-        // non rt activated
-    private:
-        bool activatedControllersChanged() const;
-        const JointAndNJointControllers&       getActivatedControllers()     const;
-        const std::vector<JointController*>& getActivatedJointControllers() const;
-        const std::vector<NJointController*>& getActivatedNJointControllers() const;
-        // non rt sensor and control
-    private:
-        bool sensorAndControlBufferChanged() const;
-        const SensorAndControl& getSensorAndControlBuffer() const;
-
-        // //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// //
-        // State: InitializingDevices
-        // //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// //
-    protected:
-        void addControlDevice(const ControlDevicePtr& cd);
-        void addSensorDevice(const SensorDevicePtr& sd);
-
-        virtual RTThreadTimingsSensorDevicePtr createRTThreadTimingSensorDevice() const;
-
-        void finishDeviceInitialization();
-
-        // //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// //
-        // State: InitializingUnits
-        // //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// //
-    protected:
-        virtual void initializeDefaultUnits();
-        virtual void initializeKinematicUnit();
-        virtual void initializePlatformUnit();
-        virtual void initializeForceTorqueUnit();
-        virtual void initializeInertialMeasurementUnit();
-        virtual void initializeTrajectoryControllerUnit();
-        virtual void initializeTcpControllerUnit();
-        void addUnit(ManagedIceObjectPtr unit);
-        void finishUnitInitialization();
-        // //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// //
-        // State: Running (RT)
-        // //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// //
-        virtual void initRTThread();
-
-        //switching helper (rt)
-        void rtDeactivateAssignedNJointControllerBecauseOfError(std::size_t ctrlDevIndex, bool writeActivatedControlers = true);
-        /**
-         * @brief Deactivates a NJointController and sets all used ControlDevices to EmergencyStop
-         * @param nJointCtrlIndex The NJointController to deactivate (index in controllersActivated)
-         * @param writeActivatedControlers Whether controllersActivated should be committed
-         */
-        void rtDeactivateNJointControllerBecauseOfError(std::size_t nJointCtrlIndex, bool writeActivatedControlers = true);
-        /**
-         * @brief Hook for deriving classes (called AFTER a NJointController is deactivated due to an error)
-         *
-         * This is useful when two Control devices can be controlled by different NJointControllers but either both or none
-         * have to be controlled.
-         *
-         * Since this hook is called after the controller with an error was deactivated an other call to
-         * \ref rtDeactivateAssignedNJointControllerBecauseOfError can't lead to a cyclic execution.
-         */
-        virtual void rtDeactivatedNJointControllerBecauseOfError(const NJointControllerPtr& /*nJointCtrl*/);
-
-        //run (these functions should be called in the control loop)
-        bool rtSwitchControllerSetup();
-        void rtRunNJointControllers(const IceUtil::Time& sensorValuesTimestamp, const IceUtil::Time& timeSinceLastIteration);
-        void rtHandleInvalidTargets();
-        /**
-         * @brief Runs Joint controllers and writes target values to ControlDevices
-         * @param sensorValuesTimestamp
-         * @param timeSinceLastIteration
-         */
-        void rtRunJointControllers(const IceUtil::Time& sensorValuesTimestamp, const IceUtil::Time& timeSinceLastIteration);
-        void rtReadSensorDeviceValues(const IceUtil::Time& sensorValuesTimestamp, const IceUtil::Time& timeSinceLastIteration);
-        //rtBusSendReceive call this robot specific function here
-        void rtUpdateSensorAndControlBuffer(const IceUtil::Time& sensorValuesTimestamp, const IceUtil::Time& timeSinceLastIteration);
-        void rtResetAllTargets();
-
-        RTThreadTimingsSensorDevice& rtGetRTThreadTimingsSensorDevice();
-
-        // //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// //
-        // State: InitializingUnits + Running (NON RT)
-        // //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// //
-    public:
-        //create NJoint controllers
-        ConstSensorDevicePtr  getSensorDevice(const std::string& sensorDeviceName) const override;
-        ConstControlDevicePtr getControlDevice(const std::string& deviceName) const override;
-        ControlTargetBase* getControlTarget(const std::string& deviceName, const std::string& controlMode) override;
-        NJointControllerInterfacePrx createNJointController(
-            const std::string& className, const std::string& instanceName,
-            const NJointControllerConfigPtr& config, const Ice::Current&) override;
-        NJointControllerInterfacePrx createNJointControllerFromVariantConfig(
-            const std::string& className, const std::string& instanceName,
-            const StringVariantBaseMap& variants, const Ice::Current&) override;
-        const NJointControllerPtr& createNJointController(
-            const std::string& className, const std::string& instanceName,
-            const NJointControllerConfigPtr& config, bool deletable, bool internal);
-        //deleting NJoint controllers
-        void deleteNJointController(const std::string& name, const Ice::Current& = GlobalIceCurrent) override;
-        void deleteNJointControllers(const Ice::StringSeq& names, const Ice::Current& = GlobalIceCurrent) override;
-        // //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// //
-        // State: Running (NON RT)
-        // //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// //
-    public:
-        //switching
-        void activateNJointController(const std::string& name, const Ice::Current& = GlobalIceCurrent) override;
-        void activateNJointControllers(const Ice::StringSeq& names, const Ice::Current& = GlobalIceCurrent) override;
-        void deactivateNJointController(const std::string& name, const Ice::Current& = GlobalIceCurrent) override;
-        void deactivateNJointControllers(const Ice::StringSeq& names, const Ice::Current& = GlobalIceCurrent) override;
-        void switchNJointControllerSetup(const Ice::StringSeq& newSetup, const Ice::Current& = GlobalIceCurrent) override;
-    private:
-        void setActivateControllersRequest(std::set<NJointControllerPtr, NJointController::IdComp>&& ctrls);
-        /**
-         * @brief This hook is called prior to writing the set of requested controllers.
-         * A deriving class can override this function to perform some additional checks
-         * (e.g. two controll devices may always need to have the same control mode, this can be checked here)
-         * If any check fails, throw an exception with a descriptive message.
-         * @param controllers The controllers to activate
-         */
-        virtual void checkSetOfControllersToActivate(const JointAndNJointControllers& /*controllers*/) const;
-        // publishing
-    protected:
-        virtual void publish(StringVariantBaseMap additionalMap = {}, StringVariantBaseMap timingMap = {});
-
-        //shutting down
-    protected:
-        ///@brief joint your thread in this hook. (used by RobotUnit::finishRunning())
-        virtual void joinRTThread() = 0;
-    private:
-        ///@brief delete all units (used by RobotUnit::finishRunning())
-        virtual void removeAllUnits();
-        void finishRunning();
-
-        // //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// //
-        // Lib loading
-        // //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// //
-    public:
-        bool loadLibFromPath(const std::string& path, const Ice::Current& = GlobalIceCurrent) override
-        {
-            return getArmarXManager()->loadLibFromPath(path);
-        }
-        bool loadLibFromPackage(const std::string& package, const std::string& lib, const Ice::Current& = GlobalIceCurrent) override
-        {
-            return getArmarXManager()->loadLibFromPackage(package, lib);
-        }
-
-        // //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// //
-        // querry data
-        // //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// //
-    public:
-        //NJoint
-        Ice::StringSeq getNJointControllerNames(const Ice::Current& = GlobalIceCurrent) const override;
-        Ice::StringSeq getRequestedNJointControllerNames(const Ice::Current& = GlobalIceCurrent) const override;
-        Ice::StringSeq getActivatedNJointControllerNames(const Ice::Current& = GlobalIceCurrent) const override;
-
-        NJointControllerInterfacePrx getNJointController(const std::string& name, const Ice::Current&) const override;
-        StringNJointControllerPrxDictionary getAllNJointControllers(const Ice::Current&) const override;
-        std::vector<NJointControllerPtr> getNJointControllersNotNull(const std::vector<std::string>& names) const;
-        const NJointControllerPtr& getNJointControllerNotNull(const std::string& name) const;
-
-        NJointControllerStatus getNJointControllerStatus(const std::string& name, const Ice::Current& = GlobalIceCurrent) const override;
-        NJointControllerStatusSeq getNJointControllerStatuses(const Ice::Current&) const override;
-
-        NJointControllerDescription getNJointControllerDescription(const std::string& name, const Ice::Current& = GlobalIceCurrent) const override;
-        NJointControllerDescriptionSeq getNJointControllerDescriptions(const Ice::Current&) const override;
-
-        NJointControllerDescriptionWithStatus getNJointControllerDescriptionWithStatus(
-            const std::string& name, const Ice::Current& = GlobalIceCurrent) const override;
-        NJointControllerDescriptionWithStatusSeq getNJointControllerDescriptionsWithStatuses(const Ice::Current&) const override;
-        //control devices
-        Ice::StringSeq getControlDeviceNames(const Ice::Current& = GlobalIceCurrent) const override;
-        ControlDeviceDescription getControlDeviceDescription(std::size_t cdidx) const;
-        ControlDeviceDescription getControlDeviceDescription(const std::string& name, const Ice::Current& = GlobalIceCurrent) const override;
-        ControlDeviceDescriptionSeq getControlDeviceDescriptions(const Ice::Current&) const override;
-        ControlDeviceStatus getControlDeviceStatus(std::size_t cdidx) const;
-        ControlDeviceStatus getControlDeviceStatus(const std::string& name, const Ice::Current& = GlobalIceCurrent) const override;
-        ControlDeviceStatusSeq getControlDeviceStatuses(const Ice::Current&) const override;
-
-        //sensor devices
-        Ice::StringSeq getSensorDeviceNames(const Ice::Current&) const override;
-        SensorDeviceDescription getSensorDeviceDescription(std::size_t cdidx) const;
-        SensorDeviceDescription getSensorDeviceDescription(const std::string& name, const Ice::Current& = GlobalIceCurrent) const override;
-        SensorDeviceDescriptionSeq getSensorDeviceDescriptions(const Ice::Current&) const override;
-        SensorDeviceStatus getSensorDeviceStatus(std::size_t idx) const;
-        SensorDeviceStatus getSensorDeviceStatus(const std::string& name, const Ice::Current& = GlobalIceCurrent) const override;
-        SensorDeviceStatusSeq getSensorDeviceStatuses(const Ice::Current&) const override;
-
-        //nJointController classes
-        Ice::StringSeq getNJointControllerClassNames(const Ice::Current& = GlobalIceCurrent) const override;
-        NJointControllerClassDescription getNJointControllerClassDescription(
-            const std::string& className, const Ice::Current& = GlobalIceCurrent) const override;
-        NJointControllerClassDescriptionSeq getNJointControllerClassDescriptions(const Ice::Current&) const override;
-
-        //units
-        Ice::ObjectProxySeq getUnits(const Ice::Current& = GlobalIceCurrent) const override;
-        Ice::ObjectPrx getUnit(const std::string& staticIceId, const Ice::Current&) const override;
-        const ManagedIceObjectPtr& getUnit(const std::string& staticIceId) const;
-        KinematicUnitInterfacePrx getKinematicUnit(const Ice::Current& = GlobalIceCurrent) const override;
-        ForceTorqueUnitInterfacePrx getForceTorqueUnit(const Ice::Current& = GlobalIceCurrent) const override;
-        InertialMeasurementUnitInterfacePrx getInertialMeasurementUnit(const Ice::Current& = GlobalIceCurrent) const override;
-        PlatformUnitInterfacePrx getPlatformUnit(const Ice::Current& = GlobalIceCurrent) const override;
-        //other ice functions
-        std::string getListenerTopicName(const Ice::Current& = GlobalIceCurrent) const override;
-        bool isRunning(const Ice::Current& = GlobalIceCurrent) const override
-        {
-            return getRobotUnitState() == RobotUnitState::Running;
+            return ModuleBase::Instance<RobotUnit>();
         }
-        //other local functions
-        const boost::shared_ptr<VirtualRobot::Robot>& getRobot() const;
-        std::string getRobotName() const;
-        const std::string& getRobotNodetSeName() const;
-        const std::string& getRobotProjectName() const;
-        const std::string& getRobotFileName() const;
-        const std::string& getRobotPlatformName() const;
-
-        std::size_t getNumberOfControlDevices() const;
-        std::size_t rtGetNumberOfControlDevices() const;
-
-        std::size_t getNumberOfSensorDevices() const;
-        std::size_t rtGetNumberOfSensorDevices() const;
-
-        const DebugDrawerInterfacePrx& getDebugDrawerProxy() const;
-        bool areDevicesReady() const;
-        RobotUnitState getRobotUnitState() const;
-        std::string getName() const override;
-
-        void setEmergencyStopState(EmergencyStopState state);
-
-        EmergencyStopState getEmergencyStopState() const;
-        const EmergencyStopMasterInterfacePtr& getEmergencyStopMaster() const
-        {
-            return emergencyStopMaster;
-        }
-
-        const SelfCollisionAvoidanceData& getSelfCollisionAvoidanceData() const;
-
-        const VirtualRobot::RobotPtr& getRtRobot() const;
-
-
-        virtual IceUtil::Time getControlThreadTargetPeriod() const = 0;
-
-    protected:
-        const RobotUnitListenerPrx& getListenerProxy() const;
-        void icePropertiesInitialized() override;
-
-        // RT-Logging
-    public:
-        bool isRtLoggingEnabled(const Ice::Current& = GlobalIceCurrent) const override
+        /// @see PropertyUser::createPropertyDefinitions()
+        armarx::PropertyDefinitionsPtr createPropertyDefinitions() override
         {
-            return rtLogging.enabled;
+            return PropertyDefinitionsPtr(new RobotUnitPropertyDefinitions(getConfigIdentifier()));
         }
-        RemoteReferenceCounterBasePtr startRtLogging(const std::string& formatString, const Ice::StringSeq& loggingNames, const Ice::Current& = GlobalIceCurrent) override;
-        RemoteReferenceCounterBasePtr startRtLoggingWithAliasNames(const std::string& formatString, const StringStringDictionary& aliasNames, const Ice::Current&   = GlobalIceCurrent) override;
-        void addMarkerToRtLog(const RemoteReferenceCounterBasePtr& token, const std::string& marker, const Ice::Current& = GlobalIceCurrent) override;
-        void stopRtLogging(const RemoteReferenceCounterBasePtr& token, const Ice::Current& = GlobalIceCurrent) override;
-
-        Ice::StringSeq getLoggingNames(const Ice::Current& = GlobalIceCurrent) const override;
-
-        void writeRecentIterationsToFile(const std::string& formatString, const Ice::Current& = GlobalIceCurrent) const override;
-
     };
 }
-
-#include "RobotUnit.ipp"
diff --git a/source/RobotAPI/components/units/RobotUnit/RobotUnit.ipp b/source/RobotAPI/components/units/RobotUnit/RobotUnit.ipp
deleted file mode 100644
index df0a0e814d6c1de57f826e7d5624bc5e7ecadca2..0000000000000000000000000000000000000000
--- a/source/RobotAPI/components/units/RobotUnit/RobotUnit.ipp
+++ /dev/null
@@ -1,398 +0,0 @@
-/*
- * This file is part of ArmarX.
- *
- * 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    RobotAPI::RobotUnit
- * @author     Raphael ( ufdrv at student dot kit dot edu )
- * @date       2017
- * @copyright  http://www.gnu.org/licenses/gpl-2.0.txt
- *             GNU General Public License
- */
-
-#pragma once
-
-#include "RobotUnit.h"
-
-//inline functions
-namespace armarx
-{
-    //RobotUnit
-    inline const KeyValueVector<std::string, SensorDevicePtr>& RobotUnit::getSensorDevices() const
-    {
-        return sensorDevices;
-    }
-
-    inline const KeyValueVector<std::string, ControlDevicePtr>& RobotUnit::getControlDevices() const
-    {
-        return controlDevices;
-    }
-
-    inline RobotUnit::TimePointT RobotUnit::Now()
-    {
-        return ClockT::now();
-    }
-
-    inline std::chrono::microseconds RobotUnit::MicroToNow(RobotUnit::TimePointT last)
-    {
-        return std::chrono::duration_cast<std::chrono::microseconds>(Now() - last);
-    }
-
-    inline std::chrono::microseconds RobotUnit::MicroNow()
-    {
-        return std::chrono::duration_cast<std::chrono::microseconds>(std::chrono::high_resolution_clock::now().time_since_epoch());
-    }
-
-    inline PropertyDefinitionsPtr RobotUnit::createPropertyDefinitions()
-    {
-        return PropertyDefinitionsPtr(new RobotUnitPropertyDefinitions(getConfigIdentifier()));
-    }
-
-    inline std::string RobotUnit::getDefaultName() const
-    {
-        return "RobotUnit";
-    }
-
-    inline constexpr std::size_t RobotUnit::IndexSentinel()
-    {
-        return JointAndNJointControllers::Sentinel();
-    }
-
-    inline void RobotUnit::onInitRobotUnit()       {}
-
-    inline void RobotUnit::onConnectRobotUnit()    {}
-
-    inline void RobotUnit::onDisconnectRobotUnit() {}
-
-    inline void RobotUnit::onExitRobotUnit()       {}
-
-    inline bool RobotUnit::rtRequestedControllersChanged() const
-    {
-        return controllersRequested.updateReadBuffer();
-    }
-
-    inline const JointAndNJointControllers& RobotUnit::rtGetRequestedControllers() const
-    {
-        return controllersRequested.getReadBuffer();
-    }
-
-    inline const std::vector<JointController*>& RobotUnit::rtGetRequestedJointControllers() const
-    {
-        return rtGetRequestedControllers().jointControllers;
-    }
-
-    inline const std::vector<NJointController*>& RobotUnit::rtGetRequestedNJointControllers() const
-    {
-        return rtGetRequestedControllers().nJointControllers;
-    }
-
-    inline void RobotUnit::rtWriteActivatedControllers()
-    {
-        controllersActivated.commitWrite();
-    }
-
-    inline JointAndNJointControllers& RobotUnit::rtGetActivatedControllers()
-    {
-        return controllersActivated.getWriteBuffer();
-    }
-
-    inline std::vector<JointController*>& RobotUnit::rtGetActivatedJointControllers()
-    {
-        return rtGetActivatedControllers().jointControllers;
-    }
-
-    inline std::vector<NJointController*>& RobotUnit::rtGetActivatedNJointControllers()
-    {
-        return rtGetActivatedControllers().nJointControllers;
-    }
-
-    inline std::vector<std::size_t>& RobotUnit::rtGetActivatedJointToNJointControllerAssignement()
-    {
-        return rtGetActivatedControllers().jointToNJointControllerAssignement;
-    }
-
-    inline RTThreadTimingsSensorDevicePtr RobotUnit::createRTThreadTimingSensorDevice() const
-    {
-        return std::make_shared<RTThreadTimingsSensorDeviceImpl<>>(rtThreadTimingsSensorDeviceName);
-    }
-
-    inline void RobotUnit::rtDeactivatedNJointControllerBecauseOfError(const NJointControllerPtr&) {}
-
-    inline RTThreadTimingsSensorDevice& RobotUnit::rtGetRTThreadTimingsSensorDevice()
-    {
-        return *rtThreadTimingsSensorDevice;
-    }
-
-    inline NJointControllerInterfacePrx RobotUnit::createNJointController(
-        const std::string& className, const std::string& instanceName,
-        const NJointControllerConfigPtr& config, const Ice::Current&
-    )
-    {
-        //no lock required
-        return NJointControllerInterfacePrx::uncheckedCast(
-                   createNJointController(className, instanceName, config, true, false)->getProxy(-1, true));
-    }
-
-    inline void RobotUnit::deleteNJointController(const std::string& name, const Ice::Current&)
-    {
-        deleteNJointControllers({name});
-    }
-
-    inline void RobotUnit::activateNJointController(const std::string& name, const Ice::Current&)
-    {
-        activateNJointControllers({name});
-    }
-
-    inline void RobotUnit::deactivateNJointController(const std::string& name, const Ice::Current&)
-    {
-        deactivateNJointControllers(Ice::StringSeq {name});
-    }
-
-    inline void RobotUnit::checkSetOfControllersToActivate(const JointAndNJointControllers&) const {}
-
-    inline Ice::StringSeq RobotUnit::getNJointControllerNames(const Ice::Current&) const
-    {
-        auto guard = getGuard();
-        return getMapKeys(nJointControllers);
-    }
-
-    inline Ice::StringSeq RobotUnit::getRequestedNJointControllerNames(const Ice::Current&) const
-    {
-        auto guard = getGuard();
-        return GetNonNullNames(getRequestedNJointControllers());
-    }
-
-    inline Ice::StringSeq RobotUnit::getActivatedNJointControllerNames(const Ice::Current&) const
-    {
-        auto guard = getGuard();
-        return GetNonNullNames(getActivatedNJointControllers());
-    }
-
-    inline Ice::StringSeq RobotUnit::getNJointControllerClassNames(const Ice::Current&) const
-    {
-        return NJointControllerRegistry::getKeys();
-    }
-
-    inline KinematicUnitInterfacePrx RobotUnit::getKinematicUnit(const Ice::Current&) const
-    {
-        //no lock required
-        return KinematicUnitInterfacePrx::uncheckedCast(getUnit(KinematicUnitInterface::ice_staticId(), GlobalIceCurrent));
-    }
-
-    inline ForceTorqueUnitInterfacePrx RobotUnit::getForceTorqueUnit(const Ice::Current&) const
-    {
-        //no lock required
-        return ForceTorqueUnitInterfacePrx::uncheckedCast(getUnit(ForceTorqueUnitInterface::ice_staticId(), GlobalIceCurrent));
-    }
-
-    inline InertialMeasurementUnitInterfacePrx RobotUnit::getInertialMeasurementUnit(const Ice::Current&) const
-    {
-        //no lock required
-        return InertialMeasurementUnitInterfacePrx::uncheckedCast(
-                   getUnit(InertialMeasurementUnitInterface::ice_staticId(), GlobalIceCurrent));
-    }
-
-    inline PlatformUnitInterfacePrx RobotUnit::getPlatformUnit(const Ice::Current&) const
-    {
-        //no lock required
-        return PlatformUnitInterfacePrx::uncheckedCast(getUnit(PlatformUnitInterface::ice_staticId(), GlobalIceCurrent));
-    }
-
-    inline std::string RobotUnit::getListenerTopicName(const Ice::Current&) const
-    {
-        auto guard = getGuard();
-        return robotUnitListenerTopicName;
-    }
-
-    inline const std::string& RobotUnit::getRobotNodetSeName() const
-    {
-        return robotNodeSetName;
-    }
-
-    inline const std::string& RobotUnit::getRobotProjectName() const
-    {
-        return robotProjectName;
-    }
-
-    inline const std::string& RobotUnit::getRobotFileName() const
-    {
-        return robotFileName;
-    }
-
-    inline const std::string& RobotUnit::getRobotPlatformName() const
-    {
-        return robotPlatformName;
-    }
-
-    inline std::size_t RobotUnit::rtGetNumberOfControlDevices() const
-    {
-        return controlDevices.size();
-    }
-
-    inline std::size_t RobotUnit::rtGetNumberOfSensorDevices() const
-    {
-        return sensorDevices.size();
-    }
-
-    inline bool RobotUnit::areDevicesReady() const
-    {
-        return devicesReadyStates.count(state);
-    }
-
-    inline RobotUnitState RobotUnit::getRobotUnitState() const
-    {
-        return state;
-    }
-
-    inline std::string RobotUnit::getName() const
-    {
-        return Component::getName();
-    }
-
-    inline void RobotUnit::setEmergencyStopState(EmergencyStopState state)
-    {
-        emergencyStop = (state == EmergencyStopState::eEmergencyStopActive);
-    }
-
-    inline EmergencyStopState RobotUnit::getEmergencyStopState() const
-    {
-        return emergencyStop ? EmergencyStopState::eEmergencyStopActive :
-               EmergencyStopState::eEmergencyStopInactive;
-    }
-
-    template<class ExceptT>
-    inline void RobotUnit::throwIfStateIsNot(const std::set<RobotUnitState>& sinit, const std::string& fnc, bool onlyWarn) const
-    {
-        std::set<RobotUnitState> sset {sinit};
-        if (! sset.count(state))
-        {
-            std::stringstream ss;
-            ss << fnc << ": Can't be called if state is not in {";
-            bool fst = true;
-            for (RobotUnitState st : sset)
-            {
-                if (!fst)
-                {
-                    ss << ", ";
-                }
-                ss << st;
-                fst = false;
-            }
-            ss << "} (current state " << getRobotUnitState() << ")";
-            ARMARX_ERROR << ss.str();
-            if (!onlyWarn)
-            {
-                throw ExceptT {ss.str()};
-            }
-        }
-    }
-
-    template<class ExceptT>
-    inline void RobotUnit::throwIfStateIsNot(RobotUnitState s, const std::string& fnc, bool onlyWarn) const
-    {
-        throwIfStateIsNot<ExceptT>(std::set<RobotUnitState> {s}, fnc, onlyWarn);
-    }
-
-    template<class ExceptT>
-    inline void RobotUnit::throwIfDevicesNotReady(const std::string& fnc) const
-    {
-        throwIfStateIsNot<ExceptT>(devicesReadyStates, fnc);
-    }
-
-    template<class Cont>
-    inline Ice::StringSeq RobotUnit::GetNonNullNames(const Cont& c)
-    {
-        Ice::StringSeq result;
-        result.reserve(c.size());
-        for (const auto& e : c)
-        {
-            if (e)
-            {
-                result.emplace_back(e->getName());
-            }
-        }
-        return result;
-    }
-
-    //RobotUnitNJointControllerAccess
-    inline void RobotUnitNJointControllerAccess::RtSetNJointControllerActivatedStatus(const NJointControllerPtr& nJointCtrl)
-    {
-        nJointCtrl->rtActivateController();
-    }
-
-    inline void RobotUnitNJointControllerAccess::RtSetNJointControllerDeactivatedStatus(const NJointControllerPtr& nJointCtrl)
-    {
-        nJointCtrl->rtDeactivateController();
-    }
-
-    inline void RobotUnitNJointControllerAccess::RtSetNJointControllerDeactivatedBecauseOfErrorStatus(const NJointControllerPtr& nJointCtrl)
-    {
-        nJointCtrl->rtDeactivateControllerBecauseOfError();
-    }
-
-    inline void RobotUnitNJointControllerAccess::InitNJointControler(
-        const NJointControllerPtr& nJointCtrl,
-        RobotUnit* ru,
-        std::size_t ctrlId,
-        std::map<std::string, const JointController*> ctrlDeviceUsedJointController,
-        std::vector<char> ctrlDeviceUsedBitmap,
-        std::vector<std::size_t> ctrlDeviceUsedIndices,
-        bool deletable, bool internal
-    ) noexcept
-    {
-        nJointCtrl->robotUnitInit(
-            ru, ctrlId, std::move(ctrlDeviceUsedJointController), std::move(ctrlDeviceUsedBitmap),
-            std::move(ctrlDeviceUsedIndices), deletable, internal
-        );
-    }
-
-    inline void RobotUnitNJointControllerAccess::PublishNJointController(
-        const NJointControllerPtr& nJointCtrl,
-        const SensorAndControl& sac,
-        const DebugDrawerInterfacePrx& draw,
-        const DebugObserverInterfacePrx& observer
-    )
-    {
-        nJointCtrl ->publish(sac, draw, observer);
-    }
-
-    inline bool RobotUnitNJointControllerAccess::GetNJointControllerStatusReportedActive(const NJointControllerPtr& nJointCtrl)
-    {
-        return nJointCtrl->statusReportedActive;
-    }
-
-    inline bool RobotUnitNJointControllerAccess::GetNJointControllerStatusReportedRequested(const NJointControllerPtr& nJointCtrl)
-    {
-        return nJointCtrl->statusReportedRequested;
-    }
-
-    inline void RobotUnitNJointControllerAccess::UpdateNJointControllerStatusReported(const NJointControllerPtr& nJointCtrl)
-    {
-        nJointCtrl->statusReportedActive = nJointCtrl->isActive.load();
-        nJointCtrl->statusReportedRequested = nJointCtrl->isRequested.load();
-    }
-
-    inline void RobotUnitNJointControllerAccess::SetNJointControllerRequested(const NJointControllerPtr& nJointCtrl, bool requested)
-    {
-        nJointCtrl->isRequested = requested;
-    }
-
-    inline void RobotUnitNJointControllerAccess::DeactivateNJointControllerPublishing(
-        const NJointControllerPtr& nJointCtrl,
-        const DebugDrawerInterfacePrx& draw,
-        const DebugObserverInterfacePrx& observer
-    )
-    {
-        nJointCtrl->deactivatePublish(draw, observer);
-    }
-}
diff --git a/source/RobotAPI/components/units/RobotUnit/RobotUnitModules/RobotUnitModuleBase.cpp b/source/RobotAPI/components/units/RobotUnit/RobotUnitModules/RobotUnitModuleBase.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..48fb28cd78bff5150b73cd683847500305b8ba18
--- /dev/null
+++ b/source/RobotAPI/components/units/RobotUnit/RobotUnitModules/RobotUnitModuleBase.cpp
@@ -0,0 +1,480 @@
+/*
+ * This file is part of ArmarX.
+ *
+ * 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    RobotAPI::ArmarXObjects::RobotUnit
+ * @author     Raphael Grimm ( raphael dot grimm at kit dot edu )
+ * @date       2018
+ * @copyright  http://www.gnu.org/licenses/gpl-2.0.txt
+ *             GNU General Public License
+ */
+
+
+#include <ArmarXCore/core/exceptions/local/ExpressionException.h>
+#include <ArmarXCore/core/util/Preprocessor.h>
+
+#include "../NJointControllers/NJointController.h"
+#include "RobotUnitModuleBase.h"
+#include "RobotUnitModules.h"
+
+namespace armarx
+{
+
+std::string to_string(RobotUnitState s)
+{
+    switch (s)
+    {
+    case armarx::RobotUnitState::InitializingComponent:
+        return "RobotUnitState::InitializingComponent";
+    case armarx::RobotUnitState::InitializingDevices:
+        return "RobotUnitState::InitializingDevices";
+    case armarx::RobotUnitState::InitializingUnits:
+        return "RobotUnitState::InitializingUnits";
+    case armarx::RobotUnitState::InitializingControlThread:
+        return "RobotUnitState::InitializingControlThread";
+    case armarx::RobotUnitState::Running:
+        return "RobotUnitState::Running";
+    case armarx::RobotUnitState::Exiting:
+        return "RobotUnitState::Exiting";
+    }
+    throw std::invalid_argument
+    {
+        "Unknown state " + to_string(static_cast<std::size_t>(s)) +
+        "\nStacktrace\n" + LogSender::CreateBackTrace()
+    };
+}
+namespace RobotUnitModule
+{
+
+    // //////////////////////////////////////////////////////////////////////////// //
+    // /////////////////////////// call for each module /////////////////////////// //
+    // //////////////////////////////////////////////////////////////////////////// //
+    #define cast_to_and_call(Type, fn, rethrow)                                             \
+        try                                                                                 \
+        {                                                                                   \
+            dynamic_cast<Type*>(this)->Type::fn;                                            \
+        }                                                                                   \
+        catch (Ice::Exception& e)                                                           \
+        {                                                                                   \
+            ARMARX_ERROR << "exception in " << #Type "::" #fn << "!\nwhat:\n"               \
+                         << e.what()                                                        \
+                         << "\n\tname: " << e.ice_name()                                    \
+                         << "\n\tfile: " << e.ice_file()                                    \
+                         << "\n\tline: " << e.ice_line()                                    \
+                         << "\n\tstack: " << e.ice_stackTrace();                            \
+            if(rethrow) { throw;}                                                           \
+        }                                                                                   \
+        catch (std::exception& e)                                                           \
+        {                                                                                   \
+            ARMARX_ERROR << "exception in " << #Type "::" #fn << "!\nwhat:\n" << e.what();  \
+            if(rethrow) { throw;}                                                           \
+        }                                                                                   \
+        catch (...)                                                                         \
+        {                                                                                   \
+            ARMARX_ERROR << "exception in " << #Type "::" #fn << "!";                       \
+            if(rethrow) { throw;}                                                           \
+        }
+
+    #define for_each_module_apply(r, data, elem) data(elem)
+    #define for_each_module(macro) \
+        BOOST_PP_SEQ_FOR_EACH(for_each_module_apply, macro, BOOST_PP_VARIADIC_TO_SEQ(RobotUnitModules))
+
+    #define check_base(Type)                                            \
+        static_assert(                                                  \
+            std::is_base_of<ModuleBase, Type>::value,                   \
+            "The RobotUnitModule '" #Type "' has to derived ModuleBase" \
+        );
+    for_each_module(check_base)
+    #undef check_base
+
+    void ModuleBase::checkDerivedClasses() const
+    {
+        #define check_deriving(Type)                                        \
+            ARMARX_CHECK_NOT_NULL_W_HINT(                                   \
+                dynamic_cast<const Type*>(this),                            \
+                "This class does not derive from " << GetTypeString<Type>() \
+            );
+        for_each_module(check_deriving)
+        #undef check_deriving
+    }
+    // //////////////////////////////////////////////////////////////////////////// //
+    // ManagedIceObject life cycle
+    void ModuleBase::onInitComponent()
+    {
+        checkDerivedClasses();
+        auto guard = getGuard();
+        throwIfStateIsNot(RobotUnitState::InitializingComponent, __FUNCTION__);
+
+        #define call_module_hook(Type) cast_to_and_call(::armarx::RobotUnitModule::Type, _preOnInitRobotUnit(), true)
+        for_each_module(call_module_hook)
+        #undef call_module_hook
+
+        onInitRobotUnit();
+
+        #define call_module_hook(Type) cast_to_and_call(::armarx::RobotUnitModule::Type, _postOnInitRobotUnit(), true)
+        for_each_module(call_module_hook)
+        #undef call_module_hook
+
+        finishComponentInitialization();
+
+    }
+
+    void ModuleBase::onConnectComponent()
+    {
+        checkDerivedClasses();
+        auto guard = getGuard();
+
+        #define call_module_hook(Type) cast_to_and_call(::armarx::RobotUnitModule::Type, _preOnConnectRobotUnit(), true)
+        for_each_module(call_module_hook)
+        #undef call_module_hook
+
+        onConnectRobotUnit();
+
+        #define call_module_hook(Type) cast_to_and_call(::armarx::RobotUnitModule::Type, _postOnConnectRobotUnit(), true)
+        for_each_module(call_module_hook)
+        #undef call_module_hook
+    }
+    void ModuleBase::onDisconnectComponent()
+    {
+        checkDerivedClasses();
+        auto guard = getGuard();
+
+        #define call_module_hook(Type) cast_to_and_call(::armarx::RobotUnitModule::Type, _preOnDisconnectRobotUnit(), true)
+        for_each_module(call_module_hook)
+        #undef call_module_hook
+
+        onDisconnectRobotUnit();
+
+        #define call_module_hook(Type) cast_to_and_call(::armarx::RobotUnitModule::Type, _postOnDisconnectRobotUnit(), true)
+        for_each_module(call_module_hook)
+        #undef call_module_hook
+    }
+
+    void ModuleBase::onExitComponent()
+    {
+        checkDerivedClasses();
+        auto guard = getGuard();
+
+        finishRunning();
+
+        #define call_module_hook(Type) cast_to_and_call(::armarx::RobotUnitModule::Type, _preOnExitRobotUnit(), false)
+        for_each_module(call_module_hook)
+        #undef call_module_hook
+
+        onExitRobotUnit();
+
+        #define call_module_hook(Type) cast_to_and_call(::armarx::RobotUnitModule::Type, _postOnExitRobotUnit(), false)
+        for_each_module(call_module_hook)
+        #undef call_module_hook
+    }
+    // //////////////////////////////////////////////////////////////////////////// //
+    //  other ManagedIceObject / Component methods
+    void ModuleBase::icePropertiesUpdated(const std::set<std::string>& changedProperties)
+    {
+        #define call_module_hook(Type) cast_to_and_call(::armarx::RobotUnitModule::Type, _icePropertiesUpdated(changedProperties), true)
+        for_each_module(call_module_hook)
+        #undef call_module_hook
+    }
+    void ModuleBase::icePropertiesInitialized()
+    {
+        #define call_module_hook(Type) cast_to_and_call(::armarx::RobotUnitModule::Type, _icePropertiesInitialized(), true)
+        for_each_module(call_module_hook)
+        #undef call_module_hook
+    }
+    // //////////////////////////////////////////////////////////////////////////// //
+    // RobotUnit life cycle
+    void ModuleBase::finishComponentInitialization()
+    {
+        checkDerivedClasses();
+        auto guard = getGuard();
+        throwIfStateIsNot(RobotUnitState::InitializingComponent, __FUNCTION__);
+
+        #define call_module_hook(Type) cast_to_and_call(::armarx::RobotUnitModule::Type, _preFinishComponentInitialization(), true)
+        for_each_module(call_module_hook)
+        #undef call_module_hook
+
+        setRobotUnitState(RobotUnitState::InitializingDevices);
+
+        #define call_module_hook(Type) cast_to_and_call(::armarx::RobotUnitModule::Type, _postFinishComponentInitialization(), true)
+        for_each_module(call_module_hook)
+        #undef call_module_hook
+    }
+    void ModuleBase::finishDeviceInitialization()
+    {
+        checkDerivedClasses();
+        auto guard = getGuard();
+        throwIfStateIsNot(RobotUnitState::InitializingDevices, __FUNCTION__);
+
+        #define call_module_hook(Type) cast_to_and_call(::armarx::RobotUnitModule::Type, _preFinishDeviceInitialization(), true)
+        for_each_module(call_module_hook)
+        #undef call_module_hook
+
+        setRobotUnitState(RobotUnitState::InitializingUnits);
+
+        #define call_module_hook(Type) cast_to_and_call(::armarx::RobotUnitModule::Type, _postFinishDeviceInitialization(), true)
+        for_each_module(call_module_hook)
+        #undef call_module_hook
+    }
+
+    void ModuleBase::finishUnitInitialization()
+    {
+        checkDerivedClasses();
+        auto guard = getGuard();
+        throwIfStateIsNot(RobotUnitState::InitializingUnits, __FUNCTION__);
+
+        #define call_module_hook(Type) cast_to_and_call(::armarx::RobotUnitModule::Type, _preFinishUnitInitialization(), true)
+        for_each_module(call_module_hook)
+        #undef call_module_hook
+
+        setRobotUnitState(RobotUnitState::InitializingControlThread);
+
+        #define call_module_hook(Type) cast_to_and_call(::armarx::RobotUnitModule::Type, _postFinishUnitInitialization(), true)
+        for_each_module(call_module_hook)
+        #undef call_module_hook
+    }
+
+    void ModuleBase::finishControlThreadInitialization()
+    {
+        checkDerivedClasses();
+        auto guard = getGuard();
+        throwIfStateIsNot(RobotUnitState::InitializingControlThread, __FUNCTION__);
+
+        #define call_module_hook(Type) cast_to_and_call(::armarx::RobotUnitModule::Type, _preFinishControlThreadInitialization(), true)
+        for_each_module(call_module_hook)
+        #undef call_module_hook
+
+        setRobotUnitState(RobotUnitState::Running);
+
+        #define call_module_hook(Type) cast_to_and_call(::armarx::RobotUnitModule::Type, _postFinishControlThreadInitialization(), true)
+        for_each_module(call_module_hook)
+        #undef call_module_hook
+    }
+
+    void ModuleBase::finishRunning()
+    {
+        checkDerivedClasses();
+        shutDown();
+        GuardType guard {dataMutex}; //DO NOT USE getGuard here!
+        if(getRobotUnitState() != RobotUnitState::Running)
+        {
+            ARMARX_ERROR << "called finishRunning when state was " << to_string(getRobotUnitState());
+        }
+
+        #define call_module_hook(Type) cast_to_and_call(::armarx::RobotUnitModule::Type, _preFinishRunning(), false)
+        for_each_module(call_module_hook)
+        #undef call_module_hook
+
+        setRobotUnitState(RobotUnitState::Exiting);
+        joinControlThread();
+
+        #define call_module_hook(Type) cast_to_and_call(::armarx::RobotUnitModule::Type, _postFinishRunning(), false)
+        for_each_module(call_module_hook)
+        #undef call_module_hook
+    }
+
+#undef for_each_module_apply
+#undef for_each_module
+#undef cast_to_and_call
+    // //////////////////////////////////////////////////////////////////////////// //
+    // ////////////////////////////////// other /////////////////////////////////// //
+    // //////////////////////////////////////////////////////////////////////////// //
+
+    const std::set<RobotUnitState> ModuleBase::DevicesReadyStates
+    {
+        RobotUnitState::InitializingUnits,
+                RobotUnitState::InitializingControlThread,
+                RobotUnitState::Running
+    };
+
+    void ModuleBase::setRobotUnitState(RobotUnitState to)
+    {
+        auto guard = getGuard();
+
+        const auto transitionErrorMessage = [=](RobotUnitState expectedFrom)
+        {
+            return "Can't switch to state " + to_string(to) + " from " + to_string(state) +
+                    "! The expected source state is " + to_string(expectedFrom) + ".";
+        };
+        const auto transitionErrorThrow = [=](RobotUnitState expectedFrom)
+        {
+            if(state != expectedFrom)
+            {
+                const auto msg = transitionErrorMessage(expectedFrom);
+                ARMARX_ERROR << msg;
+                throw std::invalid_argument {msg};
+            }
+        };
+
+        switch (to)
+        {
+        case armarx::RobotUnitState::InitializingComponent:
+            throw std::invalid_argument {"Can't switch to state RobotUnitState::InitializingComponent"};
+        case armarx::RobotUnitState::InitializingDevices:
+            transitionErrorThrow(RobotUnitState::InitializingComponent);
+            break;
+        case RobotUnitState::InitializingUnits:
+            transitionErrorThrow(RobotUnitState::InitializingDevices);
+            break;
+        case RobotUnitState::InitializingControlThread:
+            transitionErrorThrow(RobotUnitState::InitializingUnits);
+            break;
+        case RobotUnitState::Running:
+            transitionErrorThrow(RobotUnitState::InitializingControlThread);
+            break;
+        case RobotUnitState::Exiting:
+            if(state != RobotUnitState::Running)
+            {
+                ARMARX_ERROR << transitionErrorMessage(RobotUnitState::Running);
+            }
+        default:
+            throw std::invalid_argument
+            {
+                "setRobotUnitState: Unknown target state " + to_string(static_cast<std::size_t>(to))+
+                "\nStacktrace\n" + LogSender::CreateBackTrace()
+            };
+        }
+        ARMARX_INFO << "switching state from " << to_string(state) << " to " << to_string(to);
+        state = to;
+    }
+
+
+    bool ModuleBase::areDevicesReady() const
+    {
+        return DevicesReadyStates.count(state);
+    }
+
+    bool ModuleBase::inControlThread() const
+    {
+        return getRobotUnitState() == RobotUnitState::Running &&
+               std::this_thread::get_id() == _module<ControlThread>().getControlThreadId();
+    }
+
+    void ModuleBase::throwIfInControlThread(const std::string &fnc) const
+    {
+        if (inControlThread())
+        {
+            throw LogicError
+            {
+                "Called function '" + fnc + "' in the Control Thread\nStack trace:\n" +
+                        LogSender::CreateBackTrace()
+            };
+        }
+    }
+
+    ModuleBase::GuardType ModuleBase::getGuard() const
+    {
+        if (inControlThread())
+        {
+            throw LogicError
+            {
+                "Attempted to lock mutex in Control Thread\nStack trace:\n" +
+                LogSender::CreateBackTrace()
+            };
+        }
+        GuardType guard {dataMutex, std::defer_lock};
+        if(guard.try_lock())
+        {
+            return guard;
+        }
+        while(!guard.try_lock_for(std::chrono::microseconds{100}))
+        {
+            if(isShuttingDown())
+            {
+                throw LogicError{"Attempting to lock mutex during shutdown\nStacktrace\n" + LogSender::CreateBackTrace()};
+            }
+        }
+
+        return guard;
+    }
+
+    void ModuleBase::throwIfStateIsNot(const std::set<RobotUnitState> &stateSet, const std::string &fnc, bool onlyWarn) const
+    {
+        if (! stateSet.count(state))
+        {
+            std::stringstream ss;
+            ss << fnc << ": Can't be called if state is not in {";
+            bool fst = true;
+            for (RobotUnitState st : stateSet)
+            {
+                if (!fst)
+                {
+                    ss << ", ";
+                }
+                ss << st;
+                fst = false;
+            }
+            ss << "} (current state " << getRobotUnitState() << ")\n"
+               << "Stacktrace:\n" << LogSender::CreateBackTrace();
+            ARMARX_ERROR << ss.str();
+            if (!onlyWarn)
+            {
+                throw LogicError {ss.str()};
+            }
+        }
+    }
+    void ModuleBase::throwIfStateIsNot(RobotUnitState s, const std::string& fnc, bool onlyWarn) const
+    {
+        throwIfStateIsNot(std::set<RobotUnitState> {s}, fnc, onlyWarn);
+    }
+
+    void ModuleBase::throwIfStateIs(const std::set<RobotUnitState>& stateSet, const std::string& fnc, bool onlyWarn) const
+    {
+        if (stateSet.count(state))
+        {
+            std::stringstream ss;
+            ss << fnc << ": Can't be called if state is in {";
+            bool fst = true;
+            for (RobotUnitState st : stateSet)
+            {
+                if (!fst)
+                {
+                    ss << ", ";
+                }
+                ss << st;
+                fst = false;
+            }
+            ss << "} (current state " << getRobotUnitState() << ")\n"
+               << "Stacktrace:\n" << LogSender::CreateBackTrace();
+            ARMARX_ERROR << ss.str();
+            if (!onlyWarn)
+            {
+                throw LogicError {ss.str()};
+            }
+        }
+    }
+    void ModuleBase::throwIfStateIs(RobotUnitState s, const std::string& fnc, bool onlyWarn) const
+    {
+        throwIfStateIs(std::set<RobotUnitState> {s}, fnc, onlyWarn);
+    }
+
+    void ModuleBase::throwIfDevicesNotReady(const std::string& fnc) const
+    {
+        throwIfStateIsNot(DevicesReadyStates, fnc);
+    }
+
+
+    std::atomic<ModuleBase*> ModuleBase::Instance_{nullptr};
+
+    ModuleBase::ModuleBase()
+    {
+        if(Instance_ && this != Instance_)
+        {
+            ARMARX_FATAL << "This class is a Singleton. It was already instantiated. (Instance = " << Instance_ << ", this = " << this << ")";
+            std::terminate();
+        }
+        Instance_ = this;
+    }
+
+}
+}
diff --git a/source/RobotAPI/components/units/RobotUnit/RobotUnitModules/RobotUnitModuleBase.h b/source/RobotAPI/components/units/RobotUnit/RobotUnitModules/RobotUnitModuleBase.h
new file mode 100644
index 0000000000000000000000000000000000000000..17ed09e53c7068cc8364bc6a38ce3dd0741b0193
--- /dev/null
+++ b/source/RobotAPI/components/units/RobotUnit/RobotUnitModules/RobotUnitModuleBase.h
@@ -0,0 +1,502 @@
+/*
+ * This file is part of ArmarX.
+ *
+ * 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    RobotAPI::ArmarXObjects::RobotUnit
+ * @author     Raphael Grimm ( raphael dot grimm at kit dot edu )
+ * @date       2018
+ * @copyright  http://www.gnu.org/licenses/gpl-2.0.txt
+ *             GNU General Public License
+ */
+
+#pragma once
+
+#include <atomic>
+#include <chrono>
+#include <mutex>
+
+#include <boost/preprocessor/variadic/to_seq.hpp>
+#include <boost/preprocessor/seq/for_each.hpp>
+#include <boost/current_function.hpp>
+
+#include <VirtualRobot/Robot.h>
+
+#include <ArmarXCore/core/Component.h>
+
+#include <RobotAPI/interface/units/RobotUnit/RobotUnitInterface.h>
+
+#include "../JointControllers/JointController.h"
+#include "../util/JointAndNJointControllers.h"
+#include "../util.h"
+
+namespace armarx
+{
+    TYPEDEF_PTRS_HANDLE(RobotUnit);
+    TYPEDEF_PTRS_HANDLE(NJointController);
+
+    template<class T>
+    T& CheckedDeref(T* ptr)
+    {
+        if(!ptr)
+        {
+            throw std::invalid_argument{"Ptr passed to CheckedDeref is NULL"};
+        }
+        return *ptr;
+    }
+    template<class Targ, class Src>
+    Targ& CheckedCastAndDeref(Src* src)
+    {
+        Targ* ptr = dynamic_cast<Targ*>(src);
+        if(!ptr)
+        {
+            if(!src)
+            {
+                throw std::invalid_argument{"Ptr passed to CheckedCastAndDeref is NULL"};
+            }
+            throw std::invalid_argument
+            {
+                "Ptr of type '" +
+                GetTypeString<Src>() +
+                "' passed to CheckedCastAndDeref is is not related to target type '" +
+                GetTypeString<Targ>()
+            };
+        }
+        return *ptr;
+    }
+
+    /// @brief The current state of the multi step initialization of a RobotUnit
+    enum class RobotUnitState : std::size_t
+    {
+        InitializingComponent,
+        InitializingDevices,
+        //ok to use devices/create controllers
+        InitializingUnits,
+        InitializingControlThread,
+        Running,
+        Exiting
+    };
+
+    std::string to_string(armarx::RobotUnitState s);
+    inline std::ostream& operator<<(std::ostream& o, RobotUnitState s)
+    {
+        return o << to_string(s);
+    }
+}
+
+namespace armarx
+{
+    namespace RobotUnitModule
+    {
+        namespace detail
+        {
+            class ModuleBaseIntermediatePropertyDefinitions: public ComponentPropertyDefinitions
+            {
+            public:
+                ModuleBaseIntermediatePropertyDefinitions():ComponentPropertyDefinitions(""){}
+            };
+        }
+
+        class ModuleBasePropertyDefinitions: virtual public detail::ModuleBaseIntermediatePropertyDefinitions
+        {
+        public:
+            ModuleBasePropertyDefinitions(std::string prefix)
+            {
+                setDescription(prefix + " properties");
+                setPrefix(prefix + ".");
+            }
+        };
+
+
+    #define forward_declare(r, data, Mod) TYPEDEF_PTRS_HANDLE(Mod);
+            BOOST_PP_SEQ_FOR_EACH(forward_declare, , BOOST_PP_VARIADIC_TO_SEQ(RobotUnitModules))
+    #undef forward_declare
+
+            /**
+             * @brief Base class for all RobotUnitModules
+             *
+             * Since the robot unit is a complex class, it is split into several modules.
+             * One reason behind this is stopping developers from accidently using datastructures in the wrong way (e.g. causing racing conditions)
+             * For a \ref RobotUnit to work, ALL modules are required (A class has to derive all of them)
+             *
+             * \section Modules
+             * The list of Modules is:
+             *    - \ref ControllerManagement
+             *    - \ref ControlThread
+             *    - \ref ControlThreadDataBuffer
+             *    - \ref Devices
+             *    - \ref Logging
+             *    - \ref Management
+             *    - \ref Publisher
+             *    - \ref RobotData
+             *    - \ref SelfCollisionChecker
+             *    - \ref Units
+             *
+             * \section LifeCycle Life cycle
+             * The RobotUnit has multiple Phases (see \ref RobotUnitState) as well as the life cycle of a \ref ManagedIceObject.
+             *
+             * \subsection LifeCycleMIO ManagedIceObject Life cycle
+             * The hooks (\ref onInitComponent, \ref onConnectComponent, \ref onDisconnectComponent, \ref onExitComponent)
+             * for state transitions provided by \ref ManagedIceObject have a final overrider.
+             * Deriving classes have to use the replacement hooks:
+             *
+            <table>
+                <tr><th> Hook                       <th> Replacement           \th
+                <tr><td> \ref onInitComponent       <td> \ref onInitRobotUnit
+                <tr><td> \ref onConnectComponent    <td> \ref onConnectRobotUnit
+                <tr><td> \ref onDisconnectComponent <td> \ref onDisconnectRobotUnit
+                <tr><td> \ref onExitComponent       <td> \ref onExitRobotUnit
+            </table>
+
+             * \subsection LifeCycleRU RobotUnit Life cycle
+             *
+             * The initial phase is \ref RobotUnitState::InitializingComponent.
+             * The following table shows all Phase transitions and the functions causing it:
+             *
+            <table>
+                <tr><th> From                                            <th> To                                             <th> Transition function                <th> Note                              \th
+                <tr><td> \ref RobotUnitState::InitializingComponent      <td> \ref RobotUnitState::InitializingDevices       <td> \ref finishComponentInitialization <td> Called in \ref onInitComponent
+                <tr><td> \ref RobotUnitState::InitializingDevices        <td> \ref RobotUnitState::InitializingUnits         <td> \ref finishDeviceInitialization    <td>
+                <tr><td> \ref RobotUnitState::InitializingUnits          <td> \ref RobotUnitState::InitializingControlThread <td> \ref finishUnitInitialization      <td>
+                <tr><td> \ref RobotUnitState::InitializingControlThread  <td> \ref RobotUnitState::Running                   <td> \ref finishControlThreadInitialization                  <td> Has to be called in the control thread
+                <tr><td> \ref RobotUnitState::Running                    <td> \ref RobotUnitState::Exiting                   <td> \ref finishRunning                 <td> Called in \ref onExitComponent
+            </table>
+             *
+             *
+             *
+             * \subsection RUMLifeCycleHooks RobotUnitModule Hooks for Life Cycle transition functions
+             *
+             * Each RobotUnitModule has two hooks each transition function ().
+             *     -  The '_pre<TRANSITION_FUNCTION_NAME>' hook is called in the transition function before the state has changed.
+             *     -  The '_post<TRANSITION_FUNCTION_NAME>' hook is called in the transition function after the state has changed.
+             *
+             * \warning The same hook of different modules (e.g.: \ref _preFinishDeviceInitialization, \ref _postOnInitRobotUnit) must not depend on each other.
+             */
+        class ModuleBase : virtual public Component
+        {
+            /// @brief The singleton instance
+            static std::atomic<ModuleBase*> Instance_;
+        public:
+            /**
+             * @brief Returns the singleton instance of this class
+             * @return The singleton instance of this class
+             */
+            static ModuleBase& Instance()
+            {
+                ARMARX_CHECK_NOT_NULL(Instance_);
+                return *Instance_;
+            }
+            /**
+             * @brief Returns the singleton instance of the given class
+             * @return The singleton instance of the given class
+             */
+            template<class T>
+            static T& Instance()
+            {
+                static_assert(std::is_base_of<ModuleBase, T>::value, "The type has to derive ModuleBase");
+                ARMARX_CHECK_NOT_NULL(Instance_);
+                return dynamic_cast<T&>(*Instance_);
+            }
+        protected:
+            /// @brief Ctor
+            ModuleBase();
+            // //////////////////////////////////////////////////////////////////////////////////////// //
+            // //////////////////////////////////////// types ///////////////////////////////////////// //
+            // //////////////////////////////////////////////////////////////////////////////////////// //
+        protected:
+            using MutexType = std::recursive_timed_mutex;
+            using GuardType = std::unique_lock<MutexType>;
+            using ClockType = std::chrono::high_resolution_clock;
+            using TimePointType = std::chrono::high_resolution_clock::time_point;
+
+#define using_module_types(...) using_module_types_impl(__VA_ARGS__)
+#define using_module_types_impl(r, data, Mod) using Module ## Mod = Mod;
+        BOOST_PP_SEQ_FOR_EACH(using_module_types, , BOOST_PP_VARIADIC_TO_SEQ(RobotUnitModules))
+#undef using_module_types
+#undef using_module_types_impl
+            // //////////////////////////////////////////////////////////////////////////////////////// //
+            // ////////////////////////////////// access to modules /////////////////////////////////// //
+            // //////////////////////////////////////////////////////////////////////////////////////// //
+        protected:
+            /// @brief Checks whether the implementing class derives all modules.
+            void checkDerivedClasses() const;
+        public:
+            /**
+             * @brief Returns this as ref to the given type.
+             * @return This as ref to the given type.
+             */
+            template<class T>       T& _module()       {return dynamic_cast<      T&>(*this);}
+            /**
+             * @brief Returns this as ref to the given type.
+             * @return This as ref to the given type.
+             */
+            template<class T> const T& _module() const {return dynamic_cast<const T&>(*this);}
+            /**
+             * @brief Returns this as ptr to the given type.
+             * @return This as ptr to the given type.
+             */
+            template<class T>       T* _modulePtr()       {return &_module<      T>();}
+            /**
+             * @brief Returns this as ptr to the given type.
+             * @return This as ptr to the given type.
+             */
+            template<class T> const T* _modulePtr() const {return &_module<const T>();}
+            // //////////////////////////////////////////////////////////////////////////////////////// //
+            // ////////////////////////////// ManagedIceObject life cycle ///////////////////////////// //
+            // //////////////////////////////////////////////////////////////////////////////////////// //
+        protected:
+            //ManagedIceObject life cycle
+            /// @see \ref ManagedIceObject::onInitComponent
+            virtual void onInitComponent()       final;
+            /// @see \ref ManagedIceObject::onConnectComponent
+            virtual void onConnectComponent()    final;
+            /// @see \ref ManagedIceObject::onDisconnectComponent
+            virtual void onDisconnectComponent() final;
+            /// @see \ref ManagedIceObject::onExitComponent
+            virtual void onExitComponent()       final;
+
+            //ManagedIceObject life cycle module hooks
+            /// @brief Hook for deriving RobotUnitModules called in \ref onInitComponent (called before \ref onInitRobotUnit was called)
+            void _preOnInitRobotUnit(){}
+            /// @brief Hook for deriving RobotUnitModules called in \ref onInitComponent (called after \ref onInitRobotUnit was called)
+            void _postOnInitRobotUnit(){}
+
+            /// @brief Hook for deriving RobotUnitModules called in \ref onInitComponent (called before \ref onConnectRobotUnit was called)
+            void _preOnConnectRobotUnit(){}
+            /// @brief Hook for deriving RobotUnitModules called in \ref onInitComponent (called after \ref onConnectRobotUnit was called)
+            void _postOnConnectRobotUnit(){}
+
+            /// @brief Hook for deriving RobotUnitModules called in \ref onInitComponent (called before \ref onDisconnectRobotUnit was called)
+            void _preOnDisconnectRobotUnit(){}
+            /// @brief Hook for deriving RobotUnitModules called in \ref onInitComponent (called after \ref onDisconnectRobotUnit was called)
+            void _postOnDisconnectRobotUnit(){}
+
+            /// @brief Hook for deriving RobotUnitModules called in \ref onInitComponent (called before \ref onExitRobotUnit was called)
+            void _preOnExitRobotUnit(){}
+            /// @brief Hook for deriving RobotUnitModules called in \ref onInitComponent (called after \ref onExitRobotUnit was called)
+            void _postOnExitRobotUnit(){}
+            // //////////////////////////////////////////////////////////////////////////////////////// //
+            // ////////////////////// other ManagedIceObject / Component methods ////////////////////// //
+            // //////////////////////////////////////////////////////////////////////////////////////// //
+        protected:
+            /// @see \ref ManagedIceObject::icePropertiesUpdated
+            void icePropertiesUpdated(const std::set<std::string>& changedProperties) override;
+            /// @see \ref ManagedIceObject::icePropertiesInitialized
+            void icePropertiesInitialized() override;
+            /// @see \ref ManagedIceObject::getDefaultName
+            std::string getDefaultName() const override
+            {
+                return "RobotUnit";
+            }
+
+            //module hooks
+            /// @brief Hook for deriving RobotUnitModules called in \ref icePropertiesUpdated
+            void _icePropertiesUpdated(const std::set<std::string>& changedProperties){}
+            /// @brief Hook for deriving RobotUnitModules called in \ref icePropertiesInitialized
+            void _icePropertiesInitialized(){}            
+            // //////////////////////////////////////////////////////////////////////////////////////// //
+            // ////////////////////////////// state and state transition ////////////////////////////// //
+            // //////////////////////////////////////////////////////////////////////////////////////// //
+        private:
+            /**
+             * @brief Sets the \ref RobotUnit's state to \param s
+             * @param s The state to set
+             */
+            void setRobotUnitState(RobotUnitState s);
+        protected:
+            //state transitions
+            /// @brief Transition \ref RobotUnitState::InitializingComponent -> \ref RobotUnitState::InitializingDevices
+            virtual void finishComponentInitialization();
+            /// @brief Transition \ref RobotUnitState::InitializingDevices -> \ref RobotUnitState::InitializingUnits
+            virtual void finishDeviceInitialization();
+            /// @brief Transition \ref RobotUnitState::InitializingUnits -> \ref RobotUnitState::WaitingForRTThreadInitialization
+            virtual void finishUnitInitialization();
+            /// @brief Transition \ref RobotUnitState::InitializingControlThread -> \ref RobotUnitState::Running
+            virtual void finishControlThreadInitialization();
+            /// @brief Transition \ref RobotUnitState::Running -> \ref RobotUnitState::Exiting
+            virtual void finishRunning();
+
+            //state transition module hooks
+            /// @brief Hook for deriving RobotUnitModules called in \ref finishComponentInitialization (called before the state has changed)
+            void _preFinishComponentInitialization(){}
+            /// @brief Hook for deriving RobotUnitModules called in \ref finishComponentInitialization (called after the state has changed)
+            void _postFinishComponentInitialization(){}
+
+            /// @brief Hook for deriving RobotUnitModules called in \ref finishDeviceInitialization (called before the state has changed)
+            void _preFinishDeviceInitialization(){}
+            /// @brief Hook for deriving RobotUnitModules called in \ref finishDeviceInitialization (called after the state has changed)
+            void _postFinishDeviceInitialization(){}
+
+            /// @brief Hook for deriving RobotUnitModules called in \ref finishUnitInitialization (called before the state has changed)
+            void _preFinishUnitInitialization(){}
+            /// @brief Hook for deriving RobotUnitModules called in \ref finishUnitInitialization (called after the state has changed)
+            void _postFinishUnitInitialization(){}
+
+            /// @brief Hook for deriving RobotUnitModules called in \ref finishControlThreadInitialization (called before the state has changed)
+            void _preFinishControlThreadInitialization(){}
+            /// @brief Hook for deriving RobotUnitModules called in \ref finishControlThreadInitialization (called after the state has changed)
+            void _postFinishControlThreadInitialization(){}
+
+            /// @brief Hook for deriving RobotUnitModules called in \ref finishRunning (called before the state has changed)
+            void _preFinishRunning(){}
+            /// @brief Hook for deriving RobotUnitModules called in \ref finishRunning (called after the state has changed)
+            void _postFinishRunning(){}
+            // //////////////////////////////////////////////////////////////////////////////////////// //
+            // /////////////////////////////////////// utility //////////////////////////////////////// //
+            // //////////////////////////////////////////////////////////////////////////////////////// //
+        public:
+            /**
+             * @brief Returns the \ref RobotUnit's State
+             * @return The \ref RobotUnit's State
+             */
+            RobotUnitState getRobotUnitState() const;
+
+            /**
+             * @brief Throws an exception if the current state is not in \param stateSet
+             * @param stateSet The set of acceptable \ref RobotUnitState "RobotUnitStates"
+             * @param fnc The callers function name.
+             * @param onlyWarn Only print a warning instead of throwing an exception.
+             */
+            void throwIfStateIsNot(const std::set<RobotUnitState>& stateSet, const std::string& fnc, bool onlyWarn = false) const;
+            /**
+             * @brief Throws an exception if the current state is not \param state
+             * @param state The acceptable \ref RobotUnitState
+             * @param fnc The callers function name.
+             * @param onlyWarn Only print a warning instead of throwing an exception.
+             */
+            void throwIfStateIsNot(RobotUnitState s, const std::string& fnc, bool onlyWarn = false) const;
+            /**
+             * @brief Throws an exception if the current state is in \param stateSet
+             * @param stateSet The set of forbidden \ref RobotUnitState "RobotUnitStates"
+             * @param fnc The callers function name.
+             * @param onlyWarn Only print a warning instead of throwing an exception.
+             */
+            void throwIfStateIs(const std::set<RobotUnitState>& stateSet, const std::string& fnc, bool onlyWarn = false) const;
+            /**
+             * @brief Throws an exception if the current state is \param state
+             * @param state The forbidden \ref RobotUnitState
+             * @param fnc The callers function name.
+             * @param onlyWarn Only print a warning instead of throwing an exception.
+             */
+            void throwIfStateIs(RobotUnitState s, const std::string& fnc, bool onlyWarn = false) const;
+            /**
+             * @brief Throws if the \ref Device "Devices" are not ready.
+             * @param fnc The callers function name.
+             * @see areDevicesReady
+             */
+            void throwIfDevicesNotReady(const std::string& fnc) const;
+
+            /**
+             * @brief Returns whether \ref Device "Devices" are ready
+             * @return Whether \ref Device "Devices" are ready
+             * @see \ref DevicesReadyStates
+             */
+            bool areDevicesReady() const;
+
+            /**
+             * @brief Returns whether the current thread is the \ref ControlThread.
+             * @return Whether the current thread is the \ref ControlThread.
+             */
+            bool inControlThread() const;
+
+            /**
+             * @brief Throws if the current thread is the \ref ControlThread.
+             * @param fnc The callers function name.
+             */
+            void throwIfInControlThread(const std::string& fnc) const;
+
+            /**
+             * @brief Returns whether the \ref RobotUnit is shutting down
+             * @return Whether the \ref RobotUnit is shutting down
+             * @see shutDown
+             */
+            bool isShuttingDown() const ///TODO use this function in implementations
+            {
+                return isShuttingDown_.load();
+            }
+            /**
+             * @brief Requests the \ref RobotUnit to shut down.
+             * @see isShuttingDown
+             */
+            void shutDown() ///TODO use this function in implementations
+            {
+                isShuttingDown_.store(true);
+            }
+            // //////////////////////////////////////////////////////////////////////////// //
+            // /////////////////////////// robot unit impl hooks ////////////////////////// //
+            // //////////////////////////////////////////////////////////////////////////// //
+            /// @brief called in RobotUnit::onInitComponent()
+            virtual void onInitRobotUnit(){}
+            /// @brief called in RobotUnit::onConnectComponent()
+            virtual void onConnectRobotUnit(){}
+            /// @brief called in RobotUnit::onDisconnecComponent()
+            virtual void onDisconnectRobotUnit(){}
+            /// @brief called in RobotUnit::onExitComponent() before calling RobotUnit::finishRunning
+            virtual void onExitRobotUnit(){}
+
+            /// @brief Implementations have to join their \ref ControlThread in this hook. (used by RobotUnit::finishRunning())
+            virtual void joinControlThread() = 0;
+
+            /// @brief The \ref ControlThread's period
+            virtual IceUtil::Time getControlThreadTargetPeriod() const = 0;
+            // //////////////////////////////////////////////////////////////////////////// //
+            // ////////////////////////////////// other /////////////////////////////////// //
+            // //////////////////////////////////////////////////////////////////////////// //
+        protected:
+            /**
+             * @brief Returns a sentinel value for an index (std::numeric_limits<std::size_t>::max())
+             * @return A sentinel value for an index (std::numeric_limits<std::size_t>::max())
+             */
+            static constexpr std::size_t IndexSentinel()
+            {
+                return std::numeric_limits<std::size_t>::max();
+            }
+            /**
+             * @brief Returns a guard to the \ref RobotUnits mutex.
+             * @return A guard to the \ref RobotUnits mutex.
+             * @throw throws If called in the \ref ControlThread or on shutdown.
+             */
+            GuardType getGuard() const;
+            /**
+             * @brief Returns the current Time
+             * @return The current Time
+             */
+            static TimePointType Now();
+            /**
+             * @brief Returns the microseconds since the given start timepoint.
+             * @param last Start timepoint
+             * @return The microseconds since the given start timepoint.
+             */
+            static std::chrono::microseconds MicroToNow(TimePointType last);
+            /**
+             * @brief Returns the microseconds since epoch.
+             * @return The microseconds since epoch.
+             */
+            static std::chrono::microseconds MicroNow();
+            // //////////////////////////////////////////////////////////////////////////////////////// //
+            // ///////////////////////////////////////// Data ///////////////////////////////////////// //
+            // //////////////////////////////////////////////////////////////////////////////////////// //
+        private:
+            /// @brief The \ref RobotUnits mutex.
+            mutable MutexType dataMutex;
+            /// @brief Set of \ref RobotUnitState "RobotUnitStates" where \ref Device "Devices" are usable
+            static const std::set<RobotUnitState> DevicesReadyStates;
+            /// @brief The \ref RobotUnit's current state
+            std::atomic<RobotUnitState> state{RobotUnitState::InitializingComponent};
+            /// @brief Whether the \ref RobotUnit is shutting down
+            std::atomic_bool isShuttingDown_{false};
+        };
+    }
+}
+#include "RobotUnitModuleBase.ipp"
+
diff --git a/source/RobotAPI/components/units/RobotUnit/RobotUnitModules/RobotUnitModuleBase.ipp b/source/RobotAPI/components/units/RobotUnit/RobotUnitModules/RobotUnitModuleBase.ipp
new file mode 100644
index 0000000000000000000000000000000000000000..7f8a977b0c7bd27a11332ce4fa655550a5930678
--- /dev/null
+++ b/source/RobotAPI/components/units/RobotUnit/RobotUnitModules/RobotUnitModuleBase.ipp
@@ -0,0 +1,49 @@
+/*
+ * This file is part of ArmarX.
+ *
+ * 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    RobotAPI::ArmarXObjects::RobotUnit
+ * @author     Raphael Grimm ( raphael dot grimm at kit dot edu )
+ * @date       2018
+ * @copyright  http://www.gnu.org/licenses/gpl-2.0.txt
+ *             GNU General Public License
+ */
+
+#pragma once
+
+#include "RobotUnitModuleBase.h"
+
+namespace armarx
+{
+    namespace RobotUnitModule
+    {
+        inline ModuleBase::TimePointType ModuleBase::Now()
+        {
+            return ClockType::now();
+        }
+        inline std::chrono::microseconds ModuleBase::MicroToNow(ModuleBase::TimePointType last)
+        {
+            return std::chrono::duration_cast<std::chrono::microseconds>(Now() - last);
+        }
+        inline std::chrono::microseconds ModuleBase::MicroNow()
+        {
+            return std::chrono::duration_cast<std::chrono::microseconds>(std::chrono::high_resolution_clock::now().time_since_epoch());
+        }
+
+        inline RobotUnitState ModuleBase::getRobotUnitState() const
+        {
+            return state;
+        }
+    }
+}
diff --git a/source/RobotAPI/components/units/RobotUnit/RobotUnitModules/RobotUnitModuleControlThread.cpp b/source/RobotAPI/components/units/RobotUnit/RobotUnitModules/RobotUnitModuleControlThread.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..fb6bf1ce6d8e83378592dfa83291ba5eb2d2b15f
--- /dev/null
+++ b/source/RobotAPI/components/units/RobotUnit/RobotUnitModules/RobotUnitModuleControlThread.cpp
@@ -0,0 +1,573 @@
+/*
+ * This file is part of ArmarX.
+ *
+ * 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    RobotAPI::ArmarXObjects::RobotUnit
+ * @author     Raphael Grimm ( raphael dot grimm at kit dot edu )
+ * @date       2018
+ * @copyright  http://www.gnu.org/licenses/gpl-2.0.txt
+ *             GNU General Public License
+ */
+
+#include <VirtualRobot/XML/RobotIO.h>
+
+#include <ArmarXCore/core/util/OnScopeExit.h>
+
+#include "RobotUnitModuleControlThread.h"
+#include "../NJointControllers/NJointController.h"
+
+#include "../Devices/RTThreadTimingsSensorDevice.h"
+
+namespace armarx
+{
+    namespace RobotUnitModule
+    {
+        /**
+         * \brief This class allows minimal access to private members of \ref NJointController in a sane fashion for \ref ControlThread.
+         * \warning !! DO NOT ADD ANYTHING IF YOU DO NOT KNOW WAHT YOU ARE DOING! IF YOU DO SOMETHING WRONG YOU WILL CAUSE UNDEFINED BEHAVIOUR !!
+         */
+        class NJointControllerAttorneyForControlThread
+        {
+            friend class ControlThread;
+            static void RtDeactivateController(const NJointControllerPtr& nJointCtrl)
+            {
+                nJointCtrl->rtDeactivateController();
+            }
+            static void RtActivateController(const NJointControllerPtr& nJointCtrl)
+            {
+                nJointCtrl->rtActivateController();
+            }
+            static void RtDeactivateControllerBecauseOfError(const NJointControllerPtr& nJointCtrl)
+            {
+                nJointCtrl->rtDeactivateControllerBecauseOfError();
+            }
+        };
+        /**
+         * \brief This class allows minimal access to private members of \ref ControlThreadDataBuffer in a sane fashion for \ref ControlThread.
+         * \warning !! DO NOT ADD ANYTHING IF YOU DO NOT KNOW WAHT YOU ARE DOING! IF YOU DO SOMETHING WRONG YOU WILL CAUSE UNDEFINED BEHAVIOUR !!
+         */
+        class ControlThreadDataBufferAttorneyForControlThread
+        {
+            friend class ControlThread;
+            static std::vector<JointController*>& GetActivatedJointControllers(ControlThread* p)
+            {
+                return p->_module<ControlThreadDataBuffer>().controllersActivated.getWriteBuffer().jointControllers;
+            }
+            static std::vector<NJointController*>& GetActivatedNJointControllers(ControlThread* p)
+            {
+                return p->_module<ControlThreadDataBuffer>().controllersActivated.getWriteBuffer().nJointControllers;
+            }
+            static std::vector<std::size_t>& GetActivatedJointToNJointControllerAssignement(ControlThread* p)
+            {
+                return p->_module<ControlThreadDataBuffer>().controllersActivated.getWriteBuffer().jointToNJointControllerAssignement;
+            }
+            static void AcceptRequestedJointToNJointControllerAssignement(ControlThread* p)
+            {
+                p->_module<ControlThreadDataBuffer>().controllersActivated.getWriteBuffer().jointToNJointControllerAssignement =
+                        p->_module<ControlThreadDataBuffer>().controllersRequested.getReadBuffer().jointToNJointControllerAssignement;
+            }
+            static void CommitActivatedControllers(ControlThread* p)
+            {
+                return p->_module<ControlThreadDataBuffer>().controllersActivated.commitWrite();
+            }
+            static void ResetActivatedControllerAssignement(ControlThread* p)
+            {
+                return p->_module<ControlThreadDataBuffer>().controllersActivated.getWriteBuffer().resetAssignement();
+            }
+
+            static const std::vector<JointController*>& GetRequestedJointControllers(const ControlThread* p)
+            {
+                return p->_module<ControlThreadDataBuffer>().controllersRequested.getWriteBuffer().jointControllers;
+            }
+            static const std::vector<NJointController*>& GetRequestedNJointControllers(const ControlThread* p)
+            {
+                return p->_module<ControlThreadDataBuffer>().controllersRequested.getWriteBuffer().nJointControllers;
+            }
+            static bool RequestedControllersChanged(const ControlThread* p)
+            {
+                return p->_module<ControlThreadDataBuffer>().controllersRequested.updateReadBuffer();
+            }
+        };
+        /**
+         * \brief This class allows minimal access to private members of \ref Devices in a sane fashion for \ref ControlThread.
+         * \warning !! DO NOT ADD ANYTHING IF YOU DO NOT KNOW WAHT YOU ARE DOING! IF YOU DO SOMETHING WRONG YOU WILL CAUSE UNDEFINED BEHAVIOUR !!
+         */
+        class DevicesAttorneyForControlThread
+        {
+            friend class ControlThread;
+            static const std::vector<ControlDevicePtr>& GetControlDevices(const ControlThread* p)
+            {
+                return p->_module<Devices>().controlDevices.values();
+            }
+            static const std::vector<SensorDevicePtr>& GetSensorDevices(const ControlThread* p)
+            {
+                return p->_module<Devices>().sensorDevices.values();
+            }
+
+            static const std::vector<const SensorValueBase*>& GetSensorValues(const ControlThread* p)
+            {
+                return p->_module<Devices>().sensorValues;
+            }
+            static const std::vector<std::vector<PropagateConst<ControlTargetBase*>>>& GetControlTargets(const ControlThread* p)
+            {
+                return p->_module<Devices>().controlTargets;
+            }
+            static RTThreadTimingsSensorDevice& GetThreadTimingsSensorDevice(const ControlThread* p)
+            {
+                return *(p->_module<Devices>().rtThreadTimingsSensorDevice);
+            }
+
+            static void UpdateRobotWithSensorValues(const ControlThread* p, const VirtualRobot::RobotPtr& robot, const std::vector<VirtualRobot::RobotNodePtr>& robotNodes)
+            {
+                p->_module<Devices>().updateVirtualRobotFromSensorValues(robot, robotNodes, p->_module<Devices>().sensorValues);
+            }
+        };
+    }
+}
+
+namespace armarx
+{
+    namespace RobotUnitModule
+    {
+        bool ControlThread::rtSwitchControllerSetup()
+        {
+            rtGetThreadTimingsSensorDevice().rtMarkRtSwitchControllerSetupStart();
+            ARMARX_ON_SCOPE_EXIT { rtGetThreadTimingsSensorDevice().rtMarkRtSwitchControllerSetupEnd(); };
+            // !emergencyStop && !rtIsInEmergencyStop -> normal control flow
+            // !emergencyStop &&  rtIsInEmergencyStop -> force switch to reactivate old ( + reset flag)
+            //  emergencyStop && !rtIsInEmergencyStop -> deactivate all + set flag
+            //  emergencyStop &&  rtIsInEmergencyStop -> nothing to do
+
+            if (emergencyStop)
+            {
+                if (rtIsInEmergencyStop)
+                {
+                    return false;
+                }
+                rtIsInEmergencyStop = true;
+                bool updatedActive = false;
+                //deactivate all nJointCtrl
+                for (auto& nJointCtrl : rtGetActivatedNJointControllers())
+                {
+                    if (nJointCtrl)
+                    {
+                        NJointControllerAttorneyForControlThread::RtDeactivateController(nJointCtrl);
+                        nJointCtrl = nullptr;
+                        updatedActive = true;
+                    }
+                }
+                //set all JointCtrl to emergency stop (except stop movement)
+                for (std::size_t i = 0; i < rtGetControlDevices().size(); ++i)
+                {
+                    const ControlDevicePtr& controlDevice = rtGetControlDevices().at(i);
+                    const auto active = controlDevice->rtGetActiveJointController();
+                    const auto stopMov = controlDevice->rtGetJointStopMovementController();
+                    const auto emergency = controlDevice->rtGetJointEmergencyStopController();
+                    if (active != stopMov && active != emergency)
+                    {
+                        controlDevice->rtSetActiveJointController(emergency);
+                        rtGetActivatedJointControllers().at(i) = emergency;
+                        updatedActive = true;
+                    }
+                }
+                if (updatedActive)
+                {
+                    ControlThreadDataBufferAttorneyForControlThread::ResetActivatedControllerAssignement(this);
+                    rtCommitActivatedControllers();
+                }
+                return updatedActive;
+            }
+
+            if (
+                !ControlThreadDataBufferAttorneyForControlThread::RequestedControllersChanged(this) &&
+                !rtIsInEmergencyStop
+            )
+            {
+                return false;
+            }
+            rtIsInEmergencyStop = false;
+
+            //handle nJointCtrl
+            {
+                //"merge"
+                std::size_t n = rtGetControlDevices().size();
+                std::size_t idxAct = 0;
+                std::size_t idxReq = 0;
+                for (std::size_t i = 0; i < 2 * n; ++i)
+                {
+                    //skip nullptrs in act
+                    while (idxAct < n && !rtGetActivatedNJointControllers().at(idxAct))
+                    {
+                        ++idxAct;
+                    }
+                    const NJointControllerPtr& req = idxReq < n ? rtGetRequestedNJointControllers().at(idxReq) : nullptr; //may be null
+                    const NJointControllerPtr& act = idxAct < n ? rtGetActivatedNJointControllers().at(idxAct) : nullptr; //may be null if it is the last
+                    const auto reqId = reinterpret_cast<std::uintptr_t>(req.get());
+                    const auto actId = reinterpret_cast<std::uintptr_t>(act.get());
+
+                    if (reqId > actId)
+                    {
+                        //new ctrl
+                        NJointControllerAttorneyForControlThread::RtActivateController(req);
+                        ++idxReq;
+                    }
+                    else if (reqId < actId)
+                    {
+                        NJointControllerAttorneyForControlThread::RtDeactivateController(act);
+                        ++idxAct;
+                    }
+                    else //if(reqId == actId)
+                    {
+                        //same ctrl or both null ctrl
+                        ++idxReq;
+                        ++idxAct;
+                    }
+                    if (idxAct >= n && !req)
+                    {
+                        break;
+                    }
+                }
+                rtGetActivatedNJointControllers() = rtGetRequestedNJointControllers();
+            }
+
+            //handle Joint Ctrl
+            {
+                ARMARX_CHECK_EQUAL(rtGetRequestedJointControllers().size(), rtGetControlDevices().size());
+                for (std::size_t i = 0; i < rtGetControlDevices().size(); ++i)
+                {
+                    auto& controlDevice = rtGetControlDevices().at(i);
+                    const auto requestedJointCtrl = rtGetRequestedJointControllers().at(i);
+                    controlDevice->rtSetActiveJointController(requestedJointCtrl);
+                    rtGetActivatedJointControllers().at(i) = requestedJointCtrl;
+                }
+            }
+            ControlThreadDataBufferAttorneyForControlThread::AcceptRequestedJointToNJointControllerAssignement(this);
+            rtCommitActivatedControllers();
+            return true;
+        }
+
+
+        void ControlThread::rtResetAllTargets()
+        {
+            rtGetThreadTimingsSensorDevice().rtMarkRtResetAllTargetsStart();
+            for (const ControlDevicePtr& controlDev : rtGetControlDevices())
+            {
+                controlDev->rtGetActiveJointController()->rtResetTarget();
+            }
+            rtGetThreadTimingsSensorDevice().rtMarkRtResetAllTargetsEnd();
+        }
+
+
+        void ControlThread::rtHandleInvalidTargets()
+        {
+            rtGetThreadTimingsSensorDevice().rtMarkRtHandleInvalidTargetsStart();
+            bool oneIsInvalid = 0;
+            for (std::size_t i = 0; i < rtGetControlDevices().size(); ++i)
+            {
+                if (!rtGetActivatedJointControllers().at(i)->rtIsTargetVaild())
+                {
+                    rtDeactivateAssignedNJointControllerBecauseOfError(i, false);
+                    oneIsInvalid = true;
+                }
+            }
+            if (oneIsInvalid)
+            {
+                rtCommitActivatedControllers();
+            }
+            rtGetThreadTimingsSensorDevice().rtMarkRtHandleInvalidTargetsEnd();
+        }
+
+
+        void ControlThread::rtReadSensorDeviceValues(const IceUtil::Time &sensorValuesTimestamp, const IceUtil::Time &timeSinceLastIteration)
+        {
+            rtGetThreadTimingsSensorDevice().rtMarkRtReadSensorDeviceValuesStart();
+            for (const SensorDevicePtr& device : rtGetSensorDevices())
+            {
+                device->rtReadSensorValues(sensorValuesTimestamp, timeSinceLastIteration);
+            }
+            rtUpdateVirtualRobot();
+            rtGetThreadTimingsSensorDevice().rtMarkRtReadSensorDeviceValuesEnd();
+        }
+
+
+        void ControlThread::rtRunJointControllers(const IceUtil::Time &sensorValuesTimestamp, const IceUtil::Time &timeSinceLastIteration)
+        {
+            rtGetThreadTimingsSensorDevice().rtMarkRtRunJointControllersStart();
+            for (const ControlDevicePtr& device : rtGetControlDevices())
+            {
+                device->rtRun(sensorValuesTimestamp, timeSinceLastIteration);
+            }
+            rtGetThreadTimingsSensorDevice().rtMarkRtRunJointControllersEnd();
+        }
+
+
+        void ControlThread::rtRunNJointControllers(const IceUtil::Time &sensorValuesTimestamp, const IceUtil::Time &timeSinceLastIteration)
+        {
+            rtGetThreadTimingsSensorDevice().rtMarkRtRunNJointControllersStart();
+            for (std::size_t nJointCtrlIndex = 0; nJointCtrlIndex < rtGetActivatedNJointControllers().size(); ++nJointCtrlIndex)
+            {
+                NJointController* nJointCtrl = rtGetActivatedNJointControllers().at(nJointCtrlIndex);
+                try
+                {
+                    if (nJointCtrl)
+                    {
+                        auto start = MicroNow();
+                        nJointCtrl->rtSwapBufferAndRun(sensorValuesTimestamp, timeSinceLastIteration);
+                        auto duration = MicroNow() - start;
+                        if (duration.count() > 500)
+                        {
+                            ARMARX_ERROR << deactivateSpam(5) << "The NJointController " << nJointCtrl->getClassName() << " took " << duration.count() << " µs to run!";
+                        }
+                        else if (duration.count() > 50)
+                        {
+                            ARMARX_WARNING << deactivateSpam(5) << "The NJointController " << nJointCtrl->getClassName() << " took " << duration.count() << " µs to run!";
+                        }
+                    }
+                }
+                catch (...)
+                {
+                    ARMARX_ERROR << "NJoint Controller " << nJointCtrl->getInstanceName()
+                                 << " threw an exception and is now deactivated: "
+                                 << GetHandledExceptionString();
+                    rtDeactivateNJointControllerBecauseOfError(nJointCtrlIndex, false);
+                }
+            }
+            rtCommitActivatedControllers();
+            rtGetThreadTimingsSensorDevice().rtMarkRtRunNJointControllersEnd();
+        }
+
+
+        void ControlThread::rtDeactivateNJointControllerBecauseOfError(std::size_t nJointCtrlIndex, bool writeActivatedControlers)
+        {
+            const NJointControllerPtr& nJointCtrl = rtGetActivatedNJointControllers().at(nJointCtrlIndex);
+            NJointControllerAttorneyForControlThread ::RtDeactivateControllerBecauseOfError(nJointCtrl);
+            for (auto ctrlDevIdx : nJointCtrl->rtGetControlDeviceUsedIndices())
+            {
+                const ControlDevicePtr& controlDevice = rtGetControlDevices().at(ctrlDevIdx);
+                JointController* es = controlDevice->rtGetJointEmergencyStopController();
+                controlDevice->rtSetActiveJointController(es);
+                rtGetActivatedJointControllers().at(ctrlDevIdx) = es;
+                ARMARX_CHECK_EXPRESSION(rtGetActivatedJointToNJointControllerAssignement().at(ctrlDevIdx) == nJointCtrlIndex);
+                rtGetActivatedJointToNJointControllerAssignement().at(ctrlDevIdx) = IndexSentinel();
+            }
+            rtGetActivatedNJointControllers().at(nJointCtrlIndex) = nullptr;
+            //check ControlDeviceHardwareControlModeGroups
+            {
+                for (auto ctrlDevIdx : nJointCtrl->rtGetControlDeviceUsedIndices())
+                {
+                    const auto& ctrlModeGroups = _module<Devices>().getControlModeGroups();
+                    const auto groupIdx = ctrlModeGroups.groupIndices.at(ctrlDevIdx);
+                    if (groupIdx == IndexSentinel())
+                    {
+                        continue;
+                    }
+                    ControlDevice*  const dev  = rtGetControlDevices().at(ctrlDevIdx).get();
+                    JointController* const jointCtrl = dev->rtGetActiveJointController();
+                    const auto hwModeHash = jointCtrl->rtGetHardwareControlModeHash();
+                    //this device is in a group!
+                    // -> check all other devices
+                    for (const auto otherIdx : ctrlModeGroups.deviceIndices.at(groupIdx))
+                    {
+                        ControlDevice*  const otherDev  = rtGetControlDevices().at(otherIdx).get();
+                        JointController* const otherJointCtrl = otherDev->rtGetActiveJointController();
+                        const auto otherHwModeHash = otherJointCtrl->rtGetHardwareControlModeHash();
+                        if (hwModeHash == otherHwModeHash)
+                        {
+                            //the assigend ctrl has the same hwMode -> don't do anything
+                            continue;
+                        }
+                        const auto otherNJointCtrl1Idx = rtGetActivatedJointToNJointControllerAssignement().at(otherIdx);
+                        if (otherNJointCtrl1Idx == IndexSentinel())
+                        {
+                            //the hwmodes are different! (hence the other ctrl must be in stop movement
+                            ARMARX_CHECK_EXPRESSION(otherJointCtrl == otherDev->rtGetJointStopMovementController());
+                            //we need to activate the es contoller
+                            JointController* const es = otherDev->rtGetJointEmergencyStopController();
+                            otherDev->rtSetActiveJointController(es);
+                            ARMARX_CHECK_EXPRESSION(es->rtGetHardwareControlModeHash() == hwModeHash);
+                            rtGetActivatedJointControllers().at(otherIdx) = es;
+                            continue;
+                        }
+                        //the devs NJoint controller needs to be deactivated
+                        rtDeactivateAssignedNJointControllerBecauseOfError(otherIdx, false);
+                    }
+                }
+            }
+            rtDeactivatedNJointControllerBecauseOfError(nJointCtrl);
+
+            if (writeActivatedControlers)
+            {
+                rtCommitActivatedControllers();
+            }
+        }
+
+
+        void ControlThread::rtDeactivateAssignedNJointControllerBecauseOfError(std::size_t ctrlDevIndex, bool writeActivatedControlers)
+        {
+            std::size_t nJointCtrlIndex = rtGetActivatedJointToNJointControllerAssignement().at(ctrlDevIndex);
+            ARMARX_CHECK_EXPRESSION_W_HINT(
+                        nJointCtrlIndex < rtGetControlDevices().size(),
+                        nJointCtrlIndex << " < " << rtGetControlDevices().size() <<
+                        ": no NJoint controller controls this device (name = "
+                        << rtGetControlDevices().at(ctrlDevIndex)->getDeviceName()
+                        << ", ControlMode = " << rtGetActivatedJointControllers().at(ctrlDevIndex)->getControlMode() << ")!" << "\n"
+                        << VAROUT(rtGetActivatedJointControllers()) << "\n"
+                        << VAROUT(rtGetActivatedNJointControllers())
+                        );
+
+            rtDeactivateNJointControllerBecauseOfError(nJointCtrlIndex, false);
+
+            if (writeActivatedControlers)
+            {
+                rtCommitActivatedControllers();
+            }
+        }
+
+        void ControlThread::rtUpdateSensorAndControlBuffer(const IceUtil::Time &sensorValuesTimestamp, const IceUtil::Time &timeSinceLastIteration)
+        {
+            rtGetThreadTimingsSensorDevice().rtMarkRtUpdateSensorAndControlBufferStart();
+            SensorAndControl& sc = _module<ControlThreadDataBuffer>().rtGetSensorAndControlBuffer();
+            sc.writeTimestamp = IceUtil::Time::now(); // this has to be in real time
+            sc.sensorValuesTimestamp = sensorValuesTimestamp;
+            sc.timeSinceLastIteration = timeSinceLastIteration;
+            ARMARX_CHECK_EQUAL(rtGetSensorDevices().size(), sc.sensors.size());
+            for (std::size_t sensIdx = 0; sensIdx < rtGetSensorDevices().size(); ++sensIdx)
+            {
+                rtGetSensorDevices().at(sensIdx)->getSensorValue()->_copyTo(sc.sensors.at(sensIdx));
+            }
+
+            ARMARX_CHECK_EQUAL(rtGetControlDevices().size(), sc.control.size());
+            for (std::size_t ctrlIdx = 0; ctrlIdx < rtGetControlDevices().size(); ++ctrlIdx)
+            {
+                ControlDevice& controlDevice = *rtGetControlDevices().at(ctrlIdx);
+                ARMARX_CHECK_EQUAL(controlDevice.rtGetJointControllers().size(), sc.control.at(ctrlIdx).size());
+                for (std::size_t targIdx = 0; targIdx < controlDevice.rtGetJointControllers().size(); ++targIdx)
+                {
+                    JointController& jointCtrl = *controlDevice.rtGetJointControllers().at(targIdx);
+                    jointCtrl.getControlTarget()->_copyTo(sc.control.at(ctrlIdx).at(targIdx));
+                }
+            }
+            _module<ControlThreadDataBuffer>().rtSensorAndControlBufferCommitWrite();
+
+            rtGetThreadTimingsSensorDevice().rtMarkRtUpdateSensorAndControlBufferEnd();
+        }
+
+        const std::vector<ControlDevicePtr> &ControlThread::rtGetControlDevices()
+        {
+            return DevicesAttorneyForControlThread::GetControlDevices(this);
+        }
+
+        const std::vector<SensorDevicePtr> &ControlThread::rtGetSensorDevices()
+        {
+            return DevicesAttorneyForControlThread::GetSensorDevices(this);
+        }
+
+        RTThreadTimingsSensorDevice &ControlThread::rtGetThreadTimingsSensorDevice()
+        {
+            return DevicesAttorneyForControlThread::GetThreadTimingsSensorDevice(this);
+        }
+
+        void ControlThread::rtUpdateVirtualRobot()
+        {
+            DevicesAttorneyForControlThread::UpdateRobotWithSensorValues(this, rtRobot, rtRobotNodes);
+            for(NJointController* c: rtGetActivatedNJointControllers())
+            {
+                if(!c)
+                {
+                    break;
+                }
+                if(c->rtGetRobot())
+                {
+                    auto& from = rtRobotNodes;
+                    auto& to = c->rtGetRobotNodes();
+                    for(std::size_t i = 0; i < from.size(); ++i)
+                    {
+                        to.at(i)->copyPoseFrom(from.at(i));
+                    }
+                }
+            }
+        }
+
+        void ControlThread::_preFinishControlThreadInitialization()
+        {
+            controlThreadId = std::this_thread::get_id();
+        }
+
+        void ControlThread::_postOnInitRobotUnit()
+        {
+            try
+            {
+                rtRobot = VirtualRobot::RobotIO::loadRobot(_module<RobotData>().getRobotFileName(), VirtualRobot::RobotIO::eStructure);
+                rtRobot->setUpdateCollisionModel(false);
+                rtRobot->setUpdateVisualization(false);
+                rtRobot->setThreadsafe(false);
+                rtRobotNodes = rtRobot->getRobotNodes();
+            }
+            catch (VirtualRobot::VirtualRobotException& e)
+            {
+                throw UserException(e.what());
+            }
+        }
+
+        void ControlThread::setEmergencyStopState(EmergencyStopState state, const Ice::Current &)
+        {
+            _module<Units>().getEmergencyStopMaster()->setEmergencyStopState(state);
+        }
+
+        EmergencyStopState ControlThread::getEmergencyStopState(const Ice::Current &) const
+        {
+            return emergencyStop ? EmergencyStopState::eEmergencyStopActive : EmergencyStopState::eEmergencyStopInactive;
+        }
+
+        EmergencyStopState ControlThread::getRtEmergencyStopState(const Ice::Current &) const
+        {
+            return rtIsInEmergencyStop ? EmergencyStopState::eEmergencyStopActive : EmergencyStopState::eEmergencyStopInactive;
+        }
+
+        void ControlThread::setEmergencyStopStateNoReportToTopic(EmergencyStopState state)
+        {
+            emergencyStop = (state == EmergencyStopState::eEmergencyStopActive);
+        }
+
+        std::vector<JointController *> &ControlThread::rtGetActivatedJointControllers()
+        {
+            return ControlThreadDataBufferAttorneyForControlThread::GetActivatedJointControllers(this);
+        }
+
+        std::vector<NJointController *> &ControlThread::rtGetActivatedNJointControllers()
+        {
+            return ControlThreadDataBufferAttorneyForControlThread::GetActivatedNJointControllers(this);
+        }
+
+        void ControlThread::rtCommitActivatedControllers()
+        {
+            ControlThreadDataBufferAttorneyForControlThread::CommitActivatedControllers(this);
+        }
+
+        const std::vector<JointController *> &ControlThread::rtGetRequestedJointControllers()
+        {
+            return ControlThreadDataBufferAttorneyForControlThread::GetRequestedJointControllers(this);
+        }
+
+        const std::vector<NJointController *> &ControlThread::rtGetRequestedNJointControllers()
+        {
+            return ControlThreadDataBufferAttorneyForControlThread::GetRequestedNJointControllers(this);
+        }
+
+        std::vector<std::size_t> &ControlThread::rtGetActivatedJointToNJointControllerAssignement()
+        {
+            return ControlThreadDataBufferAttorneyForControlThread::GetActivatedJointToNJointControllerAssignement(this);
+        }
+    }
+}
diff --git a/source/RobotAPI/components/units/RobotUnit/RobotUnitModules/RobotUnitModuleControlThread.h b/source/RobotAPI/components/units/RobotUnit/RobotUnitModules/RobotUnitModuleControlThread.h
new file mode 100644
index 0000000000000000000000000000000000000000..5e901c5fdbdf2daab33348c22aa9075f92171200
--- /dev/null
+++ b/source/RobotAPI/components/units/RobotUnit/RobotUnitModules/RobotUnitModuleControlThread.h
@@ -0,0 +1,248 @@
+/*
+ * This file is part of ArmarX.
+ *
+ * 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    RobotAPI::ArmarXObjects::RobotUnit
+ * @author     Raphael Grimm ( raphael dot grimm at kit dot edu )
+ * @date       2018
+ * @copyright  http://www.gnu.org/licenses/gpl-2.0.txt
+ *             GNU General Public License
+ */
+
+#pragma once
+
+#include <thread>
+
+#include <RobotAPI/interface/units/RobotUnit/RobotUnitInterface.h>
+
+#include "../Devices/ControlDevice.h"
+#include "../Devices/SensorDevice.h"
+
+#include "RobotUnitModuleBase.h"
+
+namespace armarx
+{
+    class RTThreadTimingsSensorDevice;
+    namespace RobotUnitModule
+    {
+        /**
+         * @brief This \ref ModuleBase "Module" manages the \ref ControlThread.
+         *
+         * It offers the basic functions called in the \ref ControlThread.
+         *
+         * @see ModuleBase
+         */
+        class ControlThread : virtual public ModuleBase, virtual public RobotUnitControlThreadInterface
+        {
+            friend class ModuleBase;
+        public:
+            /**
+             * @brief Returns the singleton instance of this class
+             * @return The singleton instance of this class
+             */
+            static ControlThread& Instance()
+            {
+                return ModuleBase::Instance<ControlThread>();
+            }
+            // //////////////////////////////////////////////////////////////////////////////////////// //
+            // ///////////////////////////////// RobotUnitModule hooks //////////////////////////////// //
+            // //////////////////////////////////////////////////////////////////////////////////////// //
+        private:
+            ///@see \ref ModuleBase::_preFinishControlThreadInitialization
+            void _preFinishControlThreadInitialization();
+            ///@see \ref ModuleBase::_postOnInitRobotUnit
+            void _postOnInitRobotUnit();
+            // //////////////////////////////////////////////////////////////////////////////////////// //
+            // ///////////////////////////////////// ice interface //////////////////////////////////// //
+            // //////////////////////////////////////////////////////////////////////////////////////// //
+        public:
+            /**
+             * @brief Sets the \ref EmergencyStopState
+             * @param state The \ref EmergencyStopState to set
+             */
+            void setEmergencyStopState(EmergencyStopState state, const Ice::Current& = GlobalIceCurrent) override;
+            /**
+             * @brief Returns the \ref ControlThread's target \ref EmergencyStopState
+             * @return The \ref EmergencyStopState
+             */
+            EmergencyStopState getEmergencyStopState(const Ice::Current& = GlobalIceCurrent) const override;
+            /**
+             * @brief Returns the \ref ControlThread's \ref EmergencyStopState
+             * @return The \ref EmergencyStopState
+             */
+            EmergencyStopState getRtEmergencyStopState(const Ice::Current& = GlobalIceCurrent) const override;
+            // //////////////////////////////////////////////////////////////////////////////////////// //
+            // /////////////////////////////////// Module interface /////////////////////////////////// //
+            // //////////////////////////////////////////////////////////////////////////////////////// //
+        public:
+            /**
+             * @brief Sets the \ref EmergencyStopState without updating the topic
+             * @param state The \ref EmergencyStopState to set
+             */
+            void setEmergencyStopStateNoReportToTopic(EmergencyStopState state);
+            /**
+             * @brief Teturns he \ref ControlThread's thread id
+             * @return The \ref ControlThread's thread id
+             * @see controlThreadId
+             */
+            std::thread::id getControlThreadId() const
+            {
+                return controlThreadId;
+            }
+            // //////////////////////////////////////////////////////////////////////////////////////// //
+            // ///////////////////////////////////// rt interface ///////////////////////////////////// //
+            // //////////////////////////////////////////////////////////////////////////////////////// //
+        protected:
+            /**
+             * @brief Returns the simox robot used in the control thread
+             * @return The simox robot used in the control thread
+             */
+            const VirtualRobot::RobotPtr& rtGetRobot() const
+            {
+                return rtRobot;
+            }
+            /**
+             * @brief Changes the set of active controllers.
+             * Changes can be caused by a new set of requested controllers or emergency stop
+             * @return Whether active controllers were changed
+             */
+            bool rtSwitchControllerSetup();
+
+            /**
+             * @brief rtDeactivateAssignedNJointControllerBecauseOfError
+             * @param ctrlDevIndex
+             * @param writeActivatedControlers
+             */
+            void rtDeactivateAssignedNJointControllerBecauseOfError(std::size_t ctrlDevIndex, bool writeActivatedControlers = true);
+            /**
+             * @brief Deactivates a NJointController and sets all used ControlDevices to EmergencyStop
+             * @param nJointCtrlIndex The NJointController to deactivate (index in controllersActivated)
+             * @param writeActivatedControlers Whether controllersActivated should be committed
+             */
+            void rtDeactivateNJointControllerBecauseOfError(std::size_t nJointCtrlIndex, bool writeActivatedControlers = true);
+            /**
+             * @brief Runs NJoint controllers
+             * @param sensorValuesTimestamp Timestamp of the current \ref SensorValueBase SensorValues
+             * @param timeSinceLastIteration Time between the last two updates of \ref SensorValueBase SensorValues
+             */
+            void rtRunNJointControllers(const IceUtil::Time& sensorValuesTimestamp, const IceUtil::Time& timeSinceLastIteration);
+            /**
+             * @brief Runs Joint controllers and writes target values to ControlDevices
+             * @param sensorValuesTimestamp Timestamp of the current \ref SensorValueBase SensorValues
+             * @param timeSinceLastIteration Time between the last two updates of \ref SensorValueBase SensorValues
+             */
+            void rtRunJointControllers(const IceUtil::Time& sensorValuesTimestamp, const IceUtil::Time& timeSinceLastIteration);
+            /**
+             * @brief Calls \ref SensorDevice::rtReadSensorValues for all \ref SensorDevice "SensorDevices".
+             * @param sensorValuesTimestamp Timestamp of the current \ref SensorValueBase SensorValues
+             * @param timeSinceLastIteration Time between the last two updates of \ref SensorValueBase SensorValues
+             */
+            void rtReadSensorDeviceValues(const IceUtil::Time& sensorValuesTimestamp, const IceUtil::Time& timeSinceLastIteration);
+            /// @brief Deactivates all NJointControllers generating invalid targets.
+            void rtHandleInvalidTargets();
+            /// @brief Calls \ref JointController::rtResetTarget for all active Joint controllers
+            void rtResetAllTargets();
+            /**
+             * @brief Hook for deriving classes (called AFTER a NJointController is deactivated due to an error)
+             *
+             * This is useful when two Control devices can be controlled by different NJointControllers but either both or none
+             * have to be controlled.
+             *
+             * Since this hook is called after the controller with an error was deactivated an other call to
+             * \ref rtDeactivateAssignedNJointControllerBecauseOfError can't lead to a cyclic execution.
+             */
+            virtual void rtDeactivatedNJointControllerBecauseOfError(const NJointControllerPtr& /*nJointCtrl*/){}
+            /**
+             * @brief Updates the current \ref SensorValueBase "SensorValues" and \ref ControlTargetBase "ControlTargets"
+             * for code running outside of the \ref ControlThread
+             * @param sensorValuesTimestamp Timestamp of the current \ref SensorValueBase SensorValues
+             * @param timeSinceLastIteration Time between the last two updates of \ref SensorValueBase SensorValues
+             */
+            void rtUpdateSensorAndControlBuffer(const IceUtil::Time& sensorValuesTimestamp, const IceUtil::Time& timeSinceLastIteration);
+
+            /**
+             * @brief Returns all \ref ControlDevice "ControlDevices"
+             * @return All \ref ControlDevice "ControlDevices"
+             */
+            const std::vector<ControlDevicePtr>& rtGetControlDevices();
+            /**
+             * @brief Returns all \ref SensorDevice "SensorDevices"
+             * @return All \ref SensorDevice "SensorDevices"
+             */
+            const std::vector<SensorDevicePtr>& rtGetSensorDevices();
+            /**
+             * @brief Returns the \ref RTThreadTimingsSensorDevice
+             * @return The \ref RTThreadTimingsSensorDevice
+             */
+            RTThreadTimingsSensorDevice& rtGetThreadTimingsSensorDevice();
+
+            /// @brief Updates the \ref VirtualRobot::Robot used in the \ref ControlThread with the current \ref SensorValueBase SensorValues
+            void rtUpdateVirtualRobot();
+            // //////////////////////////////////////////////////////////////////////////////////////// //
+            // //////////////////////////////////// implementation //////////////////////////////////// //
+            // //////////////////////////////////////////////////////////////////////////////////////// //
+        private:
+            /**
+             * @brief Returns the activated \ref JointController "JointControllers"
+             * @return The activated \ref JointController "JointControllers"
+             */
+            std::vector<JointController*>& rtGetActivatedJointControllers();
+            /**
+             * @brief Returns the activated \ref NJointController "NJointControllers"
+             * @return The activated \ref NJointController "NJointControllers"
+             */
+            std::vector<NJointController*>& rtGetActivatedNJointControllers();
+            /**
+             * @brief Writes the activated \ref NJointController "NJointControllers" and
+             * \ref JointController "JointControllers" to the output buffer.
+             */
+            void rtCommitActivatedControllers();
+
+            /**
+             * @brief Returns the requested \ref JointController "JointControllers"
+             * @return The requested \ref JointController "JointControllers"
+             */
+            const std::vector<JointController*>& rtGetRequestedJointControllers();
+            /**
+             * @brief Returns the requested \ref NJointController "NJointControllers"
+             * @return The requested \ref NJointController "NJointControllers"
+             */
+            const std::vector<NJointController*>& rtGetRequestedNJointControllers();
+
+            /**
+             * @brief Returns a vector containing the index of the activated \ref NJointController
+             * for each \ref JointController
+             * @return A vector containing the index of the activated \ref NJointController
+             * for each \ref JointController
+             */
+            std::vector<std::size_t>& rtGetActivatedJointToNJointControllerAssignement();
+            // //////////////////////////////////////////////////////////////////////////////////////// //
+            // ///////////////////////////////////////// Data ///////////////////////////////////////// //
+            // //////////////////////////////////////////////////////////////////////////////////////// //
+        private:
+            ///@brief Whether the ControlThread is in emergency stop
+            std::atomic_bool rtIsInEmergencyStop {false};
+            ///@brief Whether the ControlThread is supposed to be in emergency stop
+            std::atomic_bool emergencyStop {false};
+
+            ///@brief The \ref VirtualRobot::Robot used in the \ref ControlThread
+            VirtualRobot::RobotPtr rtRobot;
+            ///@brief The \ref VirtualRobot::Robot's \ref VirtualRobot::RobotNode "VirtualRobot::RobotNode" used in the \ref ControlThread
+            std::vector<VirtualRobot::RobotNodePtr> rtRobotNodes;
+
+            ///@brief The \ref ControlThread's thread id
+            std::atomic<std::thread::id> controlThreadId;
+        };
+    }
+}
diff --git a/source/RobotAPI/components/units/RobotUnit/RobotUnitModules/RobotUnitModuleControlThreadDataBuffer.cpp b/source/RobotAPI/components/units/RobotUnit/RobotUnitModules/RobotUnitModuleControlThreadDataBuffer.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..24ca950bf4eace1d3c5d6cbbfa63d41ea7198943
--- /dev/null
+++ b/source/RobotAPI/components/units/RobotUnit/RobotUnitModules/RobotUnitModuleControlThreadDataBuffer.cpp
@@ -0,0 +1,319 @@
+/*
+ * This file is part of ArmarX.
+ *
+ * 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    RobotAPI::ArmarXObjects::RobotUnit
+ * @author     Raphael Grimm ( raphael dot grimm at kit dot edu )
+ * @date       2018
+ * @copyright  http://www.gnu.org/licenses/gpl-2.0.txt
+ *             GNU General Public License
+ */
+
+#include "RobotUnitModuleControlThreadDataBuffer.h"
+
+#include "RobotUnitModuleControllerManagement.h"
+#include "RobotUnitModuleDevices.h"
+
+#include "../NJointControllers/NJointController.h"
+
+namespace armarx
+{
+    namespace RobotUnitModule
+    {
+        /**
+         * \brief This class allows minimal access to private members of \ref Devices in a sane fashion for \ref ControlThreadDataBuffer.
+         * \warning !! DO NOT ADD ANYTHING IF YOU DO NOT KNOW WAHT YOU ARE DOING! IF YOU DO SOMETHING WRONG YOU WILL CAUSE UNDEFINED BEHAVIOUR !!
+         */
+        class DevicesAttorneyForControlThreadDataBuffer
+        {
+            friend class ControlThreadDataBuffer;
+            static std::vector<JointController*> GetStopMovementJointControllers(ControlThreadDataBuffer* p)
+            {
+                return p->_module<Devices>().getStopMovementJointControllers();
+            }
+        };
+        /**
+         * \brief This class allows minimal access to private members of \ref ControllerManagement in a sane fashion for \ref ControlThreadDataBuffer.
+         * \warning !! DO NOT ADD ANYTHING IF YOU DO NOT KNOW WAHT YOU ARE DOING! IF YOU DO SOMETHING WRONG YOU WILL CAUSE UNDEFINED BEHAVIOUR !!
+         */
+        class ControllerManagementAttorneyForControlThreadDataBuffer
+        {
+            friend class ControlThreadDataBuffer;
+
+            static void UpdateNJointControllerRequestedState(ControlThreadDataBuffer* p, const std::set<NJointControllerPtr>& request)
+            {
+                p->_module<ControllerManagement>().updateNJointControllerRequestedState(request);
+            }
+        };
+    }
+}
+
+namespace armarx
+{
+    namespace RobotUnitModule
+    {
+        JointAndNJointControllers ControlThreadDataBuffer::getActivatedControllers() const
+        {
+            throwIfDevicesNotReady(__FUNCTION__);
+            std::lock_guard<std::recursive_mutex> guard{controllersActivatedMutex};
+            return controllersActivated.getReadBuffer();
+        }
+
+        std::vector<JointController *> ControlThreadDataBuffer::getActivatedJointControllers() const
+        {
+            throwIfDevicesNotReady(__FUNCTION__);
+            std::lock_guard<std::recursive_mutex> guard{controllersActivatedMutex};
+            return controllersActivated.getReadBuffer().jointControllers;
+        }
+
+        std::vector<NJointController *> ControlThreadDataBuffer::getActivatedNJointControllers() const
+        {
+            throwIfDevicesNotReady(__FUNCTION__);
+            std::lock_guard<std::recursive_mutex> guard{controllersActivatedMutex};
+            return controllersActivated.getReadBuffer().nJointControllers;
+        }
+        bool ControlThreadDataBuffer::activatedControllersChanged() const
+        {
+            throwIfDevicesNotReady(__FUNCTION__);
+            std::lock_guard<std::recursive_mutex> guard{controllersActivatedMutex};
+            return controllersActivated.updateReadBuffer();
+        }
+
+        JointAndNJointControllers ControlThreadDataBuffer::getRequestedControllers() const
+        {
+            throwIfDevicesNotReady(__FUNCTION__);
+            std::lock_guard<std::recursive_mutex> guard{controllersRequestedMutex};
+            return controllersRequested.getWriteBuffer();
+        }
+
+        std::vector<JointController *> ControlThreadDataBuffer::getRequestedJointControllers() const
+        {
+            throwIfDevicesNotReady(__FUNCTION__);
+            std::lock_guard<std::recursive_mutex> guard{controllersRequestedMutex};
+            return controllersRequested.getWriteBuffer().jointControllers;
+        }
+
+        std::vector<NJointController *> ControlThreadDataBuffer::getRequestedNJointControllers() const
+        {
+            throwIfDevicesNotReady(__FUNCTION__);
+            std::lock_guard<std::recursive_mutex> guard{controllersRequestedMutex};
+            return controllersRequested.getWriteBuffer().nJointControllers;
+        }
+
+        bool ControlThreadDataBuffer::sensorAndControlBufferChanged() const
+        {
+            auto guard = getGuard();
+            throwIfDevicesNotReady(__FUNCTION__);
+            return controlThreadOutputBuffer.updateReadBuffer();
+        }
+
+        const SensorAndControl &ControlThreadDataBuffer::getSensorAndControlBuffer() const
+        {
+            auto guard = getGuard();
+            throwIfDevicesNotReady(__FUNCTION__);
+            return controlThreadOutputBuffer.getReadBuffer();
+        }
+
+        void ControlThreadDataBuffer::writeRequestedControllers(JointAndNJointControllers&& setOfControllers)
+        {
+            auto guard = getGuard();
+            throwIfDevicesNotReady(__FUNCTION__);
+            //check NJoint
+            const auto& nJointCtrls = setOfControllers.nJointControllers;
+            std::set<NJointControllerPtr> nJointSet {nJointCtrls.begin(), nJointCtrls.end()};
+                nJointSet.erase(nullptr);
+                //# NJoint
+                const std::size_t nNJointCtrls = std::count_if(nJointCtrls.begin(), nJointCtrls.end(), [](const NJointControllerPtr & p)
+                {
+                    return p;
+                });
+
+                ARMARX_CHECK_EXPRESSION(nNJointCtrls == nJointSet.size());
+                ARMARX_CHECK_EXPRESSION(nJointCtrls.size() == _module<Devices>().getNumberOfControlDevices());
+                //first nNJointCtrls not null
+                ARMARX_CHECK_EXPRESSION(std::all_of(nJointCtrls.begin(), nJointCtrls.begin() + nNJointCtrls, [](NJointController * p)
+                {
+                                            return p;
+                                        }));
+                //last getNumberOfControlDevices()-nNJointCtrls null
+                ARMARX_CHECK_EXPRESSION(std::all_of(nJointCtrls.begin() + nNJointCtrls, nJointCtrls.end(), [](NJointController * p)
+                {
+                                            return !p;
+                                        }));
+                //conflict free and sorted
+                ARMARX_CHECK_EXPRESSION(std::is_sorted(nJointCtrls.begin(), nJointCtrls.end(), std::greater<NJointController*>{}));
+                ARMARX_CHECK_EXPRESSION(NJointController::AreNotInConflict(nJointCtrls.begin(), nJointCtrls.begin() + nNJointCtrls));
+
+                //check JointCtrl
+                const auto& jointCtrls = setOfControllers.jointControllers;
+                ARMARX_CHECK_EXPRESSION(jointCtrls.size() == _module<Devices>().getNumberOfControlDevices());
+                ARMARX_CHECK_EXPRESSION(std::all_of(jointCtrls.begin(), jointCtrls.end(), [](JointController * p)
+                {
+                                            return p;
+                                        }));
+
+                //check groups
+                {
+                    ARMARX_DEBUG << "check groups";
+                    std::size_t grpIdx = 0;
+                    for (const auto& group : _module<Devices>().getControlModeGroups().groups)
+                    {
+                        ARMARX_CHECK_EXPRESSION(!group.empty());
+                        const auto hwMode = setOfControllers.jointControllers.at(_module<Devices>().getControlDeviceIndex(*group.begin()))->getHardwareControlMode();
+                        ARMARX_DEBUG << "---- group " << grpIdx << " mode '" << hwMode << "'";
+                        for (const auto& other : group)
+                        {
+                            const auto& dev = _module<Devices>().getControlDeviceIndex(other);
+                            ARMARX_CHECK_EXPRESSION(dev);
+                            const auto otherHwMode = setOfControllers.jointControllers.at(dev)->getHardwareControlMode();
+                            ARMARX_DEBUG << "-------- '" << other << "'' mode '" << otherHwMode << "'";
+                            ARMARX_CHECK_EXPRESSION(otherHwMode == hwMode);
+                        }
+                        ++grpIdx;
+                    }
+                }
+                //setup assignement
+                {
+                    ARMARX_DEBUG << "setup assignement index";
+                    setOfControllers.resetAssignement();
+                    for (std::size_t nJointCtrlIndex = 0; nJointCtrlIndex < setOfControllers.nJointControllers.size(); ++nJointCtrlIndex)
+                    {
+                        const NJointController* nJoint = setOfControllers.nJointControllers.at(nJointCtrlIndex);
+                        if (!nJoint)
+                        {
+                            break;
+                        }
+                        ARMARX_DEBUG << "---- " << nJoint->getInstanceName();
+                        for (std::size_t jointIndex : nJoint->getControlDeviceUsedIndices())
+                        {
+                            ARMARX_DEBUG << "-------- Index " << jointIndex << ": " << setOfControllers.jointToNJointControllerAssignement.at(jointIndex) << "-> " << nJointCtrlIndex;
+                            ARMARX_CHECK_EXPRESSION(setOfControllers.jointToNJointControllerAssignement.at(jointIndex) == IndexSentinel());
+                            setOfControllers.jointToNJointControllerAssignement.at(jointIndex) = nJointCtrlIndex;
+                        }
+                    }
+                }
+
+                {
+                    ARMARX_DEBUG << "call checkSetOfControllersToActivate";
+                    checkSetOfControllersToActivate(setOfControllers);
+                }
+                //set requested state
+                ControllerManagementAttorneyForControlThreadDataBuffer::UpdateNJointControllerRequestedState(this, nJointSet);
+
+                ARMARX_CHECK_EQUAL(_module<Devices>().getNumberOfControlDevices(), setOfControllers.jointControllers.size());
+                ARMARX_CHECK_EQUAL(_module<Devices>().getNumberOfControlDevices(), setOfControllers.nJointControllers.size());
+                ARMARX_CHECK_EQUAL(_module<Devices>().getNumberOfControlDevices(), setOfControllers.jointToNJointControllerAssignement.size());                
+                {
+                    std::lock_guard<std::recursive_mutex> guard{controllersRequestedMutex};
+                    controllersRequested.getWriteBuffer() = std::move(setOfControllers);
+                    controllersRequested.commitWrite();
+                }
+                ARMARX_DEBUG << "writeRequestedControllers(JointAndNJointControllers&& setOfControllers)...done!";
+        }
+
+        void ControlThreadDataBuffer::setActivateControllersRequest(std::set<NJointControllerPtr, std::greater<NJointControllerPtr>> ctrls)
+        {
+            auto guard = getGuard();
+            throwIfDevicesNotReady(__FUNCTION__);
+            //erase nullptr
+            ctrls.erase(nullptr);
+            ARMARX_CHECK_EXPRESSION(ctrls.size() <= _module<Devices>().getNumberOfControlDevices());
+            const std::set<NJointControllerPtr, std::greater<NJointControllerPtr>> setOfRequestedCtrls
+            {
+               getRequestedNJointControllers().begin(),
+               getRequestedNJointControllers().end()
+        }   ;
+            if (setOfRequestedCtrls == ctrls)
+            {
+                //redirty the flag to swap in the same set again
+                controllersRequested.commitWrite();
+                return;
+            }
+            JointAndNJointControllers request {_module<Devices>().getNumberOfControlDevices()};
+            std::size_t idx = 0;
+            for (const NJointControllerPtr& nJointCtrl : ctrls)
+            {
+                request.nJointControllers.at(idx++) = nJointCtrl.get();
+                //add Joint for this ctrl
+                for (const auto& cd2cm : nJointCtrl->getControlDeviceUsedControlModeMap())
+                {
+                    std::size_t jointCtrlIndex = _module<Devices>().getControlDevices().index(cd2cm.first);
+                    if (request.jointControllers.at(jointCtrlIndex))
+                    {
+                        std::stringstream ss;
+                        ss << "RobotUnit:setActivateControllersRequest controllers to activate are in conflict!\ncontrollers:";
+                        for (const auto& ctrl : ctrls)
+                        {
+                            ss << "\n" << ctrl->getInstanceName();
+                        }
+                        ARMARX_ERROR << ss.str();
+                        throw InvalidArgumentException {ss.str()};
+                    }
+                    request.jointControllers.at(jointCtrlIndex) = _module<Devices>().getControlDevices().at(jointCtrlIndex)->getJointController(cd2cm.second);
+                }
+            }
+            for (auto i : getIndices(request.jointControllers))
+            {
+                JointController*& jointCtrl = request.jointControllers.at(i);
+                if (!jointCtrl)
+                {
+                    JointController* jointCtrlOld = getRequestedJointControllers().at(i);
+                    if (jointCtrlOld == _module<Devices>().getControlDevices().at(i)->getJointStopMovementController())
+                    {
+                        //don't replace this controller with emergency stop
+                        jointCtrl = jointCtrlOld;
+                    }
+                    else
+                    {
+                        //no one controls this device -> emergency stop
+                        jointCtrl = _module<Devices>().getControlDevices().at(i)->getJointEmergencyStopController();
+                    }
+                }
+            }
+            writeRequestedControllers(std::move(request));
+            ARMARX_DEBUG << "wrote requested controllers";
+            ARMARX_INFO << "requested controllers:\n" << _module<ControllerManagement>().getRequestedNJointControllerNames();
+        }
+
+        void ControlThreadDataBuffer::updateVirtualRobot(const VirtualRobot::RobotPtr &robot, const std::vector<VirtualRobot::RobotNodePtr> &nodes) const
+        {
+            _module<Devices>().updateVirtualRobotFromSensorValues(robot, nodes, controlThreadOutputBuffer.getReadBuffer().sensors);
+        }
+
+        void ControlThreadDataBuffer::updateVirtualRobot(const VirtualRobot::RobotPtr &robot) const
+        {
+            _module<Devices>().updateVirtualRobotFromSensorValues(robot, controlThreadOutputBuffer.getReadBuffer().sensors);
+        }
+        void ControlThreadDataBuffer::_postFinishDeviceInitialization()
+        {
+            ARMARX_DEBUG << "initializing buffers:";
+            {
+                ARMARX_DEBUG << "----initializing controller buffers for " << _module<Devices>().getNumberOfControlDevices() << " control devices";
+
+                JointAndNJointControllers ctrlinitReq(_module<Devices>().getNumberOfControlDevices());
+                ARMARX_CHECK_EQUAL(_module<Devices>().getNumberOfControlDevices(), ctrlinitReq.jointControllers.size());
+                ARMARX_CHECK_EQUAL(_module<Devices>().getNumberOfControlDevices(), ctrlinitReq.nJointControllers.size());
+                ARMARX_CHECK_EQUAL(_module<Devices>().getNumberOfControlDevices(), ctrlinitReq.jointToNJointControllerAssignement.size());
+                controllersActivated.reinitAllBuffers(ctrlinitReq);
+
+                ctrlinitReq.jointControllers = DevicesAttorneyForControlThreadDataBuffer::GetStopMovementJointControllers(this);
+                ARMARX_CHECK_EQUAL(_module<Devices>().getNumberOfControlDevices(), ctrlinitReq.jointControllers.size());
+                ARMARX_CHECK_EQUAL(_module<Devices>().getNumberOfControlDevices(), ctrlinitReq.nJointControllers.size());
+                ARMARX_CHECK_EQUAL(_module<Devices>().getNumberOfControlDevices(), ctrlinitReq.jointToNJointControllerAssignement.size());
+                controllersRequested.reinitAllBuffers(ctrlinitReq);
+                controllersRequested.commitWrite();//to make sure the diry bit is activated (to trigger rt switch)
+            }
+        }
+    }
+}
diff --git a/source/RobotAPI/components/units/RobotUnit/RobotUnitModules/RobotUnitModuleControlThreadDataBuffer.h b/source/RobotAPI/components/units/RobotUnit/RobotUnitModules/RobotUnitModuleControlThreadDataBuffer.h
new file mode 100644
index 0000000000000000000000000000000000000000..962593d12c33bca0d5c7f3893948d35b97bb3c2d
--- /dev/null
+++ b/source/RobotAPI/components/units/RobotUnit/RobotUnitModules/RobotUnitModuleControlThreadDataBuffer.h
@@ -0,0 +1,281 @@
+/*
+ * This file is part of ArmarX.
+ *
+ * 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    RobotAPI::ArmarXObjects::RobotUnit
+ * @author     Raphael Grimm ( raphael dot grimm at kit dot edu )
+ * @date       2018
+ * @copyright  http://www.gnu.org/licenses/gpl-2.0.txt
+ *             GNU General Public License
+ */
+
+#pragma once
+
+#include <VirtualRobot/Robot.h>
+
+#include <ArmarXCore/core/util/TripleBuffer.h>
+
+#include <RobotAPI/interface/units/RobotUnit/RobotUnitInterface.h>
+
+#include "RobotUnitModuleBase.h"
+#include "../util/JointAndNJointControllers.h"
+#include "../util/ControlThreadOutputBuffer.h"
+
+#include "../SensorValues/SensorValue1DoFActuator.h"
+
+namespace armarx
+{
+    class SensorValue1DoFActuatorPosition;
+
+    namespace RobotUnitModule
+    {
+        /**
+         * @brief This \ref ModuleBase "Module" manages all communication into and out of the \ref ControlThread.
+         *
+         * \section buffers Data Buffers
+         * This class holds three data buffers
+         *
+         * \subsection bufferreq Buffer for requested controllers
+         * \note This buffer's direction is ArmarX -> \ref ControlThread
+         *
+         * This buffer contains all \ref NJointController "NJointControllers"
+         * requested by the user (e.g.: via \ref NJointController::activate) and
+         * the set of \ref JointController "JointControllers" implicitly defined by this.
+         * These controllers will be activated by \ref ControlThread::rtSwitchControllerSetup.
+         *
+         *
+         * \subsection bufferact Buffer for activated controllers
+         * \note This buffer's direction is \ref ControlThread -> ArmarX
+         *
+         * This buffer contains all \ref JointController "Joint-" and
+         * \ref NJointController "NJointControllers" executed by the \ref ControlThread.
+         *
+         *
+         * \subsection bufferout Buffer for iteration data
+         * \note This buffer's direction is \ref ControlThread -> ArmarX
+         *
+         * This buffer contains all \ref SensorValueBase "SensorValues" and \ref ControlTargetBase "ControlTargets"
+         * for each iteration.
+         * It also contains messages logged via \ref ARMARX_RT_LOGF.
+         *
+         * This data is used to update \ref Units and is reported to topics (see \ref Publish).
+         *
+         * This buffer is organized as a ringbuffer and holds several old iterations.
+         *
+         * @see ModuleBase
+         */
+        class ControlThreadDataBuffer : virtual public ModuleBase
+        {
+            friend class ModuleBase;
+        public:
+            /**
+             * @brief Returns the singleton instance of this class
+             * @return The singleton instance of this class
+             */
+            static ControlThreadDataBuffer& Instance()
+            {
+                return ModuleBase::Instance<ControlThreadDataBuffer>();
+            }
+            // //////////////////////////////////////////////////////////////////////////////////////// //
+            // ///////////////////////////////// RobotUnitModule hooks //////////////////////////////// //
+            // //////////////////////////////////////////////////////////////////////////////////////// //
+        private:
+            /// @see ModuleBase::_postFinishDeviceInitialization
+            void _postFinishDeviceInitialization();
+            // //////////////////////////////////////////////////////////////////////////////////////// //
+            // /////////////////////////////////// Module interface /////////////////////////////////// //
+            // //////////////////////////////////////////////////////////////////////////////////////// //
+        public:
+            /**
+             * @brief Updates the given VirtualRobot with the current joint values
+             * @param robot The robot to update
+             */
+            void updateVirtualRobot(const VirtualRobot::RobotPtr& robot) const;
+            /**
+             * @brief Updates the given VirtualRobot with the current joint values
+             * @param robot The robot to update
+             * @param nodes The robot's nodes
+             */
+            void updateVirtualRobot(const VirtualRobot::RobotPtr& robot, const std::vector<VirtualRobot::RobotNodePtr>& nodes) const;
+
+            /**
+             * @brief Returns whether the set of activated \ref JointController "Joint-" and
+             * \ref NJointController "NJointControllers" changed.
+             * @return Whether the set of activated \ref JointController "Joint-" and
+             * \ref NJointController "NJointControllers" changed.
+             * @see ControlThread
+             * @see ControlThread::rtSwitchControllerSetup
+             */
+            bool activatedControllersChanged() const; ///TODO private + attorney for publish
+            /**
+             * @brief Returns the set of activated \ref JointController "Joint-" and
+             * \ref NJointController "NJointControllers".
+             * @return The set of activated \ref JointController "Joint-" and
+             * \ref NJointController "NJointControllers".
+             * @see ControlThread
+             * @see ControlThread::rtSwitchControllerSetup
+             */
+            JointAndNJointControllers getActivatedControllers() const;
+            /**
+             * @brief Returns the set of activated \ref JointController "JointControllers".
+             * @return The set of activated \ref JointController "JointControllers".
+             * @see ControlThread
+             * @see ControlThread::rtSwitchControllerSetup
+             */
+            std::vector<JointController*> getActivatedJointControllers() const;
+            /**
+             * @brief Returns the set of activated \ref NJointController "NJointControllers".
+             * @return The set of activated \ref NJointController "NJointControllers".
+             * @see ControlThread
+             * @see ControlThread::rtSwitchControllerSetup
+             */
+            std::vector<NJointController*> getActivatedNJointControllers() const;
+
+            /**
+             * @brief Returns the set of requsted \ref JointController "Joint-" and
+             * \ref NJointController "NJointControllers".
+             * @return The set of requested \ref JointController "Joint-" and
+             * \ref NJointController "NJointControllers".
+             * @see ControllerManagement
+             * @see ControllerManagement::activateNJointController
+             * @see ControllerManagement::deactivateNJointController
+             * @see ControllerManagement::switchNJointControllerSetup
+             * @see NJointController::activateController
+             * @see NJointController::deactivateController
+             * @see setActivateControllersRequest
+             */
+            JointAndNJointControllers getRequestedControllers() const;
+            /**
+             * @brief Returns the set of requsted \ref JointController "JointControllers".
+             * @return The set of requested \ref JointController "JointControllers".
+             * @see ControllerManagement
+             * @see ControllerManagement::activateNJointController
+             * @see ControllerManagement::deactivateNJointController
+             * @see ControllerManagement::switchNJointControllerSetup
+             * @see NJointController::activateController
+             * @see NJointController::deactivateController
+             * @see setActivateControllersRequest
+             */
+            std::vector<JointController*> getRequestedJointControllers() const;
+            /**
+             * @brief Returns the set of requsted \ref NJointController "NJointControllers".
+             * @return The set of requested \ref NJointController "NJointControllers".
+             * @see ControllerManagement
+             * @see ControllerManagement::activateNJointController
+             * @see ControllerManagement::deactivateNJointController
+             * @see ControllerManagement::switchNJointControllerSetup
+             * @see NJointController::activateController
+             * @see NJointController::deactivateController
+             * @see setActivateControllersRequest
+             */
+            std::vector<NJointController *> getRequestedNJointControllers() const;
+
+            /**
+             * @brief Updates the sensor and control buffer and returns whether the buffer was updated.
+             * @return Whether the buffer was updated.
+             */
+            bool sensorAndControlBufferChanged() const; /// TODO private + attorney for publish
+            /**
+             * @brief Returns the last updated sensor and control buffer.
+             * @return The last updated sensor and control buffer.
+             */
+            const SensorAndControl& getSensorAndControlBuffer() const;
+
+            /**
+             * @brief Returns the \ref ControlThreadOutputBuffer
+             * \warning This function is dangerous to use.
+             * @return The \ref ControlThreadOutputBuffer
+             */
+            ControlThreadOutputBuffer& getControlThreadOutputBuffer() ///TODO refactor logging and remove this function
+            {
+                return controlThreadOutputBuffer;
+            }
+
+            /**
+             * @brief Returns the writer buffer for sensor and control values.
+             * @return The writer buffer for sensor and control values.
+             */
+            SensorAndControl& rtGetSensorAndControlBuffer() ///TODO move to attorney
+            {
+                return controlThreadOutputBuffer.getWriteBuffer();
+            }
+            /**
+             * @brief Commits the writer buffer for sensor and control values.
+             */
+            void rtSensorAndControlBufferCommitWrite() ///TODO move to attorney
+            {
+                return controlThreadOutputBuffer.commitWrite();
+            }
+
+            /**
+             * @brief Sets the set of requested \ref NJointController "NJointControllers" to \param ctrls.
+             * @param ctrls \ref NJointController "NJointControllers" requested.
+             * @see ControllerManagement
+             * @see ControllerManagement::activateNJointController
+             * @see ControllerManagement::deactivateNJointController
+             * @see ControllerManagement::switchNJointControllerSetup
+             * @see NJointController::activateController
+             * @see NJointController::deactivateController
+             */
+            void setActivateControllersRequest(std::set<NJointControllerPtr, std::greater<NJointControllerPtr> > ctrls);
+            // //////////////////////////////////////////////////////////////////////////////////////// //
+            // //////////////////////////////////// implementation //////////////////////////////////// //
+            // //////////////////////////////////////////////////////////////////////////////////////// //
+        protected:
+            /**
+             * @brief This hook is called prior to writing the set of requested controllers.
+             * A deriving class can override this function to perform some additional checks
+             * (e.g. two controll devices may always need to have the same control mode, this can be checked here)
+             * If any check fails, throw an exception with a descriptive message.
+             * @param controllers The controllers to activate
+             */
+            virtual void checkSetOfControllersToActivate(const JointAndNJointControllers& /*controllers*/) const {}
+        private:
+            void writeRequestedControllers(JointAndNJointControllers&& setOfControllers);
+
+            // //////////////////////////////////////////////////////////////////////////////////////// //
+            // ///////////////////////////////////////// Data ///////////////////////////////////////// //
+            // //////////////////////////////////////////////////////////////////////////////////////// //
+        private:
+            /// @brief Controllers the RT thread is supposed to activate (direction nonRT -> RT) (some NJoint controllers may be null)
+            /// data may only be used after State::InitializingDevices
+            /// all NJointController have to be sorted by id (null controllers are at the end)
+            WriteBufferedTripleBuffer<JointAndNJointControllers> controllersRequested;
+            /// @brief Mutex guarding \ref controllersRequested
+            mutable std::recursive_mutex controllersRequestedMutex;
+
+            /// @brief Controllers the RT thread is currently running (direction RT -> nonRT) (some NJoint controllers may be null)
+            /// data may only be used after State::InitializingDevices
+            /// all NJointController are sorted by id (null controllers may be anywhere)
+            WriteBufferedTripleBuffer<JointAndNJointControllers> controllersActivated;
+            /// @brief Mutex guarding \ref controllersActivated
+            mutable std::recursive_mutex controllersActivatedMutex;
+
+            /// @brief Transfers Data  (current sensor values and control targets) from the control thread to other threads (direction RT -> nonRT)
+            /// \warning DO NOT ACCESS EXCEPT YOU KNOW WHAT YOU ARE DOING!
+            ControlThreadOutputBuffer controlThreadOutputBuffer;
+            /// @brief Mutex guarding \ref controlThreadOutputBuffer
+            mutable std::recursive_mutex controlThreadOutputBufferMutex; /// TODO use this mutex instead of the global one
+            // //////////////////////////////////////////////////////////////////////////////////////// //
+            // /////////////////////////////////////// Attorneys ////////////////////////////////////// //
+            // //////////////////////////////////////////////////////////////////////////////////////// //
+        private:
+            /**
+            * \brief This class allows minimal access to private members of \ref ControlThreadDataBuffer in a sane fashion for \ref ControlThread.
+            * \warning !! DO NOT ADD ADDITIONAL FRIENDS IF YOU DO NOT KNOW WAHT YOU ARE DOING! IF YOU DO SOMETHING WRONG YOU WILL CAUSE UNDEFINED BEHAVIOUR !!
+            */
+            friend class ControlThreadDataBufferAttorneyForControlThread;
+        };
+    }
+}
diff --git a/source/RobotAPI/components/units/RobotUnit/RobotUnitModules/RobotUnitModuleControllerManagement.cpp b/source/RobotAPI/components/units/RobotUnit/RobotUnitModules/RobotUnitModuleControllerManagement.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..33716271d1331d1608e64bc00aa702061025a872
--- /dev/null
+++ b/source/RobotAPI/components/units/RobotUnit/RobotUnitModules/RobotUnitModuleControllerManagement.cpp
@@ -0,0 +1,628 @@
+/*
+ * This file is part of ArmarX.
+ *
+ * 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    RobotAPI::ArmarXObjects::RobotUnit
+ * @author     Raphael Grimm ( raphael dot grimm at kit dot edu )
+ * @date       2018
+ * @copyright  http://www.gnu.org/licenses/gpl-2.0.txt
+ *             GNU General Public License
+ */
+
+#include <ArmarXCore/core/util/OnScopeExit.h>
+
+#include "RobotUnitModuleControllerManagement.h"
+#include "../NJointControllers/NJointController.h"
+
+namespace armarx
+{
+    namespace RobotUnitModule
+    {
+        template<class Cont>
+        static Ice::StringSeq GetNonNullNames(const Cont& c)
+        {
+            Ice::StringSeq result;
+            result.reserve(c.size());
+            for (const auto& e : c)
+            {
+                if (e)
+                {
+                    result.emplace_back(e->getName());
+                }
+            }
+            return result;
+        }
+
+        /**
+         * \brief This class allows minimal access to private members of \ref NJointController in a sane fashion for \ref ControllerManagement.
+         * \warning !! DO NOT ADD ANYTHING IF YOU DO NOT KNOW WAHT YOU ARE DOING! IF YOU DO SOMETHING WRONG YOU WILL CAUSE UNDEFINED BEHAVIOUR !!
+         */
+        class NJointControllerAttorneyForControllerManagement
+        {
+            friend class ControllerManagement;
+            static void SetRequested(const NJointControllerPtr& nJointCtrl, bool requested)
+            {
+                nJointCtrl->isRequested = requested;
+            }
+        };
+//        /**
+//         * \brief This class allows minimal access to private members of \ref ControlThreadDataBuffer in a sane fashion for \ref ControllerManagement.
+//         * \warning !! DO NOT ADD ANYTHING IF YOU DO NOT KNOW WAHT YOU ARE DOING! IF YOU DO SOMETHING WRONG YOU WILL CAUSE UNDEFINED BEHAVIOUR !!
+//         */
+//        class ControlThreadDataBufferAttorneyForControllerManagement
+//        {
+//            friend class ControllerManagement;
+//            static void SetActivateControllersRequest(ControllerManagement* p, std::set<NJointControllerPtr, std::greater<NJointControllerPtr>>&& ctrls)
+//            {
+//                p->_module<ControlThreadDataBuffer>().setActivateControllersRequest(std::move(ctrls));
+//            }
+//        };
+    }
+}
+
+namespace armarx
+{
+    namespace RobotUnitModule
+    {
+        Ice::StringSeq ControllerManagement::getRequestedNJointControllerNames(const Ice::Current &) const
+        {
+            auto guard = getGuard();
+            return GetNonNullNames(_module<ControlThreadDataBuffer>().getRequestedNJointControllers());
+        }
+
+        Ice::StringSeq ControllerManagement::getActivatedNJointControllerNames(const Ice::Current &) const
+        {
+            auto guard = getGuard();
+            return GetNonNullNames(_module<ControlThreadDataBuffer>().getActivatedNJointControllers());
+        }
+
+        void ControllerManagement::deleteNJointController(const std::string &name, const Ice::Current &)
+        {
+            deleteNJointControllers({name}, GlobalIceCurrent);
+        }
+
+        void ControllerManagement::activateNJointController(const std::string &name, const Ice::Current &)
+        {
+            activateNJointControllers({name}, GlobalIceCurrent);
+        }
+
+        void ControllerManagement::deactivateNJointController(const std::string &name, const Ice::Current &)
+        {
+            deactivateNJointControllers(Ice::StringSeq {name}, GlobalIceCurrent);
+        }
+
+        void ControllerManagement::checkNJointControllerClassName(const std::string &className) const
+        {
+            if (!NJointControllerRegistry::has(className))
+            {
+                std::stringstream ss;
+                ss << "Requested controller class '" << className << "' unknown! Known classes:" << NJointControllerRegistry::getKeys()
+                   << " (If this class exists in a different lib then load it via loadLibFromPath(path) or loadLibFromPackage(package, lib))";
+                ARMARX_ERROR << ss.str();
+                throw InvalidArgumentException {ss.str()};
+            }
+        }
+
+        std::vector<NJointControllerPtr> ControllerManagement::getNJointControllersNotNull(const std::vector<std::string> &names) const
+        {
+            auto guard = getGuard();
+            throwIfDevicesNotReady(__FUNCTION__);
+            std::vector<NJointControllerPtr> ctrl;
+            ctrl.reserve(names.size());
+            for (const auto& name : names)
+            {
+                ctrl.emplace_back(getNJointControllerNotNull(name));
+            }
+            return ctrl;
+        }
+
+        const NJointControllerPtr &ControllerManagement::getNJointControllerNotNull(const std::string &name) const
+        {
+            auto guard = getGuard();
+            throwIfDevicesNotReady(__FUNCTION__);
+            auto it = nJointControllers.find(name);
+            if (it == nJointControllers.end())
+            {
+                std::stringstream ss;
+                ss << "RobotUnit: there is no NJointController with name '" << name
+                   << "'. Existing NJointControllers are: " << getNJointControllerNames();
+                throw InvalidArgumentException {ss.str()};
+            }
+            if (!it->second)
+            {
+                std::stringstream ss;
+                ss << "RobotUnit: The NJointController with name '" << name
+                   << "'. Is a nullptr! This should never be the case (invariant)!  \nMap:\n" << nJointControllers;
+                ARMARX_FATAL << ss.str();
+                throw InvalidArgumentException {ss.str()};
+            }
+            return it->second;
+        }
+
+        StringNJointControllerPrxDictionary ControllerManagement::getAllNJointControllers(const Ice::Current &) const
+        {
+            std::map<std::string, NJointControllerPtr> nJointControllersCopy;
+            {
+                auto guard = getGuard();
+                //copy to keep lock retention time low
+                nJointControllersCopy = nJointControllers;
+            }
+            StringNJointControllerPrxDictionary result;
+            for (const auto& pair : nJointControllersCopy)
+            {
+                result[pair.first] = NJointControllerInterfacePrx::uncheckedCast(pair.second->getProxy(-1, true));
+            }
+            return result;
+        }
+
+        NJointControllerInterfacePrx ControllerManagement::createNJointController(
+                const std::string& className,
+                const std::string& instanceName,
+                const NJointControllerConfigPtr& config,
+                const Ice::Current&)
+        {
+            //no lock required
+            return NJointControllerInterfacePrx::uncheckedCast(
+                        createNJointController(className, instanceName, config, true, false)->getProxy(-1, true));
+        }
+
+        NJointControllerInterfacePrx ControllerManagement::createNJointControllerFromVariantConfig(
+                const std::string& className,
+                const std::string& instanceName,
+                const StringVariantBaseMap& variants,
+                const Ice::Current&)
+        {
+            //no lock required
+            checkNJointControllerClassName(className);
+            if (!NJointControllerRegistry::get(className)->hasRemoteConfiguration())
+            {
+                std::stringstream ss;
+                ss << "Requested controller class '" << className << "' allows no remote configuration" << NJointControllerRegistry::getKeys()
+                   << " (Implement 'static WidgetDescription::WidgetPtr " << className << "::GenerateConfigDescription()'"
+                   << " and 'static NJointControllerConfigPtr " << className
+                   << "::GenerateConfigFromVariants(const StringVariantBaseMap&)' to allow remote configuration";
+                ARMARX_ERROR << ss.str();
+                throw InvalidArgumentException {ss.str()};
+            }
+            return createNJointController(
+                        className, instanceName,
+                        NJointControllerRegistry::get(className)->GenerateConfigFromVariants(variants),
+                        GlobalIceCurrent/*to select ice overload*/);
+        }
+
+        const NJointControllerPtr& ControllerManagement::createNJointController(
+                const std::string& className,
+                const std::string& instanceName,
+                const NJointControllerConfigPtr& config,
+                bool deletable,
+                bool internal)
+        {
+            auto guard = getGuard();
+            throwIfDevicesNotReady(__FUNCTION__);
+            if (instanceName.empty())
+            {
+                ARMARX_ERROR << "The instance name is empty! (give a unique name)";
+                throw InvalidArgumentException {"The instance name is empty! (give a unique name)"};
+            }
+            //check if we would be able to create the class
+            checkNJointControllerClassName(className);
+            auto& factory = NJointControllerRegistry::get(className);
+
+            //check if the instance name is already in use
+            if (nJointControllers.count(instanceName))
+            {
+                std::stringstream ss;
+                ss << "There already is a controller instance with the name '" << instanceName << "'. Use a different instance name instead."
+                   << " Other used instance names are " << getNJointControllerNames();
+                ARMARX_ERROR << ss.str();
+                throw InvalidArgumentException {ss.str()};
+            }
+
+            //create the controller
+            ARMARX_CHECK_EXPRESSION(factory);
+            NJointControllerPtr nJointCtrl = factory->create(
+                        this,
+                        config,
+                        controllerCreateRobot,
+                        deletable, internal
+            );
+            ARMARX_CHECK_NOT_EQUAL_W_HINT(
+                nJointCtrl->getControlDeviceUsedIndices().size(), 0,
+                "The NJointController '" << nJointCtrl->getName() << "' uses no ControlDevice! (It has to use at least one)"
+            );
+
+            getArmarXManager()->addObjectAsync(nJointCtrl, instanceName, false, false);
+            nJointControllers[instanceName] = std::move(nJointCtrl);
+            _module<Publisher>().getRobotUnitListenerProxy()->nJointControllerCreated(instanceName);
+            return nJointControllers.at(instanceName);
+        }
+
+
+        bool ControllerManagement::loadLibFromPath(const std::string &path, const Ice::Current &)
+        {
+            return getArmarXManager()->loadLibFromPath(path);
+        }
+
+        bool ControllerManagement::loadLibFromPackage(const std::string &package, const std::string &lib, const Ice::Current &)
+        {
+            return getArmarXManager()->loadLibFromPackage(package, lib);
+        }
+
+        Ice::StringSeq ControllerManagement::getNJointControllerClassNames(const Ice::Current &) const
+        {
+            return NJointControllerRegistry::getKeys();
+        }
+
+        Ice::StringSeq ControllerManagement::getNJointControllerNames(const Ice::Current &) const
+        {
+            auto guard = getGuard();
+            return getMapKeys(nJointControllers);
+        }
+
+
+        void ControllerManagement::activateNJointControllers(const Ice::StringSeq& names, const Ice::Current&)
+        {
+            ARMARX_VERBOSE << "requesting controller activation for:\n" << names;
+            if (names.empty())
+            {
+                return;
+            }
+            auto guard = getGuard();
+            throwIfDevicesNotReady(__FUNCTION__);
+            auto ctrlsToActVec = getNJointControllersNotNull(names); //also checks if these controllers exist
+            ARMARX_DEBUG << "all requested controllers exist" << std::flush;
+            std::set<NJointControllerPtr, std::greater<NJointControllerPtr>> ctrlsToAct {ctrlsToActVec.begin(), ctrlsToActVec.end()};
+            ARMARX_CHECK_EXPRESSION(!ctrlsToAct.count(nullptr));
+            std::set<NJointControllerPtr, std::greater<NJointControllerPtr>> ctrls
+            {
+                _module<ControlThreadDataBuffer>().getRequestedNJointControllers().begin(),
+                _module<ControlThreadDataBuffer>().getRequestedNJointControllers().end()
+            };
+            ctrls.erase(nullptr);
+            //check for conflict
+            std::vector<char> inuse;
+            //check requested controllers
+            {
+                auto r = NJointController::AreNotInConflict(ctrlsToAct.begin(), ctrlsToAct.end());
+                if (!r)
+                {
+                    std::stringstream ss;
+                    ss << "activateNJointControllers: requested controllers are in conflict!\ncontrollers:\n" << names;
+                    ARMARX_ERROR << ss.str();
+                    throw InvalidArgumentException {ss.str()};
+                }
+                inuse = std::move(r.get());
+            }
+            ARMARX_DEBUG << "all requested controllers are conflict free" << std::flush;
+            auto printInUse = ARMARX_STREAM_PRINTER
+            {
+                for (const auto c : inuse)
+                {
+                    out << (c ? 1 : 0);
+                }
+            };
+            ARMARX_DEBUG << "inuse field (request)\n" << printInUse;
+            //add already active controllers if they are conflict free
+            {
+                if (ctrls.empty())
+                {
+                    ARMARX_DEBUG << "no already requested NJointControllers";
+                }
+                for (const NJointControllerPtr& nJointCtrl : ctrls)
+                {
+                    if (ctrlsToAct.count(nJointCtrl))
+                    {
+                        continue;
+                    }
+                    auto r = nJointCtrl->isNotInConflictWith(inuse);
+                    if (r)
+                    {
+                        ARMARX_DEBUG << "keeping  already requested NJointController '"
+                                     << nJointCtrl->getInstanceName() << "' in   list of requested controllers";
+                        ctrlsToAct.insert(nJointCtrl);
+                        inuse = std::move(r.get());
+                    }
+                    else
+                    {
+                        ARMARX_INFO << "removing already requested NJointController '"
+                                    << nJointCtrl->getInstanceName() << "' from list of requested controllers";
+                    }
+                }
+                ARMARX_DEBUG << "inuse field (all)\n" << printInUse;
+            }
+            _module<ControlThreadDataBuffer>().setActivateControllersRequest(ctrlsToAct);
+        }
+        void ControllerManagement::deactivateNJointControllers(const Ice::StringSeq& names, const Ice::Current&)
+        {
+            ARMARX_VERBOSE << "requesting controller deactivation for:\n" << names;
+            if (names.empty())
+            {
+                return;
+            }
+            auto guard = getGuard();
+            throwIfDevicesNotReady(__FUNCTION__);
+            auto ctrlsDeacVec = getNJointControllersNotNull(names); //also checks if these controllers exist
+            std::set<NJointControllerPtr, std::greater<NJointControllerPtr>> ctrls
+            {
+                _module<ControlThreadDataBuffer>().getRequestedNJointControllers().begin(),
+                _module<ControlThreadDataBuffer>().getRequestedNJointControllers().end()
+            };
+            for (const auto& nJointCtrlToDeactivate : ctrlsDeacVec)
+            {
+                ctrls.erase(nJointCtrlToDeactivate);
+            }
+            _module<ControlThreadDataBuffer>().setActivateControllersRequest(ctrls);
+        }
+        void ControllerManagement::switchNJointControllerSetup(const Ice::StringSeq& newSetup, const Ice::Current&)
+        {
+            auto guard = getGuard();
+            throwIfDevicesNotReady(__FUNCTION__);
+            auto ctrlsToActVec = getNJointControllersNotNull(newSetup); //also checks if these controllers exist
+            _module<ControlThreadDataBuffer>().setActivateControllersRequest({ctrlsToActVec.begin(), ctrlsToActVec.end()});
+        }
+
+
+        void ControllerManagement::deleteNJointControllers(const Ice::StringSeq& names, const Ice::Current&)
+        {
+            ARMARX_VERBOSE << "requesting controller deletion for:\n" << names;
+            if (names.empty())
+            {
+                return;
+            }
+            auto guard = getGuard();
+            throwIfDevicesNotReady(__FUNCTION__);
+            auto ctrlsToActVec = getNJointControllersNotNull(names); //also checks if these controllers exist
+            ARMARX_DEBUG << "all controllers requested to delete exist" << std::flush;
+            //check if all can be deleted
+            for (const auto& nJointCtrl : ctrlsToActVec)
+            {
+                if (!nJointCtrl->isDeletable())
+                {
+                    throw LogicError
+                    {
+                        "The NJointController '" + nJointCtrl->getInstanceName() +
+                        "' can't be deleted since this operation is not allowed for this controller! (no NJointController was deleted)"
+                    };
+                }
+            }
+            for (const auto& nJointCtrl : ctrlsToActVec)
+            {
+                if (nJointCtrl->isControllerActive() || nJointCtrl->isControllerRequested())
+                {
+                    throw LogicError
+                    {
+                        "The NJointController '" + nJointCtrl->getInstanceName() +
+                        "' can't be deleted since it is active or requested! (no NJointController was deleted)"
+                    };
+                }
+            }
+            for (const auto& nJointCtrl : ctrlsToActVec)
+            {
+                const auto name = nJointCtrl->getInstanceName();
+                //deletion is done in a different thread since this call may be done by the controller (protection against use after free)
+                nJointControllersToBeDeleted[name] = std::move(nJointCtrl);
+                nJointControllers.erase(name);
+                ARMARX_VERBOSE << "added NJointController '" << name << "' to be deleted";
+            }
+        }
+
+
+        NJointControllerClassDescription ControllerManagement::getNJointControllerClassDescription(
+            const std::string& className, const Ice::Current&) const
+        {
+            while (getRobotUnitState() == RobotUnitState::InitializingComponent || getRobotUnitState() == RobotUnitState::InitializingDevices)
+            {
+                //this phase should only last short so busy waiting is ok
+                std::this_thread::sleep_for(std::chrono::milliseconds(50));
+            }
+            auto guard = getGuard();
+            throwIfDevicesNotReady(__FUNCTION__);
+            checkNJointControllerClassName(className);
+            NJointControllerClassDescription data;
+            data.className = className;
+            if (NJointControllerRegistry::get(className)->hasRemoteConfiguration())
+            {
+                data.configDescription =
+                    NJointControllerRegistry::get(className)->GenerateConfigDescription(
+                            controllerCreateRobot,
+                            _module<Devices>().getControlDevicesConstPtr(),
+                            _module<Devices>().getSensorDevicesConstPtr()
+                );
+            }
+            return data;
+        }
+
+        NJointControllerClassDescriptionSeq ControllerManagement::getNJointControllerClassDescriptions(const Ice::Current&) const
+        {
+            std::size_t tries = 200;
+            while (getRobotUnitState() == RobotUnitState::InitializingComponent || getRobotUnitState() == RobotUnitState::InitializingDevices)
+            {
+                //this phase should only last short so busy waiting is ok
+                std::this_thread::sleep_for(std::chrono::milliseconds(50));
+                if (! --tries)
+                {
+                    throw RuntimeError {"RobotUnit::getNJointControllerClassDescriptions: it took too long to for the unit to get in a valid state"};
+                }
+            }
+            auto guard = getGuard();
+            NJointControllerClassDescriptionSeq r;
+            r.reserve(NJointControllerRegistry::getKeys().size());
+            for (const auto& key : NJointControllerRegistry::getKeys())
+            {
+                r.emplace_back(getNJointControllerClassDescription(key));
+            }
+            return r;
+        }
+
+        NJointControllerInterfacePrx ControllerManagement::getNJointController(const std::string& name, const Ice::Current&) const
+        {
+            NJointControllerPtr ctrl;
+            {
+                auto guard = getGuard();
+                auto it = nJointControllers.find(name);
+                if (it == nJointControllers.end())
+                {
+                    return nullptr;
+                }
+                ctrl = it->second;
+            }
+            return NJointControllerInterfacePrx::uncheckedCast(ctrl->getProxy(-1, true));
+        }
+
+        NJointControllerStatus ControllerManagement::getNJointControllerStatus(const std::string& name, const Ice::Current&) const
+        {
+            auto guard = getGuard();
+            throwIfDevicesNotReady(__FUNCTION__);
+            return getNJointControllerNotNull(name)->getControllerStatus();
+        }
+
+        NJointControllerStatusSeq ControllerManagement::getNJointControllerStatuses(const Ice::Current&) const
+        {
+            auto guard = getGuard();
+            if (!areDevicesReady())
+            {
+                return {};
+            }
+            NJointControllerStatusSeq r;
+            r.reserve(nJointControllers.size());
+            for (const auto& nJointCtrl : nJointControllers)
+            {
+                r.emplace_back(nJointCtrl.second->getControllerStatus());
+            }
+            return r;
+        }
+
+        NJointControllerDescription ControllerManagement::getNJointControllerDescription(const std::string& name, const Ice::Current&) const
+        {
+            NJointControllerPtr nJointCtrl;
+            {
+                auto guard = getGuard();
+                throwIfDevicesNotReady(__FUNCTION__);
+                nJointCtrl = getNJointControllerNotNull(name);
+            }
+            return nJointCtrl->getControllerDescription();
+        }
+
+        NJointControllerDescriptionSeq ControllerManagement::getNJointControllerDescriptions(const Ice::Current&) const
+        {
+            std::map<std::string, NJointControllerPtr> nJointControllersCopy;
+            {
+                auto guard = getGuard();
+                if (!areDevicesReady())
+                {
+                    return {};
+                }
+                nJointControllersCopy = nJointControllers;
+            }
+            NJointControllerDescriptionSeq r;
+            r.reserve(nJointControllersCopy.size());
+            for (const auto& nJointCtrl : nJointControllersCopy)
+            {
+                r.emplace_back(nJointCtrl.second->getControllerDescription());
+            }
+            return r;
+        }
+
+        NJointControllerDescriptionWithStatus ControllerManagement::getNJointControllerDescriptionWithStatus(
+            const std::string& name, const Ice::Current&) const
+        {
+            NJointControllerPtr nJointCtrl;
+            {
+                auto guard = getGuard();
+                throwIfDevicesNotReady(__FUNCTION__);
+                nJointCtrl = getNJointControllerNotNull(name);
+            }
+            return nJointCtrl->getControllerDescriptionWithStatus();
+        }
+
+        NJointControllerDescriptionWithStatusSeq ControllerManagement::getNJointControllerDescriptionsWithStatuses(const Ice::Current&) const
+        {
+            std::map<std::string, NJointControllerPtr> nJointControllersCopy;
+            {
+                auto guard = getGuard();
+                if (!areDevicesReady())
+                {
+                    return {};
+                }
+                nJointControllersCopy = nJointControllers;
+            }
+            NJointControllerDescriptionWithStatusSeq r;
+            r.reserve(nJointControllersCopy.size());
+            for (const auto& nJointCtrl : nJointControllersCopy)
+            {
+                r.emplace_back(nJointCtrl.second->getControllerDescriptionWithStatus());
+            }
+            return r;
+        }
+
+        void ControllerManagement::removeNJointControllers(std::map<std::string, NJointControllerPtr>& ctrls, bool blocking, RobotUnitListenerPrx l)
+        {
+            for (auto& n2NJointCtrl : ctrls)
+            {
+                NJointControllerPtr& nJointCtrl = n2NJointCtrl.second;
+                if(blocking)
+                {
+                    ARMARX_VERBOSE << "deleted NJointController " << n2NJointCtrl.first;
+                    getArmarXManager()->removeObjectBlocking(nJointCtrl->getName());
+                }
+                else
+                {
+                    ARMARX_VERBOSE << "deleted NJointController " << n2NJointCtrl.first;
+                    getArmarXManager()->removeObjectBlocking(nJointCtrl->getName());
+                }
+                if(l)
+                {
+                    l->nJointControllerDeleted(n2NJointCtrl.first);
+                }
+            }
+            ctrls.clear();
+        }
+
+        void ControllerManagement::removeNJointControllersToBeDeleted(bool blocking, RobotUnitListenerPrx l)
+        {
+            removeNJointControllers(nJointControllersToBeDeleted, blocking, l);
+        }
+
+        void ControllerManagement::_preFinishRunning()
+        {
+            //NJoint queued for deletion (some could still be in the queue)
+            ARMARX_DEBUG << "remove NJointControllers queued for deletion";
+            removeNJointControllersToBeDeleted();
+            ARMARX_DEBUG << "remove NJointControllers queued for deletion...done";
+            //NJoint
+            ARMARX_DEBUG << "remove NJointControllers";
+            removeNJointControllers(nJointControllers);
+            ARMARX_DEBUG << "remove NJointControllers...done";
+        }
+
+        void ControllerManagement::_postFinishRunning()
+        {
+            nJointControllers.clear();
+        }
+
+        void ControllerManagement::_postOnInitRobotUnit()
+        {
+            controllerCreateRobot = _module<RobotData>().cloneRobot();
+        }
+
+        void ControllerManagement::updateNJointControllerRequestedState(const std::set<NJointControllerPtr> &request)
+        {
+            ARMARX_DEBUG << "set requested state for NJoint controllers";
+            for (const auto& name2NJoint : nJointControllers)
+            {
+                NJointControllerAttorneyForControllerManagement::SetRequested(name2NJoint.second, request.count(name2NJoint.second));
+            }
+        }
+    }
+}
diff --git a/source/RobotAPI/components/units/RobotUnit/RobotUnitModules/RobotUnitModuleControllerManagement.h b/source/RobotAPI/components/units/RobotUnit/RobotUnitModules/RobotUnitModuleControllerManagement.h
new file mode 100644
index 0000000000000000000000000000000000000000..f48cf5976e5941afbf5eb2fd8d860b37fdb169b3
--- /dev/null
+++ b/source/RobotAPI/components/units/RobotUnit/RobotUnitModules/RobotUnitModuleControllerManagement.h
@@ -0,0 +1,356 @@
+/*
+ * This file is part of ArmarX.
+ *
+ * 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    RobotAPI::ArmarXObjects::RobotUnit
+ * @author     Raphael Grimm ( raphael dot grimm at kit dot edu )
+ * @date       2018
+ * @copyright  http://www.gnu.org/licenses/gpl-2.0.txt
+ *             GNU General Public License
+ */
+
+#pragma once
+
+#include <thread>
+
+#include <RobotAPI/interface/units/RobotUnit/RobotUnitInterface.h>
+
+#include "RobotUnitModuleBase.h"
+
+namespace armarx
+{
+    namespace RobotUnitModule
+    {
+        /**
+         * @brief This \ref ModuleBase "Module" manages \ref NJointController "NJointControllers".
+         *
+         * @see ModuleBase
+         */
+        class ControllerManagement : virtual public ModuleBase, virtual public RobotUnitControllerManagementInterface
+        {
+            friend class ModuleBase;
+        public:
+            /**
+             * @brief Returns the singleton instance of this class
+             * @return The singleton instance of this class
+             */
+            static ControllerManagement& Instance()
+            {
+                return ModuleBase::Instance<ControllerManagement>();
+            }
+            // //////////////////////////////////////////////////////////////////////////////////////// //
+            // ///////////////////////////////// RobotUnitModule hooks //////////////////////////////// //
+            // //////////////////////////////////////////////////////////////////////////////////////// //
+        private:
+            /// @see ModuleBase::_postOnInitRobotUnit
+            void _postOnInitRobotUnit();
+            /// @see ModuleBase::_preFinishRunning
+            void _preFinishRunning();
+            /// @see ModuleBase::_postFinishRunning
+            void _postFinishRunning();
+            // //////////////////////////////////////////////////////////////////////////////////////// //
+            // ///////////////////////////////////// ice interface //////////////////////////////////// //
+            // //////////////////////////////////////////////////////////////////////////////////////// //
+        public:
+            /**
+             * @brief Returns a proxy to the \ref NJointController.
+             * @param name The \ref NJointController's name.
+             * @return A proxy to the \ref NJointController.
+             * @see getAllNJointControllers
+             */
+            NJointControllerInterfacePrx getNJointController(const std::string& name, const Ice::Current&) const override;
+            /**
+             * @brief Returns proxies to all \ref NJointController "NJointControllers"
+             * @return Proxies to all \ref NJointController "NJointControllers"
+             * @see getNJointController
+             */
+            StringNJointControllerPrxDictionary getAllNJointControllers(const Ice::Current&) const override;
+
+            /**
+             * @brief Returns the status of the \ref NJointController.
+             * @param name The \ref NJointController's name.
+             * @return The status of the \ref NJointController.
+             * @see NJointControllerStatus
+             * @see getNJointControllerStatuses
+             * @see getNJointControllerDescriptionWithStatus
+             * @see getNJointControllerDescriptionsWithStatuses
+             */
+            NJointControllerStatus getNJointControllerStatus(const std::string& name, const Ice::Current& = GlobalIceCurrent) const override;
+            /**
+             * @brief Returns the status of all \ref NJointController "NJointControllers".
+             * @return The status of all \ref NJointController "NJointControllers".
+             * @see NJointControllerStatus
+             * @see getNJointControllerStatus
+             * @see getNJointControllerDescriptionWithStatus
+             * @see getNJointControllerDescriptionsWithStatuses
+             */
+            NJointControllerStatusSeq getNJointControllerStatuses(const Ice::Current&) const override;
+
+            /**
+             * @brief Returns the description of the \ref NJointController.
+             * @param name The \ref NJointController's name.
+             * @return The description of the \ref NJointController.
+             * @see NJointControllerDescription
+             * @see getNJointControllerDescriptions
+             * @see getNJointControllerDescriptionWithStatus
+             * @see getNJointControllerDescriptionsWithStatuses
+             */
+            NJointControllerDescription getNJointControllerDescription(const std::string& name, const Ice::Current& = GlobalIceCurrent) const override;
+            /**
+             * @brief Returns the description of all \ref NJointController "NJointControllers".
+             * @return The description of all \ref NJointController "NJointControllers".
+             * @see NJointControllerDescription
+             * @see getNJointControllerDescription
+             * @see getNJointControllerDescriptionWithStatus
+             * @see getNJointControllerDescriptionsWithStatuses
+             */
+
+            NJointControllerDescriptionSeq getNJointControllerDescriptions(const Ice::Current&) const override;
+
+            /**
+             * @brief Returns the status and description of the \ref NJointController.
+             * @param name The \ref NJointController's name.
+             * @return The status and description of the \ref NJointController.
+             * @see getNJointControllerDescriptionsWithStatuses
+             * @see NJointControllerStatus
+             * @see getNJointControllerStatus
+             * @see getNJointControllerStatuses
+             * @see NJointControllerDescription
+             * @see getNJointControllerDescription
+             * @see getNJointControllerDescriptions
+             */
+            NJointControllerDescriptionWithStatus getNJointControllerDescriptionWithStatus(
+                const std::string& name, const Ice::Current& = GlobalIceCurrent) const override;
+            /**
+             * @brief Returns the status and description of all \ref NJointController "NJointControllers".
+             * @return The status and description of all \ref NJointController "NJointControllers".
+             * @see getNJointControllerDescriptionsWithStatus
+             * @see NJointControllerStatus
+             * @see getNJointControllerStatus
+             * @see getNJointControllerStatuses
+             * @see NJointControllerDescription
+             * @see getNJointControllerDescription
+             * @see getNJointControllerDescriptions
+             */
+            NJointControllerDescriptionWithStatusSeq getNJointControllerDescriptionsWithStatuses(const Ice::Current&) const override;
+
+            /**
+             * @brief getNJointControllerClassDescription
+             * @param className
+             * @return
+             */
+            NJointControllerClassDescription getNJointControllerClassDescription(
+                const std::string& className, const Ice::Current& = GlobalIceCurrent) const override;
+            /**
+             * @brief getNJointControllerClassDescriptions
+             * @return
+             */
+            NJointControllerClassDescriptionSeq getNJointControllerClassDescriptions(const Ice::Current&) const override;
+            /**
+             * @brief Loads the given lib. (calls `getArmarXManager()->loadLibFromPath(path)`)
+             * @param path Path to the lib to load.
+             * @return Whether loading the lib was successful.
+             * @see ArmarXManager::loadLibFromPath
+             */
+            bool loadLibFromPath(const std::string& path, const Ice::Current& = GlobalIceCurrent) override;
+            /**
+             * @brief Loads the given lib. (calls `getArmarXManager()->loadLibFromPath(package, lib)`)
+             * @param package The armarx package containing the lib
+             * @param lib The lib name to load.
+             * @return Whether loading the lib was successful.
+             * @see ArmarXManager::loadLibFromPackage
+             */
+            bool loadLibFromPackage(const std::string& package, const std::string& lib, const Ice::Current& = GlobalIceCurrent) override;
+            /**
+             * @brief Returns the names of all available classes of \ref NJointController.
+             * @return The names of all available classes of \ref NJointController.
+             */
+            Ice::StringSeq getNJointControllerClassNames(const Ice::Current& = GlobalIceCurrent) const override;
+            /**
+             * @brief Returns the names of all \ref NJointController "NJointControllers"
+             * @return The names of all \ref NJointController "NJointControllers"
+             */
+            Ice::StringSeq getNJointControllerNames(const Ice::Current& = GlobalIceCurrent) const override;
+            /**
+             * @brief Returns the names of all requested \ref NJointController "NJointControllers"
+             * @return The names of all requested \ref NJointController "NJointControllers"
+             */
+            Ice::StringSeq getRequestedNJointControllerNames(const Ice::Current& = GlobalIceCurrent) const override;
+            /**
+             * @brief Returns the names of all activated \ref NJointController "NJointControllers"
+             * @return The names of all activated \ref NJointController "NJointControllers"
+             */
+            Ice::StringSeq getActivatedNJointControllerNames(const Ice::Current& = GlobalIceCurrent) const override;
+
+            /**
+             * @brief Queues the given \ref NJointController for deletion.
+             * @param name The \ref NJointController to delete.
+             * @see removeNJointControllersToBeDeleted
+             * @see nJointControllersToBeDeleted
+             * @see deleteNJointControllers
+             */
+            void deleteNJointController(const std::string& name, const Ice::Current& = GlobalIceCurrent) override;
+            /**
+             * @brief Queues the given \ref NJointController "NJointControllers" for deletion.
+             * @param names The \ref NJointController "NJointControllers" to delete.
+             * @see removeNJointControllersToBeDeleted
+             * @see nJointControllersToBeDeleted
+             * @see deleteNJointController
+             */
+            void deleteNJointControllers(const Ice::StringSeq& names, const Ice::Current& = GlobalIceCurrent) override;
+
+            /**
+             * @brief Requests activation for the given \ref NJointController.
+             * @param name The requested \ref NJointController.
+             * @see activateNJointControllers
+             */
+            void activateNJointController(const std::string& name, const Ice::Current& = GlobalIceCurrent) override;
+            /**
+             * @brief Requests activation for the given \ref NJointController "NJointControllers".
+             * @param names The requested \ref NJointController "NJointControllers".
+             * @see activateNJointController
+             */
+            void activateNJointControllers(const Ice::StringSeq& names, const Ice::Current& = GlobalIceCurrent) override;
+
+            /**
+             * @brief Requests deactivation for the given \ref NJointController.
+             * @param name The \ref NJointController to be deactivated.
+             * @see deactivateNJointControllers
+             */
+            void deactivateNJointController(const std::string& name, const Ice::Current& = GlobalIceCurrent) override;
+            /**
+             * @brief Requests deactivation for the given \ref NJointController "NJointControllers".
+             * @param names The \ref NJointController "NJointControllers" to be deactivated.
+             * @see deactivateNJointController
+             */
+            void deactivateNJointControllers(const Ice::StringSeq& names, const Ice::Current& = GlobalIceCurrent) override;
+
+            /**
+             * @brief Cretes a \ref NJointController.
+             * @param className The \ref NJointController's class.
+             * @param instanceName The \ref NJointController's name.
+             * @param config A config passed to the \ref NJointController's ctor.
+             * @return A proxy to the created \ref NJointController.
+             */
+            NJointControllerInterfacePrx createNJointController(
+                const std::string& className, const std::string& instanceName,
+                const NJointControllerConfigPtr& config, const Ice::Current&) override;
+            /**
+             * @brief Cretes a \ref NJointController.
+             * @param className The \ref NJointController's class.
+             * @param instanceName The \ref NJointController's name.
+             * @param variants A map of \ref Variant "Variants" passed to the \ref NJointController's ctor.
+             * @return A proxy to the created \ref NJointController.
+             */
+            NJointControllerInterfacePrx createNJointControllerFromVariantConfig(
+                const std::string& className, const std::string& instanceName,
+                const StringVariantBaseMap& variants, const Ice::Current&) override;
+
+            /**
+             * @brief Changes the set of requested \ref NJointController "NJointControllers" to the given set.
+             * @param newSetup The new set of requested \ref NJointController "NJointControllers"
+             */
+            void switchNJointControllerSetup(const Ice::StringSeq& newSetup, const Ice::Current& = GlobalIceCurrent) override;
+            // //////////////////////////////////////////////////////////////////////////////////////// //
+            // /////////////////////////////////// Module interface /////////////////////////////////// //
+            // //////////////////////////////////////////////////////////////////////////////////////// //
+        public:
+            /**
+             * @brief Cretes a \ref NJointController.
+             * @param className The \ref NJointController's class.
+             * @param instanceName The \ref NJointController's name.
+             * @param config A config passed to the \ref NJointController's ctor.
+             * @param deletable Whether the \ref NJointController can be deleted.
+             * @param internal Whether the \ref NJointController should be tagged as internal.
+             * @return A pointer to the created \ref NJointController
+             */
+            const NJointControllerPtr& createNJointController(
+                const std::string& className, const std::string& instanceName,
+                const NJointControllerConfigPtr& config, bool deletable, bool internal);
+
+            /**
+             * @brief Returns pointers to the \ref NJointController "NJointControllers". (If one does not exist, an exception is thrown.)
+             * @param names The \ref NJointController "NJointControllers" names.
+             * @return Pointers to the \ref NJointController "NJointControllers".
+             * @throw If there is no \ref NJointcontroller for \param name
+             */
+            std::vector<armarx::NJointControllerPtr> getNJointControllersNotNull(const std::vector<std::string>& names) const;
+            /**
+             * @brief Returns a pointer to the \ref NJointController. (If it does not exist, an exception is thrown.)
+             * @param name The \ref NJointController
+             * @return A pointer to the \ref NJointController.
+             * @throw If there is no \ref NJointcontroller for \param name
+             */
+            const NJointControllerPtr& getNJointControllerNotNull(const std::string& name) const;
+            // //////////////////////////////////////////////////////////////////////////////////////// //
+            // //////////////////////////////////// implementation //////////////////////////////////// //
+            // //////////////////////////////////////////////////////////////////////////////////////// //
+        private:
+            /**
+             * @brief Deletes the given \ref NJointController "NJointControllers" and removes them
+             * from the \ref ArmarXManager
+             * @param ctrls \ref NJointController "NJointControllers" to delete.
+             * @param blocking Whether removal from the \ref ArmarXManager should be blocking.
+             * @param l Proxy to the listener topic all removal events should be sent to.
+             */
+            void removeNJointControllers(std::map<std::string, NJointControllerPtr>& ctrls, bool blocking = true, RobotUnitListenerPrx l = nullptr);
+            /**
+             * @brief Calls \ref removeNJointControllers for all \ref NJointController "NJointControllers"
+             * queued for deletion (\ref nJointControllersToBeDeleted).
+             * @param blocking Whether removal from the \ref ArmarXManager should be blocking.
+             * @param l Proxy to the listener topic all removal events should be sent to.
+             * @see removeNJointControllers
+             * @see nJointControllersToBeDeleted
+             */
+            void removeNJointControllersToBeDeleted(bool blocking = true, RobotUnitListenerPrx l = nullptr);
+
+            /**
+             * @brief Sets the requested flag for all given \ref NJointController "NJointControllers" and unsets it for the rest.
+             * @param request The \ref NJointController "NJointControllers" where the requested flag should be set.
+             */
+            void updateNJointControllerRequestedState(const std::set<NJointControllerPtr>& request);
+            /**
+             * @brief Throws if there is no factory for \ref NJointController "NJointControllers" for the given class name.
+             * @param className The class to check for.
+             * @throw If there is no factory for \ref NJointController "NJointControllers" for the given class name.
+             */
+            void checkNJointControllerClassName(const std::string& className) const;
+
+            // //////////////////////////////////////////////////////////////////////////////////////// //
+            // ///////////////////////////////////////// Data ///////////////////////////////////////// //
+            // //////////////////////////////////////////////////////////////////////////////////////// //
+        private:
+            /// @brief Holds all currently loaded NJoint controllers (index: [instancename])(May not be accessed in rt.)
+            std::map<std::string, NJointControllerPtr> nJointControllers;
+            /// @brief These controllers will be deleted in the next iteration of publish
+            std::map<std::string, NJointControllerPtr> nJointControllersToBeDeleted;
+            /// @brief VirtualRobot used when creating controllers / calling other functions in this module
+            VirtualRobot::RobotPtr controllerCreateRobot;
+            // //////////////////////////////////////////////////////////////////////////////////////// //
+            // /////////////////////////////////////// Attorneys ////////////////////////////////////// //
+            // //////////////////////////////////////////////////////////////////////////////////////// //
+        private:
+            /**
+            * \brief This class allows minimal access to private members of \ref ControllerManagement in a sane fashion for \ref Publisher.
+            * \warning !! DO NOT ADD ADDITIONAL FRIENDS IF YOU DO NOT KNOW WAHT YOU ARE DOING! IF YOU DO SOMETHING WRONG YOU WILL CAUSE UNDEFINED BEHAVIOUR !!
+            */
+            friend class ControllerManagementAttorneyForPublisher;
+            /**
+            * \brief This class allows minimal access to private members of \ref ControllerManagement in a sane fashion for \ref ControlThreadDataBuffer.
+            * \warning !! DO NOT ADD ADDITIONAL FRIENDS IF YOU DO NOT KNOW WAHT YOU ARE DOING! IF YOU DO SOMETHING WRONG YOU WILL CAUSE UNDEFINED BEHAVIOUR !!
+            */
+            friend class ControllerManagementAttorneyForControlThreadDataBuffer;
+        };
+    }
+}
diff --git a/source/RobotAPI/components/units/RobotUnit/RobotUnitModules/RobotUnitModuleDevices.cpp b/source/RobotAPI/components/units/RobotUnit/RobotUnitModules/RobotUnitModuleDevices.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..456705d417e637098b2e52fd8f31cd588277fef9
--- /dev/null
+++ b/source/RobotAPI/components/units/RobotUnit/RobotUnitModules/RobotUnitModuleDevices.cpp
@@ -0,0 +1,648 @@
+/*
+ * This file is part of ArmarX.
+ *
+ * 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    RobotAPI::ArmarXObjects::RobotUnit
+ * @author     Raphael Grimm ( raphael dot grimm at kit dot edu )
+ * @date       2018
+ * @copyright  http://www.gnu.org/licenses/gpl-2.0.txt
+ *             GNU General Public License
+ */
+
+#include "RobotUnitModuleDevices.h"
+#include "RobotUnitModuleControlThreadDataBuffer.h"
+#include "RobotUnitModuleRobotData.h"
+
+
+namespace armarx
+{
+    namespace RobotUnitModule
+    {
+        const std::string Devices::rtThreadTimingsSensorDeviceName = "RTThreadTimings";
+
+        ControlDeviceDescription Devices::getControlDeviceDescription(const std::string &name, const Ice::Current &) const
+        {
+            throwIfInControlThread(__FUNCTION__);
+            throwIfDevicesNotReady(__FUNCTION__);
+            if (!controlDevices.has(name))
+            {
+                std::stringstream ss;
+                ss << "getControlDeviceDescription: There is no ControlDevice '" << name
+                   << "'. There are these ControlDevices: " << controlDevices.keys();
+                throw InvalidArgumentException {ss.str()};
+            }
+            return getControlDeviceDescription(controlDevices.index(name));
+        }
+
+        ControlDeviceDescriptionSeq Devices::getControlDeviceDescriptions(const Ice::Current &) const
+        {
+            throwIfInControlThread(__FUNCTION__);
+            if (!areDevicesReady())
+            {
+                return {};
+            }
+            ControlDeviceDescriptionSeq r;
+            r.reserve(getNumberOfControlDevices());
+            for (auto idx : getIndices(controlDevices.values()))
+            {
+                r.emplace_back(getControlDeviceDescription(idx));
+            }
+            return r;
+        }
+
+        std::size_t Devices::getNumberOfControlDevices() const
+        {
+            throwIfInControlThread(__FUNCTION__);
+            throwIfDevicesNotReady(__FUNCTION__);
+            return controlDevices.size();
+        }
+
+        std::size_t Devices::getNumberOfSensorDevices() const
+        {
+            throwIfInControlThread(__FUNCTION__);
+            throwIfDevicesNotReady(__FUNCTION__);
+            return sensorDevices.size();
+        }
+
+        std::size_t Devices::getControlDeviceIndex(const std::string& deviceName) const
+        {
+            throwIfInControlThread(__FUNCTION__);
+            throwIfDevicesNotReady(__FUNCTION__);
+            ARMARX_CHECK_EXPRESSION(sensorDevices.has(deviceName));
+            return sensorDevices.index(deviceName);
+        }
+        std::size_t Devices::getSensorDeviceIndex(const std::string& deviceName) const
+        {
+            throwIfInControlThread(__FUNCTION__);
+            throwIfDevicesNotReady(__FUNCTION__);
+            ARMARX_CHECK_EXPRESSION(controlDevices.has(deviceName));
+            return controlDevices.index(deviceName);
+        }
+
+        ConstSensorDevicePtr Devices::getSensorDevice(const std::string &sensorDeviceName) const
+        {
+            throwIfInControlThread(__FUNCTION__);
+            throwIfDevicesNotReady(__FUNCTION__);
+            return sensorDevices.at(sensorDeviceName, SensorDevice::NullPtr);
+        }
+
+        ConstControlDevicePtr Devices::getControlDevice(const std::string &deviceName) const
+        {
+            throwIfInControlThread(__FUNCTION__);
+            throwIfDevicesNotReady(__FUNCTION__);
+            return controlDevices.at(deviceName, ControlDevice::NullPtr);
+        }
+
+        Ice::StringSeq Devices::getControlDeviceNames(const Ice::Current &) const
+        {
+            throwIfInControlThread(__FUNCTION__);
+            throwIfDevicesNotReady(__FUNCTION__);
+            return controlDevices.keys();
+        }
+
+        ControlDeviceDescription Devices::getControlDeviceDescription(std::size_t idx) const
+        {
+            throwIfInControlThread(__FUNCTION__);
+            throwIfDevicesNotReady(__FUNCTION__);
+            const ControlDevicePtr& controlDevice = controlDevices.at(idx);
+            ControlDeviceDescription data;
+            data.deviceName = controlDevice->getDeviceName();
+            data.tags.assign(controlDevice->getTags().begin(), controlDevice->getTags().end());
+            for (const auto& jointCtrl : controlDevice->getJointControllers())
+            {
+                data.contolModeToTargetType[jointCtrl->getControlMode()].targetType = jointCtrl->getControlTarget()->getControlTargetType();
+                data.contolModeToTargetType[jointCtrl->getControlMode()].hardwareControlMode = jointCtrl->getHardwareControlMode();
+            }
+            return data;
+        }
+
+        ControlDeviceStatus Devices::getControlDeviceStatus(std::size_t idx) const
+        {
+            auto guard = getGuard();
+            throwIfDevicesNotReady(__FUNCTION__);
+            const ControlDevicePtr& controlDevice = controlDevices.at(idx);
+            ControlDeviceStatus status;
+            const auto activeJointCtrl = _module<ControlThreadDataBuffer>().getActivatedJointControllers().at(idx);
+            status.activeControlMode = activeJointCtrl ? activeJointCtrl->getControlMode() : std::string {"!!JointController is nullptr!!"};
+            status.deviceName = controlDevice->getDeviceName();
+            ARMARX_CHECK_EXPRESSION(_module<ControlThreadDataBuffer>().getRequestedJointControllers().at(idx));
+            status.requestedControlMode = _module<ControlThreadDataBuffer>().getRequestedJointControllers().at(idx)->getControlMode();
+            for (const auto& targ : _module<ControlThreadDataBuffer>().getSensorAndControlBuffer().control.at(idx))
+            {
+                status.controlTargetValues[targ->getControlMode()] = targ->toVariants(_module<ControlThreadDataBuffer>().getSensorAndControlBuffer().sensorValuesTimestamp);
+            }
+            status.timestampUSec = MicroNow().count();
+            return status;
+        }
+
+        ControlDeviceStatus Devices::getControlDeviceStatus(const std::string &name, const Ice::Current &) const
+        {
+            throwIfInControlThread(__FUNCTION__);
+            throwIfDevicesNotReady(__FUNCTION__);
+            if (!controlDevices.has(name))
+            {
+                std::stringstream ss;
+                ss << "getControlDeviceStatus: There is no ControlDevice '" << name
+                   << "'. There are these ControlDevices: " << controlDevices.keys();
+                throw InvalidArgumentException {ss.str()};
+            }
+            return getControlDeviceStatus(controlDevices.index(name));
+        }
+
+        ControlDeviceStatusSeq Devices::getControlDeviceStatuses(const Ice::Current &) const
+        {
+            throwIfInControlThread(__FUNCTION__);
+            if (!areDevicesReady())
+            {
+                return {};
+            }
+            ControlDeviceStatusSeq r;
+            r.reserve(getNumberOfControlDevices());
+            for (auto idx : getIndices(controlDevices.values()))
+            {
+                r.emplace_back(getControlDeviceStatus(idx));
+            }
+            return r;
+        }
+
+        Ice::StringSeq Devices::getSensorDeviceNames(const Ice::Current &) const
+        {
+            throwIfInControlThread(__FUNCTION__);
+            throwIfDevicesNotReady(__FUNCTION__);
+            return sensorDevices.keys();
+        }
+
+        SensorDeviceDescription Devices::getSensorDeviceDescription(std::size_t idx) const
+        {
+            throwIfInControlThread(__FUNCTION__);
+            throwIfDevicesNotReady(__FUNCTION__);
+            const SensorDevicePtr& sensorDevice = sensorDevices.at(idx);
+            SensorDeviceDescription data;
+            data.deviceName = sensorDevice->getDeviceName();
+            data.tags.assign(sensorDevice->getTags().begin(), sensorDevice->getTags().end());
+            data.sensorValueType = sensorDevice->getSensorValueType();
+            return data;
+        }
+
+        SensorDeviceStatus Devices::getSensorDeviceStatus(std::size_t idx) const
+        {
+            auto guard = getGuard();
+            throwIfDevicesNotReady(__FUNCTION__);
+            const SensorDevicePtr& sensorDevice = sensorDevices.at(idx);
+            SensorDeviceStatus status;
+            status.deviceName = sensorDevice->getDeviceName();
+            status.sensorValue = _module<ControlThreadDataBuffer>().getSensorAndControlBuffer().sensors.at(idx)->toVariants(_module<ControlThreadDataBuffer>().getSensorAndControlBuffer().sensorValuesTimestamp);
+            status.timestampUSec = MicroNow().count();
+            return status;
+        }
+
+        SensorDeviceDescription Devices::getSensorDeviceDescription(const std::string &name, const Ice::Current &) const
+        {
+            throwIfInControlThread(__FUNCTION__);
+            throwIfDevicesNotReady(__FUNCTION__);
+            if (!sensorDevices.has(name))
+            {
+                std::stringstream ss;
+                ss << "getSensorDeviceDescription: There is no SensorDevice '" << name
+                   << "'. There are these SensorDevices: " << sensorDevices.keys();
+                throw InvalidArgumentException {ss.str()};
+            }
+            return getSensorDeviceDescription(sensorDevices.index(name));
+        }
+
+        SensorDeviceDescriptionSeq Devices::getSensorDeviceDescriptions(const Ice::Current &) const
+        {
+            throwIfInControlThread(__FUNCTION__);
+            if (!areDevicesReady())
+            {
+                return {};
+            }
+            SensorDeviceDescriptionSeq r;
+            r.reserve(getNumberOfSensorDevices());
+            for (auto idx : getIndices(sensorDevices.values()))
+            {
+                r.emplace_back(getSensorDeviceDescription(idx));
+            }
+            return r;
+        }
+
+        SensorDeviceStatus Devices::getSensorDeviceStatus(const std::string &name, const Ice::Current &) const
+        {
+            throwIfInControlThread(__FUNCTION__);
+            throwIfDevicesNotReady(__FUNCTION__);
+            if (!sensorDevices.has(name))
+            {
+                std::stringstream ss;
+                ss << "getSensorDeviceStatus: There is no SensorDevice '" << name
+                   << "'. There are these SensorDevices: " << sensorDevices.keys();
+                throw InvalidArgumentException {ss.str()};
+            }
+            return getSensorDeviceStatus(sensorDevices.index(name));
+        }
+
+        SensorDeviceStatusSeq Devices::getSensorDeviceStatuses(const Ice::Current &) const
+        {
+            throwIfInControlThread(__FUNCTION__);
+            if (!areDevicesReady())
+            {
+                return {};
+            }
+            SensorDeviceStatusSeq r;
+            r.reserve(getNumberOfSensorDevices());
+            for (auto idx : getIndices(sensorDevices.values()))
+            {
+                r.emplace_back(getSensorDeviceStatus(idx));
+            }
+            return r;
+        }
+
+        void Devices::addControlDevice(const ControlDevicePtr &cd)
+        {
+            throwIfInControlThread(__FUNCTION__);
+            //this guards prevents the RobotUnitState to change
+            auto guard = getGuard();
+            throwIfStateIsNot(RobotUnitState::InitializingDevices, __FUNCTION__);
+            controlDevices.add(cd->getDeviceName(), cd);
+            ARMARX_INFO << "added ControlDevice " << cd->getDeviceName();
+        }
+
+        void Devices::addSensorDevice(const SensorDevicePtr &sd)
+        {
+            throwIfInControlThread(__FUNCTION__);
+            //this guards prevents the RobotUnitState to change
+            auto guard = getGuard();
+            throwIfStateIsNot(RobotUnitState::InitializingDevices, __FUNCTION__);
+            if (!sd)
+            {
+                std::stringstream ss;
+                ss << "armarx::RobotUnit::addSensorDevice: SensorDevice is nullptr";
+                ARMARX_ERROR << ss.str();
+                throw InvalidArgumentException {ss.str()};
+            }
+            if (!sd->getSensorValue())
+            {
+                std::stringstream ss;
+                ss << "armarx::RobotUnit::addSensorDevice: SensorDevice " << sd->getDeviceName()
+                   << " has null SensorValue (this is not allowed)";
+                ARMARX_ERROR << ss.str();
+                throw InvalidArgumentException {ss.str()};
+            }
+            if (sd->getDeviceName() == rtThreadTimingsSensorDeviceName)
+            {
+                if (!std::dynamic_pointer_cast<RTThreadTimingsSensorDevice>(sd))
+                {
+                    throw InvalidArgumentException
+                    {
+                        "You tried to add a SensorDevice with the name " + sd->getDeviceName() +
+                                " which does not derive from RTThreadTimingsSensorDevice. (Don't do this)"
+                    };
+                }
+                //this checks if we already added such a device (do this before setting timingSensorDevice)
+                sensorDevices.add(sd->getDeviceName(), sd);
+                rtThreadTimingsSensorDevice = std::dynamic_pointer_cast<RTThreadTimingsSensorDevice>(sd);
+            }
+            else
+            {
+                sensorDevices.add(sd->getDeviceName(), sd);
+            }
+            ARMARX_INFO << "added SensorDevice " << sd->getDeviceName() << " (valuetype = " << sd->getSensorValueType() << ")";
+        }
+
+        RTThreadTimingsSensorDevicePtr Devices::createRTThreadTimingSensorDevice() const
+        {
+            throwIfInControlThread(__FUNCTION__);
+            return std::make_shared<RTThreadTimingsSensorDeviceImpl<>>(rtThreadTimingsSensorDeviceName);
+        }
+
+        void Devices::_postFinishRunning()
+        {
+            throwIfInControlThread(__FUNCTION__);
+            controlDevicesConstPtr.clear();
+            sensorDevicesConstPtr.clear();
+            sensorDevices.clear();
+            controlDevices.clear();
+        }
+
+        std::vector<JointController *> Devices::getStopMovementJointControllers() const
+        {
+            throwIfDevicesNotReady(__FUNCTION__);
+            throwIfInControlThread(__FUNCTION__);
+
+            std::vector<JointController*> controllers;
+            controllers.reserve(controlDevices.values().size());
+            for(const ControlDevicePtr& dev : controlDevices.values())
+            {
+                ARMARX_CHECK_NOT_NULL(dev);
+                controllers.emplace_back(dev->rtGetJointStopMovementController());
+                ARMARX_CHECK_NOT_NULL(controllers.back());
+            }
+            ARMARX_CHECK_EQUAL(controlDevices.size(), controllers.size());
+            return controllers;
+        }
+
+        std::vector<JointController *> Devices::getEmergencyStopJointControllers() const
+        {
+            throwIfDevicesNotReady(__FUNCTION__);
+            throwIfInControlThread(__FUNCTION__);
+
+            std::vector<JointController*> controllers;
+            controllers.reserve(controlDevices.values().size());
+            for(const ControlDevicePtr& dev : controlDevices.values())
+            {
+                ARMARX_CHECK_NOT_NULL(dev);
+                controllers.emplace_back(dev->rtGetJointEmergencyStopController());
+                ARMARX_CHECK_NOT_NULL(controllers.back());
+            }
+            ARMARX_CHECK_EQUAL(controlDevices.size(), controllers.size());
+            return controllers;
+        }
+
+        void Devices::_preFinishDeviceInitialization()
+        {
+            throwIfInControlThread(__FUNCTION__);
+            if (!sensorDevices.has(rtThreadTimingsSensorDeviceName))
+            {
+                addSensorDevice(createRTThreadTimingSensorDevice());
+            }
+        }
+
+        void Devices::_postFinishDeviceInitialization()
+        {
+            throwIfInControlThread(__FUNCTION__);
+            ARMARX_DEBUG << "checking " << controlDevices.size() << " ControlDevices:";
+            {
+                for (const ControlDevicePtr& controlDevice : controlDevices.values())
+                {
+                    ARMARX_CHECK_EXPRESSION(controlDevice);
+                    ARMARX_DEBUG << "----" << controlDevice->getDeviceName();
+                    if (!controlDevice->hasJointController(ControlModes::EmergencyStop))
+                    {
+                        std::stringstream s;
+                        s << "ControlDevice " << controlDevice->getDeviceName()
+                          << " has no JointController with ControlMode " << ControlModes::EmergencyStop
+                          << " (to fix this, add a JointController with this ControlMode to the ControlDevice).\nAvailable controllers: "
+                          <<  controlDevice->getControlModes();
+                        ARMARX_ERROR << "--------" << s.str();
+                        throw LogicError {s.str()};
+
+                    }
+                    if (!controlDevice->hasJointController(ControlModes::StopMovement))
+                    {
+                        std::stringstream s;
+                        s << "ControlDevice " << controlDevice->getDeviceName()
+                          << " has no JointController with ControlMode \"" << ControlModes::StopMovement
+                          << "\" (to fix this, add a JointController with this ControlMode to the ControlDevice) \nAvailable controllers: "
+                          << controlDevice->getControlModes();
+                        ARMARX_ERROR << "--------" << s.str();
+                        throw LogicError {s.str()};
+                    }
+                }
+            }
+            ARMARX_DEBUG << "checking " << controlDevices.size() << " SensorDevices:";
+            {
+                for (const SensorDevicePtr& sensorDevice : sensorDevices.values())
+                {
+                    ARMARX_CHECK_EXPRESSION(sensorDevice);
+                    ARMARX_DEBUG << "----" << sensorDevice->getDeviceName();
+                    if (!sensorDevice->getSensorValue())
+                    {
+                        std::stringstream s;
+                        s << "SensorDevice " << sensorDevice->getSensorValue() << " has null SensorValue";
+                        ARMARX_ERROR << "--------" << s.str();
+                        throw LogicError {s.str()};
+                    }
+                    ARMARX_CHECK_EXPRESSION(sensorDevice);
+                }
+            }
+            ARMARX_DEBUG << "copying device ptrs to const ptr map";
+            {
+                for (const auto& dev : controlDevices.values())
+                {
+                    controlDevicesConstPtr[dev->getDeviceName()] = dev;
+                }
+                for (const auto& dev : sensorDevices.values())
+                {
+                    sensorDevicesConstPtr[dev->getDeviceName()] = dev;
+                }
+            }
+            ARMARX_DEBUG << "copy sensor values";
+            {
+                ARMARX_CHECK_EXPRESSION(sensorValues.empty());
+                sensorValues.reserve(sensorDevices.values().size());
+                for(const SensorDevicePtr& dev : sensorDevices.values())
+                {
+                    ARMARX_CHECK_NOT_NULL(dev);
+                    sensorValues.emplace_back(dev->getSensorValue());
+                    ARMARX_CHECK_NOT_NULL(sensorValues.back());
+                }
+            }
+            ARMARX_DEBUG << "copy control targets";
+            {
+                ARMARX_CHECK_EXPRESSION(controlTargets.empty());
+                controlTargets.reserve(controlDevices.values().size());
+                for(const ControlDevicePtr& dev : controlDevices.values())
+                {
+                    ARMARX_CHECK_NOT_NULL(dev);
+                    controlTargets.emplace_back();
+                    controlTargets.back().reserve(dev->rtGetJointControllers().size());
+                    for(JointController* ctrl : dev->rtGetJointControllers())
+                    {
+                        ARMARX_CHECK_NOT_NULL(ctrl);
+                        controlTargets.back().emplace_back(ctrl->getControlTarget());
+                        ARMARX_CHECK_NOT_NULL(controlTargets.back().back().get());
+                    }
+                }
+            }
+            ARMARX_DEBUG << "setup ControlDeviceHardwareControlModeGroups";
+            {
+                ctrlModeGroups.groupIndices.assign(getNumberOfControlDevices(), IndexSentinel());
+
+                if (!ctrlModeGroups.groupsMerged.empty())
+                {
+                    ARMARX_DEBUG << "Remove control devs from ControlDeviceHardwareControlModeGroups ("
+                                 << ctrlModeGroups.groups.size() << ")";
+                    const auto groupsMerged = ctrlModeGroups.groupsMerged;
+                    for (const auto& dev : groupsMerged)
+                    {
+                        if (controlDevices.has(dev))
+                        {
+                            continue;
+                        }
+                        ctrlModeGroups.groupsMerged.erase(dev);
+                        for (auto& group : ctrlModeGroups.groups)
+                        {
+                            group.erase(dev);
+                        }
+                        ARMARX_DEBUG << "----removing nonexistent device: " << dev;
+                    }
+                    //remove empty groups
+                    std::vector<std::set<std::string>> cleanedGroups;
+                    cleanedGroups.reserve(ctrlModeGroups.groups.size());
+                    for (auto& group : ctrlModeGroups.groups)
+                    {
+                        const auto sz = group.size();
+                        if (sz == 1)
+                        {
+                            ARMARX_DEBUG << "----removing group with one dev: " << *group.begin();
+                        }
+                        else if (sz > 1)
+                        {
+                            cleanedGroups.emplace_back(std::move(group));
+                        }
+                    }
+                    ctrlModeGroups.groups = cleanedGroups;
+                    ARMARX_DEBUG << "----number of groups left: " << ctrlModeGroups.groups.size();
+                }
+                if (!ctrlModeGroups.groupsMerged.empty())
+                {
+                    ARMARX_DEBUG << "Checking control modes for ControlDeviceHardwareControlModeGroups ("
+                                 << ctrlModeGroups.groups.size() << ")";
+                    ctrlModeGroups.deviceIndices.resize(ctrlModeGroups.groups.size());
+                    //iterate over groups
+                    for (std::size_t groupIdx = 0; groupIdx < ctrlModeGroups.groups.size(); ++groupIdx)
+                    {
+                        const std::set<std::string>& group = ctrlModeGroups.groups.at(groupIdx);
+                        ctrlModeGroups.deviceIndices.at(groupIdx).reserve(group.size());
+                        ARMARX_CHECK_EXPRESSION(!group.empty());
+                        ARMARX_DEBUG << "----Group " << groupIdx << " size: " << group.size();
+                        //gets a map of ControlMode->HardwareControlMode for the given device
+                        const auto getControlModeToHWControlMode = [&](const std::string & devname)
+                        {
+                            std::map<std::string, std::string> controlModeToHWControlMode;
+                            const ControlDevicePtr& cd = controlDevices.at(devname);
+                            for (const auto& jointCtrl : cd->getJointControllers())
+                            {
+                                controlModeToHWControlMode[jointCtrl->getControlMode()] = jointCtrl->getHardwareControlMode();
+                            }
+                            return controlModeToHWControlMode;
+                        };
+                        //get modes of first dev
+                        const auto controlModeToHWControlMode = getControlModeToHWControlMode(*group.begin());
+                        //check other devs
+                        for (const auto& devname : group)
+                        {
+                            ARMARX_CHECK_EXPRESSION_W_HINT(
+                                controlDevices.has(devname),
+                                "The ControlDeviceHardwareControlModeGroups property contains device names not existent in the robot: "
+                                << devname << "\navailable:\n" << controlDevices.keys()
+                            );
+                            //Assert all devices in a group have the same control modes with the same hw controle modes
+                            const auto controlModeToHWControlModeForDevice = getControlModeToHWControlMode(devname);
+                            ARMARX_CHECK_EXPRESSION_W_HINT(
+                                controlModeToHWControlModeForDevice == controlModeToHWControlMode,
+                                "Error for control modes of device '" << devname << "'\n"
+                                << "it has the modes: " << controlModeToHWControlModeForDevice
+                                << "\n but should have the modes: " << controlModeToHWControlMode
+                            );
+                            //insert the device index into the device indices
+                            const auto devIdx = controlDevices.index(devname);
+                            ctrlModeGroups.deviceIndices.at(groupIdx).emplace_back(devIdx);
+                            //insert the group index into the group indices (+ check the current group index is the sentinel
+                            ARMARX_CHECK_EXPRESSION(ctrlModeGroups.groupIndices.size() > devIdx);
+                            ARMARX_CHECK_EXPRESSION(ctrlModeGroups.groupIndices.at(devIdx) == IndexSentinel());
+                            ctrlModeGroups.groupIndices.at(devIdx) = groupIdx;
+                            ARMARX_DEBUG << "------- " << devname;
+                        }
+                    }
+                }
+            }
+            ARMARX_DEBUG << "create mapping from sensor values to robot nodes";
+            {
+                ARMARX_CHECK_EXPRESSION(simoxRobotSensorValueMapping.empty());
+                VirtualRobot::RobotPtr r = _module<RobotData>().cloneRobot();
+                const auto nodes = r->getRobotNodes();
+                for(std::size_t idxRobot = 0; idxRobot < nodes.size(); ++idxRobot)
+                {
+                    const VirtualRobot::RobotNodePtr& node = nodes.at(idxRobot);
+                    if(node->isRotationalJoint() || node->isTranslationalJoint())
+                    {
+                        const auto& name = node->getName();
+                        if(sensorDevices.has(name))
+                        {
+                            const auto& dev = sensorDevices.at(name);
+                            if(dev->getSensorValue()->isA<SensorValue1DoFActuatorPosition>())
+                            {
+                                SimoxRobotSensorValueMapping m;
+                                m.idxRobot = idxRobot;
+                                m.idxSens = sensorDevices.index(name);
+                                simoxRobotSensorValueMapping.emplace_back(m);
+                            }
+                            else
+                            {
+                                ARMARX_WARNING << "SensorValue for SensorDevice " << name << " has no position data";
+                            }
+                        }
+                        else
+                        {
+                            ARMARX_INFO << "No SensorDevice for RobotNode: " << name;
+                        }
+                    }
+                }
+            }
+
+            ARMARX_VERBOSE << "ControlDevices:\n" << controlDevices.keys();
+            ARMARX_VERBOSE << "SensorDevices:\n" << sensorDevices.keys();
+        }
+
+        void Devices::_preOnInitRobotUnit()
+        {
+            throwIfInControlThread(__FUNCTION__);
+            //ControlDeviceHardwareControlModeGroups
+            const std::string controlDeviceHardwareControlModeGroupsStr = getProperty<std::string>("ControlDeviceHardwareControlModeGroups").getValue();
+            if (!controlDeviceHardwareControlModeGroupsStr.empty())
+            {
+                const auto numGroups = std::count(
+                            controlDeviceHardwareControlModeGroupsStr.begin(),
+                            controlDeviceHardwareControlModeGroupsStr.end(), ';'
+                            ) + 1;
+                ctrlModeGroups.groups.reserve(numGroups);
+                std::vector<std::string> strGroups;
+                strGroups.reserve(numGroups);
+                boost::algorithm::split(strGroups, controlDeviceHardwareControlModeGroupsStr, boost::is_any_of(";"));
+                for (const auto& gstr : strGroups)
+                {
+                    std::vector<std::string> strElems;
+                    boost::algorithm::split(strElems, gstr, boost::is_any_of(","));
+                    std::set<std::string> group;
+                    for (auto& device : strElems)
+                    {
+                        boost::algorithm::trim(device);
+                        ARMARX_CHECK_EXPRESSION_W_HINT(
+                                    !device.empty(),
+                                    "The ControlDeviceHardwareControlModeGroups property contains empty device names"
+                                    );
+                        ARMARX_CHECK_EXPRESSION_W_HINT(
+                                    !ctrlModeGroups.groupsMerged.count(device),
+                                    "The ControlDeviceHardwareControlModeGroups property contains duplicate device names: " << device
+                                    );
+                        ctrlModeGroups.groupsMerged.emplace(device);
+                        group.emplace(std::move(device));
+                    }
+                    if (!group.empty())
+                    {
+                        ARMARX_DEBUG << "adding device group:\n"
+                                     << ARMARX_STREAM_PRINTER
+                        {
+                                        for (const auto& elem : group)
+                        {
+                                        out << "    " << elem << "\n";
+                    }
+                    };
+                        ctrlModeGroups.groups.emplace_back(std::move(group));
+                    }
+                }
+            }
+        }
+    }
+}
diff --git a/source/RobotAPI/components/units/RobotUnit/RobotUnitModules/RobotUnitModuleDevices.h b/source/RobotAPI/components/units/RobotUnit/RobotUnitModules/RobotUnitModuleDevices.h
new file mode 100644
index 0000000000000000000000000000000000000000..0872a2be7a9d1a6a5378baf6d4c237b347d3d945
--- /dev/null
+++ b/source/RobotAPI/components/units/RobotUnit/RobotUnitModules/RobotUnitModuleDevices.h
@@ -0,0 +1,449 @@
+/*
+ * This file is part of ArmarX.
+ *
+ * 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    RobotAPI::ArmarXObjects::RobotUnit
+ * @author     Raphael Grimm ( raphael dot grimm at kit dot edu )
+ * @date       2018
+ * @copyright  http://www.gnu.org/licenses/gpl-2.0.txt
+ *             GNU General Public License
+ */
+
+#pragma once
+
+#include <mutex>
+
+#include <RobotAPI/interface/units/RobotUnit/RobotUnitInterface.h>
+#include "RobotUnitModuleBase.h"
+
+#include "../Devices/ControlDevice.h"
+#include "../Devices/SensorDevice.h"
+#include "../Devices/RTThreadTimingsSensorDevice.h"
+
+#include "../SensorValues/SensorValue1DoFActuator.h"
+
+namespace armarx
+{
+
+    namespace RobotUnitModule
+    {
+        class DevicesPropertyDefinitions: public ModuleBasePropertyDefinitions
+        {
+        public:
+            DevicesPropertyDefinitions(std::string prefix): ModuleBasePropertyDefinitions(prefix)
+            {
+                defineOptionalProperty<std::string>(
+                    "ControlDeviceHardwareControlModeGroups", "",
+                    "Groups of control devices for which the same hardware control mode has to be set. "
+                    "For a control mode, the JointControllers of all devices in a group must have the identical hardware control mode. "
+                    "The kinematic unit will change the control mode of all joints in a group,"
+                    " if their current hw control mode does not match the new hw control mode. "
+                    "This can be used if the robot has a multi DOF joint which is represented by multiple  1DOF control devices "
+                    "(in such a case all of these 1DOF joints should have the same hw control mode, "
+                    "except he multi DOF joint can handle different control modes at once). "
+                    "Syntax: semicolon separated groups , each group is CSV of joints "
+                    "e.g. j1,j2;j3,j4,j5 -> Group 1 = j1+j2 Group 2 = j3+j4+j5; No joint may be in two groups!"
+                );
+            }
+        };
+
+        /**
+         * @brief This \ref ModuleBase "Module" manages sensor and control devices for a RobotUnit and only allows save and sane access.
+         *
+         * @see ModuleBase
+         */
+        class Devices : virtual public ModuleBase, virtual public RobotUnitDevicesInterface
+        {
+            friend class ModuleBase;
+        public:
+            struct ControlDeviceHardwareControlModeGroups;
+            /**
+             * @brief Returns the singleton instance of this class
+             * @return The singleton instance of this class
+             */
+            static Devices& Instance()
+            {
+                return ModuleBase::Instance<Devices>();
+            }
+            // //////////////////////////////////////////////////////////////////////////////////////// //
+            // ///////////////////////////////// RobotUnitModule hooks //////////////////////////////// //
+            // //////////////////////////////////////////////////////////////////////////////////////// //
+        private:
+            /// @see ModuleBase::_preOnInitRobotUnit
+            void _preOnInitRobotUnit();
+            /// @see ModuleBase::_preFinishDeviceInitialization
+            void _preFinishDeviceInitialization();
+            /// @see ModuleBase::_postFinishDeviceInitialization
+            void _postFinishDeviceInitialization();
+            /// @see ModuleBase::_postFinishRunning
+            void _postFinishRunning();
+            // //////////////////////////////////////////////////////////////////////////////////////// //
+            // ///////////////////////////////////// ice interface //////////////////////////////////// //
+            // //////////////////////////////////////////////////////////////////////////////////////// //
+        public:
+            /**
+             * @brief Returns the names of all \ref ControlDevice "ControlDevices" for the robot.
+             * @return The names of all \ref ControlDevice "ControlDevices" for the robot.
+             */
+            Ice::StringSeq getControlDeviceNames(const Ice::Current& = GlobalIceCurrent) const override;
+
+            /**
+             * @brief Return the \ref ControlDeviceDescription for the given \ref ControlDevice
+             * @param name The \ref ControlDevice
+             * @return The \ref ControlDeviceDescription
+             * @see ControlDeviceDescription
+             * @see getControlDeviceDescriptions
+             */
+            ControlDeviceDescription getControlDeviceDescription(const std::string& name, const Ice::Current& = GlobalIceCurrent) const override;
+            /**
+             * @brief Return the \ref ControlDeviceDescription "ControlDeviceDescriptions" for all \ref ControlDevice "ControlDevices"
+             * @return The \ref ControlDeviceDescription "ControlDeviceDescriptions"
+             * @see ControlDeviceDescription
+             * @see getControlDeviceDescription
+             */
+            ControlDeviceDescriptionSeq getControlDeviceDescriptions(const Ice::Current& = GlobalIceCurrent) const override;
+
+            /**
+             * @brief Return the \ref ControlDeviceStatus for the given \ref ControlDevice
+             * @param name The \ref ControlDevice
+             * @return The \ref ControlDeviceStatus
+             * @see ControlDeviceStatus
+             * @see getControlDeviceStatuses
+             */
+            ControlDeviceStatus getControlDeviceStatus(const std::string& name, const Ice::Current& = GlobalIceCurrent) const override;
+            /**
+             * @brief Return the \ref ControlDeviceStatus "ControlDeviceStatuses" for all \ref ControlDevice "ControlDevices"
+             * @return The \ref ControlDeviceStatus "ControlDeviceStatuses"
+             * @see ControlDeviceStatus
+             * @see getControlDeviceStatus
+             */
+            ControlDeviceStatusSeq getControlDeviceStatuses(const Ice::Current& = GlobalIceCurrent) const override;
+
+            /**
+             * @brief Returns the names of all \ref SensorDevice "SensorDevices" for the robot.
+             * @return The names of all \ref SensorDevice "ControlDevices" for the robot.
+             */
+            Ice::StringSeq getSensorDeviceNames(const Ice::Current& = GlobalIceCurrent) const override;
+
+            /**
+             * @brief Return the \ref SensorDeviceDescription for the given \ref SensorDevice
+             * @param name The \ref SensorDevice
+             * @return The \ref SensorDeviceDescription
+             * @see SensorDeviceDescription
+             * @see getSensorDeviceDescriptions
+             */
+            SensorDeviceDescription getSensorDeviceDescription(const std::string& name, const Ice::Current& = GlobalIceCurrent) const override;
+            /**
+             * @brief Return the \ref SensorDeviceDescription "SensorDeviceDescriptions" for all \ref SensorDevice "SensorDevices"
+             * @return The \ref SensorDeviceDescription "SensorDeviceDescriptions"
+             * @see SensorDeviceDescription
+             * @see getSensorDeviceDescription
+             */
+            SensorDeviceDescriptionSeq getSensorDeviceDescriptions(const Ice::Current& = GlobalIceCurrent) const override;
+
+            /**
+             * @brief Return the \ref SensorDeviceStatus for the given \ref SensorDevice
+             * @param name The \ref SensorDevice
+             * @return The \ref SensorDeviceStatus
+             * @see SensorDeviceStatus
+             * @see getSensorDeviceStatuses
+             */
+            SensorDeviceStatus getSensorDeviceStatus(const std::string& name, const Ice::Current& = GlobalIceCurrent) const override;
+            /**
+             * @brief Return the \ref SensorDeviceStatus "SensorDeviceStatuses" for all \ref SensorDevice "SensorDevices"
+             * @return The \ref SensorDeviceStatus "SensorDeviceStatuses"
+             * @see SensorDeviceStatus
+             * @see getSensorDeviceStatus
+             */
+            SensorDeviceStatusSeq getSensorDeviceStatuses(const Ice::Current& = GlobalIceCurrent) const override;
+            // //////////////////////////////////////////////////////////////////////////////////////// //
+            // /////////////////////////////////// Module interface /////////////////////////////////// //
+            // //////////////////////////////////////////////////////////////////////////////////////// //
+        public:
+            /**
+             * @brief Returns the number of \ref ControlDevice "ControlDevices"
+             * @return The number of \ref ControlDevice "ControlDevices"
+             */
+            std::size_t getNumberOfControlDevices() const;
+            /**
+             * @brief Returns the number of \ref SensorDevice "SensorDevices"
+             * @return The number of \ref SensorDevice "SensorDevices"
+             */
+            std::size_t getNumberOfSensorDevices() const;
+
+            /**
+             * @brief Return the \ref ControlDeviceDescription for the given \ref ControlDevice
+             * @param idx The \ref ControlDevice's index
+             * @return The \ref ControlDeviceDescription for the given \ref ControlDevice
+             * @see ControlDeviceDescription
+             * @see getControlDeviceDescription
+             * @see getControlDeviceDescriptions
+             */
+            ControlDeviceDescription getControlDeviceDescription(std::size_t idx) const;
+            /**
+             * @brief Return the \ref ControlDeviceStatus for the given \ref ControlDevice
+             * @param idx The \ref ControlDevice's index
+             * @return The \ref ControlDeviceStatus
+             * @see ControlDeviceStatus
+             * @see getControlDeviceStatus
+             * @see getControlDeviceStatuses
+             */
+            ControlDeviceStatus getControlDeviceStatus(std::size_t idx) const;
+
+            /**
+             * @brief Return the \ref SensorDeviceDescription for the given \ref SensorDevice
+             * @param idx The \ref SensorDevice's index
+             * @return The \ref SensorDeviceDescription for the given \ref SensorDevice
+             * @see SensorDeviceDescription
+             * @see getSensorDeviceDescription
+             * @see getSensorDeviceDescriptions
+             */
+            SensorDeviceDescription getSensorDeviceDescription(std::size_t idx) const;
+            /**
+             * @brief Return the \ref SensorDeviceStatus for the given \ref SensorDevice
+             * @param idx The \ref SensorDevice's index
+             * @return The \ref SensorDeviceStatus
+             * @see SensorDeviceStatus
+             * @see getSensorDeviceStatus
+             * @see getSensorDeviceStatuses
+             */
+            SensorDeviceStatus getSensorDeviceStatus(std::size_t idx) const;
+
+            /**
+             * @brief Updates the given VirtualRobot with the given \ref SensorValue "SensorValues"
+             * @param robot The VirtualRobot to update
+             * @param sensors The \ref SensorValue "SensorValues"
+             */
+            template<class PtrT>
+            void updateVirtualRobotFromSensorValues(const VirtualRobot::RobotPtr& robot, const std::vector<PtrT>& sensors) const
+            {
+                updateVirtualRobotFromSensorValues(robot, robot->getRobotNodes(), sensors);
+            }
+            /**
+             * @brief Updates the given VirtualRobot with the given \ref SensorValue "SensorValues"
+             *
+             * This overload is slightly faster than the other version.
+             * @param robot The VirtualRobot to update
+             * @param nodes The VirtualRobot's RobotNodes
+             * @param sensors The \ref SensorValue "SensorValues"
+             */
+            template<class PtrT>
+            void updateVirtualRobotFromSensorValues(const VirtualRobot::RobotPtr& robot, const std::vector<VirtualRobot::RobotNodePtr>& nodes, const std::vector<PtrT>& sensors) const
+            {
+                for(const SimoxRobotSensorValueMapping& m : simoxRobotSensorValueMapping)
+                {
+                    const SensorValueBase* sv = sensors.at(m.idxSens);
+                    ARMARX_CHECK_NOT_NULL(sv);
+                    const SensorValue1DoFActuatorPosition* svPos = sv->asA<SensorValue1DoFActuatorPosition>();
+                    ARMARX_CHECK_NOT_NULL(svPos);
+                    nodes.at(m.idxRobot)->setJointValueNoUpdate(svPos->position);
+                }
+                robot->applyJointValues();
+            }
+
+            /**
+             * @brief Returns the groups of \ref ControlDevice "ControlDevices" required to be in the same
+             * hardware control mode. (explained \ref RobotUnitCtrlModeGroups "here")
+             * @return The groups of \ref ControlDevice "ControlDevices" required to be in the same
+             * hardware control mode.
+             */
+            const ControlDeviceHardwareControlModeGroups& getControlModeGroups() const
+            {
+                return ctrlModeGroups;
+            }
+
+            /**
+             * @brief Returns the \ref ControlDevice's index
+             * @param deviceName \ref ControlDevice's name.
+             * @return The \ref ControlDevice's index
+             */
+            std::size_t getControlDeviceIndex(const std::string& deviceName) const;
+            /**
+             * @brief Returns the \ref SensorDevice's index
+             * @param deviceName \ref SensorDevice's name.
+             * @return The \ref SensorDevice's index
+             */
+            std::size_t getSensorDeviceIndex(const std::string& deviceName) const;
+
+            /**
+             * @brief Returns the \ref ControlDevice
+             * @param deviceName \ref ControlDevice's name.
+             * @return The \ref ControlDevice
+             */
+            ConstControlDevicePtr getControlDevice(const std::string& deviceName) const; /// TODO move to attorney for NJointController
+            /**
+             * @brief Returns the \ref SensorDevice
+             * @param deviceName \ref SensorDevice's name.
+             * @return The \ref SensorDevice
+             */
+            ConstSensorDevicePtr getSensorDevice(const std::string& deviceName) const; /// TODO move to attorney for NJointController
+
+            /**
+             * @brief Returns all \ref SensorDevice "SensorDevices"
+             * @return All \ref SensorDevice "SensorDevices"
+             */
+            const KeyValueVector<std::string, SensorDevicePtr>& getSensorDevices() const ///TODO remove from interface
+            {
+                return sensorDevices;
+            }
+
+            /**
+             * @brief Returns all \ref ControlDevice "ControlDevices"
+             * @return All \ref ControlDevice "ControlDevices"
+             */
+            const KeyValueVector<std::string, ControlDevicePtr>& getControlDevices() const ///TODO remove from interface
+            {
+                return controlDevices;
+            }
+
+            /**
+             * @brief Returns const pointers to  all \ref SensorDevice "SensorDevices"
+             * @return Const pointers to all \ref SensorDevice "SensorDevices"
+             */
+            const std::map<std::string, ConstSensorDevicePtr>& getSensorDevicesConstPtr() const ///TODO rename to getSensorDevices
+            {
+                return sensorDevicesConstPtr;
+            }
+            /**
+             * @brief Returns const pointers to all \ref ControlDevice "ControlDevices"
+             * @return Const pointers to all \ref ControlDevice "ControlDevices"
+             */
+            const std::map<std::string, ConstControlDevicePtr>& getControlDevicesConstPtr() const ///TODO rename to getControlDevices
+            {
+                return controlDevicesConstPtr;
+            }
+        protected:
+            /**
+             * @brief Adds a \ref ControlDevice to the robot.
+             * \warning Must not be called when the \ref RobotUnit's \ref RobotUnitState "state" is not \ref RobotUnitState::InitializingDevices
+             * @param cd The \ref ControlDevice to add
+             */
+            void addControlDevice(const ControlDevicePtr& cd);
+            /**
+             * @brief Adds a \ref SensorDevice to the robot.
+             * \warning Must not be called when the \ref RobotUnit's \ref RobotUnitState "state" is not \ref RobotUnitState::InitializingDevices
+             * @param cd The \ref SensorDevice to add
+             */
+            void addSensorDevice(const SensorDevicePtr& sd);
+            /**
+             * @brief Creates the \ref SensorDevice used to log timings in the \ref ControlThread
+             * (This function is supposed to be used in the \ref ModuleBase::finishDeviceInitialization)
+             * @return The \ref SensorDevice used to log timings in the \ref ControlThread
+             * @see rtGetRTThreadTimingsSensorDevice
+             */
+            virtual RTThreadTimingsSensorDevicePtr createRTThreadTimingSensorDevice() const;
+            /**
+             * @brief Returns the \ref SensorDevice used to log timings in the \ref ControlThread.
+             * (This function is supposed to be used in the \ref ControlThread)
+             * @return The \ref SensorDevice used to log timings in the \ref ControlThread
+             * @see createRTThreadTimingSensorDevice
+             */
+            RTThreadTimingsSensorDevice& rtGetRTThreadTimingsSensorDevice()
+            {
+                return *rtThreadTimingsSensorDevice;
+            }
+            // //////////////////////////////////////////////////////////////////////////////////////// //
+            // //////////////////////////////////// implementation //////////////////////////////////// //
+            // //////////////////////////////////////////////////////////////////////////////////////// //
+        private:
+            /**
+             * @brief Returns the stop movement \ref JointController "JointControllers"
+             * for all \ref ControlDevice "ControlDevices"
+             * @return The stop movement \ref JointController "JointControllers"
+             */
+            std::vector<JointController*> getStopMovementJointControllers() const;
+            /**
+             * @brief Returns the emergency stop \ref JointController "JointControllers"
+             * for all \ref ControlDevice "ControlDevices"
+             * @return The emergency stop \ref JointController "JointControllers"
+             */
+            std::vector<JointController*> getEmergencyStopJointControllers() const;
+            // //////////////////////////////////////////////////////////////////////////////////////// //
+            // ///////////////////////////////////////// Data ///////////////////////////////////////// //
+            // //////////////////////////////////////////////////////////////////////////////////////// //
+        private:
+            /// @brief Struct correlating a \ref VirtualRobot::RobotNode to a \ref SensorDevice
+            struct SimoxRobotSensorValueMapping
+            {
+                /// @brief The RobotNode's index
+                std::size_t idxRobot;
+                /// @brief The \ref SensorDevice's index
+                std::size_t idxSens;
+            };
+            /// @brief Mapping from RobotNode index to \ref SensorDevice
+            std::vector<SimoxRobotSensorValueMapping> simoxRobotSensorValueMapping;
+            /// @brief Pointers to all \ref SensorValueBase "SensorValues"
+            std::vector<const SensorValueBase*> sensorValues;
+            /// @brief Pointers to all \ref ControlTargetBase "ControlTargets"
+            std::vector<std::vector<PropagateConst<ControlTargetBase*>>> controlTargets;
+        public:
+            /// @brief Holds data about a device group requiring the same hardware control mode. (explained \ref RobotUnitCtrlModeGroups "here")
+            struct ControlDeviceHardwareControlModeGroups
+            {
+                /// @brief contains a vector per group.
+                /// Each vector contains the names of devices in this group.
+                std::vector<std::set<std::string>> groups;
+                /// @brief contains a vector per group.
+                /// Each vector contains the indices of devices in this group.
+                std::vector<std::vector<std::size_t>> deviceIndices;
+                /// @brief contains the names of all devices in any group
+                std::set<std::string> groupsMerged;
+                /// @brief contains the group index for each device (or the sentinel)
+                std::vector<std::size_t> groupIndices;
+            };
+        private:
+            /// @brief Device groups requiring the same hardware control mode.
+            ControlDeviceHardwareControlModeGroups ctrlModeGroups;
+
+            /// @brief ControlDevices added to this unit (data may only be added during and only be used after State::InitializingDevices)
+            KeyValueVector<std::string, ControlDevicePtr> controlDevices;
+            /// @brief SensorDevices added to this unit (data may only be added during and only be used after State::InitializingDevices)
+            KeyValueVector<std::string, SensorDevicePtr > sensorDevices;
+
+            /// @brief const pointer to all ControlDevices (passed to GenerateConfigDescription of a NJointController)
+            std::map<std::string, ConstControlDevicePtr> controlDevicesConstPtr;
+            /// @brief const pointer to all SensorDevices (passed to GenerateConfigDescription of a NJointController)
+            std::map<std::string, ConstSensorDevicePtr> sensorDevicesConstPtr;
+
+            /// @brief a pointer to the RTThreadTimingsSensorDevice used to meassure timings in the rt loop
+            RTThreadTimingsSensorDevicePtr rtThreadTimingsSensorDevice;
+            /// @brief The device name of rtThreadTimingsSensorDevice
+            static const std::string rtThreadTimingsSensorDeviceName;
+            // //////////////////////////////////////////////////////////////////////////////////////// //
+            // /////////////////////////////////////// Attorneys ////////////////////////////////////// //
+            // //////////////////////////////////////////////////////////////////////////////////////// //
+        private:
+            /**
+            * \brief This class allows minimal access to private members of \ref Devices in a sane fashion for \ref Publisher.
+            * \warning !! DO NOT ADD ADDITIONAL FRIENDS IF YOU DO NOT KNOW WAHT YOU ARE DOING! IF YOU DO SOMETHING WRONG YOU WILL CAUSE UNDEFINED BEHAVIOUR !!
+            */
+            friend class DevicesAttorneyForPublisher;
+            /**
+            * \brief This class allows minimal access to private members of \ref Devices in a sane fashion for \ref ControlThread.
+            * \warning !! DO NOT ADD ADDITIONAL FRIENDS IF YOU DO NOT KNOW WAHT YOU ARE DOING! IF YOU DO SOMETHING WRONG YOU WILL CAUSE UNDEFINED BEHAVIOUR !!
+            */
+            friend class DevicesAttorneyForControlThread;
+            /**
+            * \brief This class allows minimal access to private members of \ref Devices in a sane fashion for \ref ControlThreadDataBuffer.
+            * \warning !! DO NOT ADD ADDITIONAL FRIENDS IF YOU DO NOT KNOW WAHT YOU ARE DOING! IF YOU DO SOMETHING WRONG YOU WILL CAUSE UNDEFINED BEHAVIOUR !!
+            */
+            friend class DevicesAttorneyForControlThreadDataBuffer;
+            /**
+             * \brief This class allows minimal access to private members of \ref armarx::RobotUnitModule::Devices in a sane fashion for \ref armarx::NJointController.
+            * \warning !! DO NOT ADD ADDITIONAL FRIENDS IF YOU DO NOT KNOW WAHT YOU ARE DOING! IF YOU DO SOMETHING WRONG YOU WILL CAUSE UNDEFINED BEHAVIOUR !!
+            */
+            friend class DevicesAttorneyForNJointController;
+        };
+    }
+}
diff --git a/source/RobotAPI/components/units/RobotUnit/RobotUnitModules/RobotUnitModuleLogging.cpp b/source/RobotAPI/components/units/RobotUnit/RobotUnitModules/RobotUnitModuleLogging.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..77675b15a15e595a02947c5104ab32829be0c1e8
--- /dev/null
+++ b/source/RobotAPI/components/units/RobotUnit/RobotUnitModules/RobotUnitModuleLogging.cpp
@@ -0,0 +1,503 @@
+/*
+ * This file is part of ArmarX.
+ *
+ * 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    RobotAPI::ArmarXObjects::RobotUnit
+ * @author     Raphael Grimm ( raphael dot grimm at kit dot edu )
+ * @date       2018
+ * @copyright  http://www.gnu.org/licenses/gpl-2.0.txt
+ *             GNU General Public License
+ */
+
+#include <ArmarXCore/core/util/FileSystemPathBuilder.h>
+#include <ArmarXCore/core/ArmarXManager.h>
+
+#include "RobotUnitModuleLogging.h"
+
+#include "RobotUnitModuleControlThreadDataBuffer.h"
+#include "RobotUnitModuleDevices.h"
+
+#include "../util/ControlThreadOutputBuffer.h"
+
+namespace armarx
+{
+    namespace RobotUnitModule
+    {
+        void Logging::addMarkerToRtLog(const RemoteReferenceCounterBasePtr &token, const std::string &marker, const Ice::Current &)
+        {
+            std::lock_guard<std::mutex> guard {rtLoggingMutex};
+            if (!rtLoggingEntries.count(token->getId()))
+            {
+                throw InvalidArgumentException {"addMarkerToRtLog called for a nonexistent log"};
+            }
+            rtLoggingEntries.at(token->getId())->marker = marker;
+        }
+
+        RemoteReferenceCounterBasePtr Logging::startRtLogging(const std::string &formatString, const Ice::StringSeq &loggingNames, const Ice::Current &)
+        {
+            StringStringDictionary alias;
+            for (const auto& name : loggingNames)
+            {
+                alias.emplace(name, "");
+            }
+            return startRtLoggingWithAliasNames(formatString, alias, GlobalIceCurrent);
+        }
+
+        void Logging::stopRtLogging(const RemoteReferenceCounterBasePtr &token, const Ice::Current &)
+        {
+            std::lock_guard<std::mutex> guard {rtLoggingMutex};
+            if (!rtLoggingEntries.count(token->getId()))
+            {
+                throw InvalidArgumentException {"addMarkerToRtLog called for a nonexistent log"};
+            }
+            ARMARX_DEBUG_S << "RobotUnit: stop RtLogging for file " << rtLoggingEntries.at(token->getId())->filename;
+            rtLoggingEntries.at(token->getId())->stopLogging = true;
+        }
+
+        Ice::StringSeq Logging::getLoggingNames(const Ice::Current &) const
+        {
+            Ice::StringSeq result;
+            for (const auto& strs : sensorDeviceValueLoggingNames)
+            {
+                result.insert(result.end(), strs.begin(), strs.end());
+            }
+            for (const auto& strvecss : controlDeviceValueLoggingNames)
+            {
+                for (const auto& strs : strvecss)
+                {
+                    result.insert(result.end(), strs.begin(), strs.end());
+                }
+            }
+            return result;
+        }
+
+        RemoteReferenceCounterBasePtr Logging::startRtLoggingWithAliasNames(const std::string &formatString, const StringStringDictionary &aliasNames, const Ice::Current &)
+        {
+            FileSystemPathBuilder pb {formatString};
+            std::lock_guard<std::mutex> guard {rtLoggingMutex};
+            if (rtLoggingEntries.count(pb.getPath()))
+            {
+                throw InvalidArgumentException {"There already is a logger for the path '" + pb.getPath() + "'"};
+            }
+            auto ptr = rtLoggingEntries[pb.getPath()];
+            CSVLoggingEntry& e = *ptr;
+            e.filename = pb.getPath();
+            pb.createParentDirectories();
+            e.stream.open(e.filename);
+            if (!e.stream)
+            {
+                rtLoggingEntries.erase(pb.getPath());
+                throw LogicError {"RtLogging could not open filestream for '" + pb.getPath() + "'"};
+            }
+
+            std::stringstream header;
+            header << "marker;iteration;timestamp";
+            auto logDev = [&](const std::string & dev)
+            {
+                for (const auto& pair : aliasNames)
+                {
+                    std::string name = pair.first;
+                    if (boost::starts_with(dev + "$", name))
+                    {
+                        if ((name.size() > 0 && name.back() == '$'))
+                        {
+                            name.resize(name.size() - 1);
+                        }
+                        const std::string& alias = pair.second.empty() ? name : pair.second;
+                        header << ";" << alias << dev.substr(name.size());
+                        return true;
+                    }
+                }
+                return false;
+            };
+
+            //get logged sensor device values
+            {
+                e.loggedSensorDeviceValues.reserve(sensorDeviceValueLoggingNames.size());
+                for (const auto& svfields : sensorDeviceValueLoggingNames)
+                {
+                    e.loggedSensorDeviceValues.emplace_back();
+                    auto& svfieldsFlags = e.loggedSensorDeviceValues.back(); //vv
+                    svfieldsFlags.reserve(svfields.size());
+                    for (const auto& field : svfields)
+                    {
+                        svfieldsFlags.emplace_back(logDev(field));
+                    }
+                }
+            }
+            //get logged control device values
+            {
+                e.loggedControlDeviceValues.reserve(controlDeviceValueLoggingNames.size());
+                for (const auto& sjctrls : controlDeviceValueLoggingNames)
+                {
+                    e.loggedControlDeviceValues.emplace_back();
+                    auto& sjctrlsFlags = e.loggedControlDeviceValues.back(); //vv
+                    sjctrlsFlags.reserve(sjctrls.size());
+                    for (const auto& ctargfields : sjctrls)
+                    {
+
+                        sjctrlsFlags.emplace_back();
+                        auto& ctargfieldsFlags = sjctrlsFlags.back(); //v
+                        ctargfieldsFlags.reserve(ctargfields.size());
+
+                        for (const auto& field : ctargfields)
+                        {
+                            ctargfieldsFlags.emplace_back(logDev(field));
+                        }
+                    }
+                }
+            }
+
+            //write header
+            e.stream << header.str() << std::flush; // newline is written at the beginning of each log line
+            //create and return handle
+            auto block = getArmarXManager()->createRemoteReferenceCount(
+                        [ptr]()
+            {
+                ARMARX_DEBUG_S << "RobotUnit: stop RtLogging for file " << ptr->filename;
+                ptr->stopLogging = true;
+            }, e.filename);
+            auto counter = block->getReferenceCounter();
+            block->activateCounting();
+            ARMARX_DEBUG_S << "RobotUnit: start RtLogging for file " << ptr->filename;
+            return counter;
+        }
+
+        void Logging::writeRecentIterationsToFile(const std::string &formatString, const Ice::Current &) const
+        {
+            std::lock_guard<std::mutex> guard {rtLoggingMutex};
+            FileSystemPathBuilder pb {formatString};
+            pb.createParentDirectories();
+            std::ofstream outCSV {pb.getPath() + ".csv"};
+            if (!outCSV)
+            {
+                throw LogicError {"writeRecentIterationsToFile could not open filestream for '" + pb.getPath() + ".csv'"};
+            }
+            std::ofstream outMsg {pb.getPath() + ".messages"};
+            if (!outMsg)
+            {
+                throw LogicError {"writeRecentIterationsToFile could not open filestream for '" + pb.getPath() + ".messages'"};
+            }
+            ARMARX_INFO << "writing the last " << backlog.size() << " iterations to " << pb.getPath() << ".{csv, messages}";
+            //write csv header
+            {
+                outCSV << "iteration;timestamp";
+                for (const auto& vs : sensorDeviceValueLoggingNames)
+                {
+                    for (const auto& s : vs)
+                    {
+                        outCSV << ";" << s;
+                    }
+                }
+                for (const auto& vvs : controlDeviceValueLoggingNames)
+                {
+                    for (const auto& vs : vvs)
+                    {
+                        for (const auto& s : vs)
+                        {
+                            outCSV << ";" << s;
+                        }
+                    }
+                }
+                outCSV << std::endl;
+            }
+
+            for (const ::armarx::detail::ControlThreadOutputBufferEntry& iteration : backlog)
+            {
+                //write csv data
+                {
+                    outCSV  << iteration.iteration << ";" << iteration.sensorValuesTimestamp;
+                    //sens
+                    {
+                        for (const SensorValueBase* val : iteration.sensors)
+                        {
+                            for (std::size_t idxField = 0; idxField < val->getNumberOfDataFields(); ++ idxField)
+                            {
+                                outCSV  << ";" << val->getDataFieldAsString(idxField);
+                            }
+                        }
+                    }
+                    //ctrl
+                    {
+                        for (const auto& vals : iteration.control)
+                        {
+                            for (const ControlTargetBase* val : vals)
+                            {
+                                for (std::size_t idxField = 0; idxField < val->getNumberOfDataFields(); ++ idxField)
+                                {
+                                    outCSV  << ";" << val->getDataFieldAsString(idxField);
+                                }
+                            }
+                        }
+                    }
+                    outCSV << std::endl;
+                }
+                //write message data
+                {
+                    for (const ::armarx::detail::RtMessageLogEntryBase* msg : iteration.messages.getEntries())
+                    {
+                        if (!msg)
+                        {
+                            break;
+                        }
+                        outMsg << "[" << msg->getTime().toDateTime() << "] iteration "
+                               << iteration.iteration << ":\n"
+                               << msg->format() << std::endl;
+                    }
+                    outMsg << "\nmessages lost: " << iteration.messages.messagesLost
+                           << " (required additional "
+                           << iteration.messages.requiredAdditionalBufferSpace << " bytes, "
+                           << iteration.messages.requiredAdditionalEntries << " message entries)\n" << std::endl;
+                }
+            }
+        }
+
+        void Logging::_preFinishRunning()
+        {
+            defaultLogHandle = nullptr;
+            if (rtLoggingTask)
+            {
+                ARMARX_DEBUG << "shutting down rt logging task";
+                rtLoggingTask->stop();
+                while (rtLoggingTask->isFunctionExecuting() || rtLoggingTask->isRunning())
+                {
+                    ARMARX_FATAL << deactivateSpam(0.1) << "RT LOGGING TASK IS RUNNING AFTER IT WAS STOPPED!";
+                }
+                rtLoggingTask = nullptr;
+                ARMARX_DEBUG << "shutting down rt logging task done";
+            }
+        }
+
+        void Logging::_preFinishControlThreadInitialization()
+        {
+            controlThreadId = LogSender::getThreadId();
+            ControlThreadOutputBuffer::RtLoggingInstance = &(_module<ControlThreadDataBuffer>().getControlThreadOutputBuffer());
+
+            ARMARX_INFO << "starting rt logging with timestep " << rtLoggingTimestep;
+            rtLoggingTask->start();
+        }
+
+        void Logging::doLogging()
+        {
+            std::lock_guard<std::mutex> guard {rtLoggingMutex};
+            const auto now = IceUtil::Time::now();
+            // entries are removed last
+
+            //remove backlog entries
+            {
+                while (!backlog.empty() && backlog.front().writeTimestamp + rtLoggingBacklogRetentionTime < now)
+                {
+                    backlog.pop_front();
+                }
+            }
+            //log all
+            {
+                _module<ControlThreadDataBuffer>().getControlThreadOutputBuffer().foreachNewLoggingEntry(
+                            [&](const ControlThreadOutputBuffer::Entry & data)
+                {
+                    //base (marker;iteration;timestamp)
+                    {
+                        for (auto& pair : rtLoggingEntries)
+                        {
+                            CSVLoggingEntry& e = *pair.second;
+                            e.stream << "\n"
+                                     << e.marker << ";"
+                                     << data.iteration << ";"
+                                     << data.sensorValuesTimestamp.toMicroSeconds();
+                            e.marker.clear();
+                        }
+                    }
+                    //sens
+                    {
+                        for (std::size_t idxDev = 0; idxDev < data.sensors.size(); ++ idxDev)
+                        {
+                            const SensorValueBase* val = data.sensors.at(idxDev);
+                            for (std::size_t idxField = 0; idxField < val->getNumberOfDataFields(); ++ idxField)
+                            {
+                                const auto str = val->getDataFieldAsString(idxField);
+                                for (auto& pair : rtLoggingEntries)
+                                {
+                                    CSVLoggingEntry& e = *pair.second;
+                                    if (e.loggedSensorDeviceValues.at(idxDev).at(idxField))
+                                    {
+                                        pair.second->stream  << ";" << str;
+                                    }
+                                }
+                            }
+                        }
+                    }
+                    //ctrl
+                    {
+                        for (std::size_t idxDev = 0; idxDev < data.control.size(); ++ idxDev)
+                        {
+                            const auto& vals = data.control.at(idxDev);
+                            for (std::size_t idxVal = 0; idxVal < vals.size(); ++idxVal)
+                            {
+                                const ControlTargetBase* val = vals.at(idxVal);
+                                for (std::size_t idxField = 0; idxField < val->getNumberOfDataFields(); ++ idxField)
+                                {
+                                    const auto str = val->getDataFieldAsString(idxField);
+                                    for (auto& pair : rtLoggingEntries)
+                                    {
+                                        CSVLoggingEntry& e = *pair.second;
+                                        if (e.loggedControlDeviceValues.at(idxDev).at(idxVal).at(idxField))
+                                        {
+                                            pair.second->stream  << ";" << str;
+                                        }
+                                    }
+                                }
+                            }
+                        }
+                    }
+                    //store data to backlog
+                    {
+                        if (data.writeTimestamp + rtLoggingBacklogRetentionTime >= now)
+                        {
+                            backlog.emplace_back(data, true); //true for minimal copy
+                        }
+                    }
+                    //print + reset messages
+                    {
+                        for (const ::armarx::detail::RtMessageLogEntryBase* ptr : data.messages.getEntries())
+                        {
+                            if (!ptr)
+                            {
+                                break;
+                            }
+                            ptr->print(controlThreadId);
+                        }
+                    }
+                });
+            }
+            ARMARX_DEBUG_S << ::deactivateSpam() << "the last " << backlog.size() << " iterations are stored";
+            //flush all files
+            {
+                for (auto& pair : rtLoggingEntries)
+                {
+                    pair.second->stream << std::flush;
+                }
+            }
+
+            //remove entries
+            {
+                std::vector<std::string> toRemove;
+                toRemove.reserve(rtLoggingEntries.size());
+                for (auto& pair : rtLoggingEntries)
+                {
+                    if (pair.second->stopLogging)
+                    {
+                        //can't remove the current elemet
+                        //(this would invalidate the current iterator)
+                        toRemove.emplace_back(pair.first);
+                    }
+                }
+                for (const auto& rem : toRemove)
+                {
+                    rtLoggingEntries.erase(rem);
+                }
+            }
+        }
+
+        void Logging::_postOnInitRobotUnit()
+        {
+            rtLoggingTimestep = getProperty<std::size_t>("RTLoggingPeriodMs");
+            ARMARX_CHECK_LESS_W_HINT(0, rtLoggingTimestep, "The property RTLoggingPeriodMs must not be 0");
+
+            messageBufferSize = getProperty<std::size_t>("RTLoggingMessageBufferSize");
+            messageBufferMaxSize = getProperty<std::size_t>("RTLoggingMaxMessageBufferSize");
+            ARMARX_CHECK_LESS_EQUAL(messageBufferSize, messageBufferMaxSize);
+
+            messageBufferNumberEntries = getProperty<std::size_t>("RTLoggingMessageNumber");
+            messageBufferMaxNumberEntries = getProperty<std::size_t>("RTLoggingMaxMessageNumber");
+            ARMARX_CHECK_LESS_EQUAL(messageBufferNumberEntries, messageBufferMaxNumberEntries);
+
+            rtLoggingBacklogRetentionTime = IceUtil::Time::milliSeconds(getProperty<std::size_t>("RTLoggingKeepIterationsForMs"));
+
+            ARMARX_CHECK_GREATER(getControlThreadTargetPeriod().toMicroSeconds(), 0);
+        }
+
+        void Logging::_postFinishDeviceInitialization()
+        {
+            //init buffer
+            {
+                std::size_t ctrlThreadPeriodUs = static_cast<std::size_t>(getControlThreadTargetPeriod().toMicroSeconds());
+                std::size_t logThreadPeriodUs = rtLoggingTimestep * 1000;
+                std::size_t nBuffers = (logThreadPeriodUs / ctrlThreadPeriodUs + 1) * 100;
+
+                const auto bufferSize = _module<ControlThreadDataBuffer>().getControlThreadOutputBuffer().initialize(
+                            nBuffers, _module<Devices>().getControlDevices(), _module<Devices>().getSensorDevices(),
+                            messageBufferSize, messageBufferNumberEntries,
+                            messageBufferMaxSize, messageBufferMaxNumberEntries);
+                ARMARX_INFO << "RTLogging activated! using "
+                            << nBuffers << "buffers "
+                            << "(buffersize = " << bufferSize << " bytes)";
+            }
+            //init logging names
+            {
+                //sensorDevices
+                controlDeviceValueLoggingNames.reserve(_module<Devices>().getControlDevices().size());
+                for (const auto& cd : _module<Devices>().getControlDevices().values())
+                {
+                    controlDeviceValueLoggingNames.emplace_back();
+                    auto& namesForDev = controlDeviceValueLoggingNames.back();
+                    namesForDev.reserve(cd->getJointControllers().size());
+                    for (auto jointC : cd->getJointControllers())
+                    {
+                        const auto names = jointC->getControlTarget()->getDataFieldNames();
+                        namesForDev.emplace_back();
+                        auto& fullNames = namesForDev.back();
+                        fullNames.reserve(names.size());
+                        for (const auto& name :  names)
+                        {
+                            fullNames.emplace_back(
+                                        "ctrl." +
+                                        cd->getDeviceName() + "." +
+                                        jointC->getControlMode() + "." +
+                                        name);
+                        }
+                    }
+                }
+                //sensorDevices
+                sensorDeviceValueLoggingNames.reserve(_module<Devices>().getSensorDevices().size());
+                for (const auto& sd : _module<Devices>().getSensorDevices().values())
+                {
+                    const auto names = sd->getSensorValue()->getDataFieldNames();
+                    sensorDeviceValueLoggingNames.emplace_back();
+                    auto& fullNames = sensorDeviceValueLoggingNames.back();
+                    fullNames.reserve(names.size());
+                    for (const auto& name :  names)
+                    {
+                        fullNames.emplace_back(
+                                    "sens." +
+                                    sd->getDeviceName() + "." +
+                                    name);
+                    }
+                }
+            }
+            //start logging thread is done in rtinit
+            //maybe add the default log
+            {
+                const auto loggingpath = getProperty<std::string>("RTLoggingDefaultLog").getValue();
+                if (!loggingpath.empty())
+                {
+                    defaultLogHandle = startRtLogging(loggingpath, getLoggingNames());
+                }
+            }
+            //setup thread (don't start it
+            rtLoggingTask = new RTLoggingTaskT([&] {doLogging();}, rtLoggingTimestep, false, getName() + "_RTLoggingTask");
+            rtLoggingTask->setDelayWarningTolerance(rtLoggingTimestep * 10);
+        }
+
+    }
+}
diff --git a/source/RobotAPI/components/units/RobotUnit/RobotUnitModules/RobotUnitModuleLogging.h b/source/RobotAPI/components/units/RobotUnit/RobotUnitModules/RobotUnitModuleLogging.h
new file mode 100644
index 0000000000000000000000000000000000000000..77bb2c0de4e6ec1c1707036997290b2f44eb128a
--- /dev/null
+++ b/source/RobotAPI/components/units/RobotUnit/RobotUnitModules/RobotUnitModuleLogging.h
@@ -0,0 +1,215 @@
+/*
+ * This file is part of ArmarX.
+ *
+ * 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    RobotAPI::ArmarXObjects::RobotUnit
+ * @author     Raphael Grimm ( raphael dot grimm at kit dot edu )
+ * @date       2018
+ * @copyright  http://www.gnu.org/licenses/gpl-2.0.txt
+ *             GNU General Public License
+ */
+
+#pragma once
+
+#include <atomic>
+#include <map>
+#include <vector>
+#include <fstream>
+
+#include <ArmarXCore/core/services/tasks/TaskUtil.h>
+
+#include <RobotAPI/interface/units/RobotUnit/RobotUnitInterface.h>
+
+#include "RobotUnitModuleBase.h"
+#include "../util/ControlThreadOutputBuffer.h"
+
+namespace armarx
+{
+    namespace RobotUnitModule
+    {
+        class LoggingPropertyDefinitions: public ModuleBasePropertyDefinitions
+        {
+        public:
+            LoggingPropertyDefinitions(std::string prefix): ModuleBasePropertyDefinitions(prefix)
+            {
+                defineOptionalProperty<std::size_t>(
+                    "RTLoggingPeriodMs", 10,
+                    "Period of the rt-logging thread in milliseconds. "
+                    "A high period can cause spikes in disk activity if data is logged to disk. "
+                    "A low period causes more computation overhead and memory consumption. "
+                    "Must not be 0.");
+
+                defineOptionalProperty<std::string>(
+                    "RTLoggingDefaultLog", "",
+                    "If rt logging is active and a file path is given, all data is logged to this file.");
+
+                defineOptionalProperty<std::size_t>(
+                    "RTLoggingMessageNumber", 1000,
+                    "Number of messages that can be logged in the control thread");
+                defineOptionalProperty<std::size_t>(
+                    "RTLoggingMessageBufferSize", 1024 * 1024,
+                    "Number of bytes that can be logged in the control thread");
+                defineOptionalProperty<std::size_t>(
+                    "RTLoggingMaxMessageNumber", 16000,
+                    "Max number of messages that can be logged in the control thread");
+                defineOptionalProperty<std::size_t>(
+                    "RTLoggingMaxMessageBufferSize", 16 * 1024 * 1024,
+                    "Max number of bytes that can be logged in the control thread");
+
+                defineOptionalProperty<std::size_t>(
+                    "RTLoggingKeepIterationsForMs", 60 * 1000,
+                    "All logging data (SensorValues, ControlTargets, Messages) is keept for this duration "
+                    "and can be dunped in case of an error.");
+            }
+        };
+
+        /**
+         * @brief This \ref ModuleBase "Module" manages logging of data.
+         *
+         * There are two types of data:
+         *    - Messages: These are logged via \ref ARMARX_RT_LOGF macros and printed to the corresponding ArmarX streams
+         *    - \ref SensorValueBase "SensorValues" / \ref ControlTargetBase "ControlTargets": These can be logged to CSV files
+         *
+         * @see ModuleBase
+         */
+        class Logging : virtual public ModuleBase, virtual public RobotUnitLoggingInterface
+        {
+            friend class ModuleBase;
+        public:
+            /**
+             * @brief Returns the singleton instance of this class
+             * @return The singleton instance of this class
+             */
+            static Logging& Instance()
+            {
+                return ModuleBase::Instance<Logging>();
+            }
+            // //////////////////////////////////////////////////////////////////////////////////////// //
+            // ///////////////////////////////// RobotUnitModule hooks //////////////////////////////// //
+            // //////////////////////////////////////////////////////////////////////////////////////// //
+        private:
+            /// @see ModuleBase::_postOnInitRobotUnit
+            void _postOnInitRobotUnit();
+            /// @see ModuleBase::_postFinishDeviceInitialization
+            void _postFinishDeviceInitialization();
+            /// @see ModuleBase::_preFinishControlThreadInitialization
+            void _preFinishControlThreadInitialization();
+            /// @see ModuleBase::_preFinishRunning
+            void _preFinishRunning();
+            // //////////////////////////////////////////////////////////////////////////////////////// //
+            // ///////////////////////////////////// ice interface //////////////////////////////////// //
+            // //////////////////////////////////////////////////////////////////////////////////////// //
+        public:
+            /**
+             * @brief Starts logging to a CSV file
+             * @param formatString The file to log to.
+             * @param loggingNames The data fields to log.
+             * @return A handle to the log. If it's last copy is deleted, logging is stopped.
+             */
+            RemoteReferenceCounterBasePtr startRtLogging(const std::string& formatString, const Ice::StringSeq& loggingNames, const Ice::Current& = GlobalIceCurrent) override;
+            /**
+             * @brief Starts logging to a CSV file
+             * @param formatString The file to log to.
+             * @param aliasNames Data fields to log. For an entry (key,value), the datafield key is logged and the table heading value is used.
+             * If value is empty, key is used as heading.
+             * @return A handle to the log. If it's last copy is deleted, logging is stopped.
+             */
+            RemoteReferenceCounterBasePtr startRtLoggingWithAliasNames(const std::string& formatString, const StringStringDictionary& aliasNames, const Ice::Current&   = GlobalIceCurrent) override;
+
+            /**
+             * @brief Stops logging to the given log.
+             * @param token The log to close.
+             */
+            void stopRtLogging(const armarx::RemoteReferenceCounterBasePtr& token, const Ice::Current& = GlobalIceCurrent) override;
+            /**
+             * @brief Adds a string to the log (it is added in a special column).
+             * @param token The log.
+             * @param marker The string to add.
+             */
+            void addMarkerToRtLog(const RemoteReferenceCounterBasePtr& token, const std::string& marker, const Ice::Current& = GlobalIceCurrent) override;
+
+            /**
+             * @brief Returns the names of all loggable data fields.
+             * @return The names of all loggable data fields.
+             */
+            Ice::StringSeq getLoggingNames(const Ice::Current& = GlobalIceCurrent) const override;
+            /**
+              * @brief Dumps the backlog of all recent iterations to the given file.
+              * This helps debugging.
+              * @param formatString The file.
+              */
+             void writeRecentIterationsToFile(const std::string& formatString, const Ice::Current& = GlobalIceCurrent) const override;
+
+            // //////////////////////////////////////////////////////////////////////////////////////// //
+            // //////////////////////////////////// implementation //////////////////////////////////// //
+            // //////////////////////////////////////////////////////////////////////////////////////// //
+        private:
+            /// @brief Executes the logging loop.
+            void doLogging();
+
+            // //////////////////////////////////////////////////////////////////////////////////////// //
+            // ///////////////////////////////////////// Data ///////////////////////////////////////// //
+            // //////////////////////////////////////////////////////////////////////////////////////// //
+        private:
+            using RTLoggingTaskT = SimplePeriodicTask<std::function<void(void)>>;
+
+            /// @brief Data structure holding information about an logging entry.
+            struct CSVLoggingEntry
+            {
+                /// @brief Whether logging should be stopped.
+                std::atomic_bool stopLogging {false};
+                /// @brief Bools whether a control device field should be logged.
+                std::vector<std::vector<std::vector<char>>> loggedControlDeviceValues;
+                /// @brief Bools whether a sensor device field should be logged.
+                std::vector<std::vector<char>> loggedSensorDeviceValues;
+                /// @brief The file stream for the csv file
+                std::ofstream stream;
+                /// @brief The file name
+                std::string filename;
+                /// @brief The marker to add in the next logging iteration. (protected by \ref rtLoggingMutex)
+                std::string marker;
+            };
+
+            /// @brief The thread executing the logging functions.
+            RTLoggingTaskT::pointer_type rtLoggingTask;
+            /// @brief All entries for logging.
+            std::map<std::string, std::shared_ptr<CSVLoggingEntry>> rtLoggingEntries;
+            /// @brief Handle for the default log. (This log can be enabled via a property and logs everything)
+            RemoteReferenceCounterBasePtr defaultLogHandle;
+            /// @brief The stored backlog (it is dumped when \ref writeRecentIterationsToFile is called)
+            std::deque< ::armarx::detail::ControlThreadOutputBufferEntry > backlog;
+            /// @brief The control threads unix thread id
+            Ice::Int controlThreadId {0};
+            /// @brief Mutex protecting the data structures of this class
+            mutable std::mutex rtLoggingMutex;
+            /// @brief Data field names for all \ref ControlTargetBase "ControlTargets"
+            std::vector<std::vector<std::vector<std::string>>> controlDeviceValueLoggingNames;
+            /// @brief Data field names for all \ref SensorValueBase "SensorValues"
+            std::vector<std::vector<            std::string >> sensorDeviceValueLoggingNames;
+
+            /// @brief The initial size of the Message entry buffer
+            std::size_t messageBufferSize{0};
+            /// @brief The initial number of Message entries
+            std::size_t messageBufferNumberEntries{0};
+            /// @brief The maximal size of the Message entry buffer
+            std::size_t messageBufferMaxSize{0};
+            /// @brief The maximal number of Message entries
+            std::size_t messageBufferMaxNumberEntries{0};
+            /// @brief The logging thread's period
+            std::size_t rtLoggingTimestep {0};
+            /// @brief The time an entry shold remain in the backlog.
+            IceUtil::Time rtLoggingBacklogRetentionTime;
+        };
+    }
+}
diff --git a/source/RobotAPI/components/units/RobotUnit/RobotUnitModules/RobotUnitModuleManagement.cpp b/source/RobotAPI/components/units/RobotUnit/RobotUnitModules/RobotUnitModuleManagement.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..b532f3f47922c50eb2ac75ad30ac8a6d81c554e5
--- /dev/null
+++ b/source/RobotAPI/components/units/RobotUnit/RobotUnitModules/RobotUnitModuleManagement.cpp
@@ -0,0 +1,37 @@
+/*
+ * This file is part of ArmarX.
+ *
+ * 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    RobotAPI::ArmarXObjects::RobotUnit
+ * @author     Raphael Grimm ( raphael dot grimm at kit dot edu )
+ * @date       2018
+ * @copyright  http://www.gnu.org/licenses/gpl-2.0.txt
+ *             GNU General Public License
+ */
+
+#include <ArmarXCore/core/ArmarXManager.h>
+
+#include "RobotUnitModuleManagement.h"
+
+namespace armarx
+{
+    namespace RobotUnitModule
+    {
+        void Management::_preOnInitRobotUnit()
+        {
+            additionalObjectSchedulerCount = getProperty<std::uint64_t>("AdditionalObjectSchedulerCount").getValue();
+            getArmarXManager()->increaseSchedulers(static_cast<int>(additionalObjectSchedulerCount));
+        }
+    }
+}
diff --git a/source/RobotAPI/components/units/RobotUnit/RobotUnitModules/RobotUnitModuleManagement.h b/source/RobotAPI/components/units/RobotUnit/RobotUnitModules/RobotUnitModuleManagement.h
new file mode 100644
index 0000000000000000000000000000000000000000..377e3889b5b86a9d17075674e544918776cb3757
--- /dev/null
+++ b/source/RobotAPI/components/units/RobotUnit/RobotUnitModules/RobotUnitModuleManagement.h
@@ -0,0 +1,87 @@
+/*
+ * This file is part of ArmarX.
+ *
+ * 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    RobotAPI::ArmarXObjects::RobotUnit
+ * @author     Raphael Grimm ( raphael dot grimm at kit dot edu )
+ * @date       2018
+ * @copyright  http://www.gnu.org/licenses/gpl-2.0.txt
+ *             GNU General Public License
+ */
+
+#pragma once
+
+#include "RobotUnitModuleBase.h"
+
+namespace armarx
+{
+    namespace RobotUnitModule
+    {
+
+        class ManagementPropertyDefinitions: public ModuleBasePropertyDefinitions
+        {
+        public:
+            ManagementPropertyDefinitions(std::string prefix): ModuleBasePropertyDefinitions(prefix)
+            {
+                defineOptionalProperty<std::uint64_t>(
+                    "AdditionalObjectSchedulerCount", 10,
+                    "Number of ObjectSchedulers to be added");
+            }
+        };
+
+        /**
+         * @brief This \ref ModuleBase "Module" handles some general management tasks.
+         * It implements the \ref RobotUnitManagementInterface.
+         *
+         * @see ModuleBase
+         */
+        class Management : virtual public ModuleBase, virtual public RobotUnitManagementInterface
+        {
+            friend class ModuleBase;
+        public:
+            /**
+             * @brief Returns the singleton instance of this class
+             * @return The singleton instance of this class
+             */
+            static Management& Instance()
+            {
+                return ModuleBase::Instance<Management>();
+            }
+            // //////////////////////////////////////////////////////////////////////////////////////// //
+            // ///////////////////////////////// RobotUnitModule hooks //////////////////////////////// //
+            // //////////////////////////////////////////////////////////////////////////////////////// //
+        private:
+            /// @see ModuleBase::_preOnInitRobotUnit
+            void _preOnInitRobotUnit();
+            // //////////////////////////////////////////////////////////////////////////////////////// //
+            // ///////////////////////////////////// ice interface //////////////////////////////////// //
+            // //////////////////////////////////////////////////////////////////////////////////////// //
+        public:
+            /**
+             * @brief Returns whether the RobotUnit is running.
+             * @return Whether the RobotUnit is running.
+             */
+            bool isRunning(const Ice::Current& = GlobalIceCurrent) const override
+            {
+                return getRobotUnitState() == RobotUnitState::Running;
+            }
+            // //////////////////////////////////////////////////////////////////////////////////////// //
+            // ///////////////////////////////////////// Data ///////////////////////////////////////// //
+            // //////////////////////////////////////////////////////////////////////////////////////// //
+        private:
+            /// @brief The number of additional object schedulers
+            std::uint64_t additionalObjectSchedulerCount{0};
+        };
+    }
+}
diff --git a/source/RobotAPI/components/units/RobotUnit/RobotUnitModules/RobotUnitModulePublisher.cpp b/source/RobotAPI/components/units/RobotUnit/RobotUnitModules/RobotUnitModulePublisher.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..36ad04b621caeb6c9d3254530ea06073014218cd
--- /dev/null
+++ b/source/RobotAPI/components/units/RobotUnit/RobotUnitModules/RobotUnitModulePublisher.cpp
@@ -0,0 +1,507 @@
+/*
+ * This file is part of ArmarX.
+ *
+ * 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    RobotAPI::ArmarXObjects::RobotUnit
+ * @author     Raphael Grimm ( raphael dot grimm at kit dot edu )
+ * @date       2018
+ * @copyright  http://www.gnu.org/licenses/gpl-2.0.txt
+ *             GNU General Public License
+ */
+
+#include "RobotUnitModulePublisher.h"
+
+#include "../NJointControllers/NJointController.h"
+#include "../Units/RobotUnitSubUnit.h"
+
+namespace armarx
+{
+    namespace RobotUnitModule
+    {
+        namespace detail
+        {
+            std::function<std::string(const std::string&)> makeDebugObserverNameFixer(const std::string& prefix)
+            {
+                return
+                    [prefix](const std::string & name)
+                {
+                    std::string s = prefix + name;
+                    std::replace(s.begin(), s.end(), '.', '_');
+                    std::replace(s.begin(), s.end(), ':', '_');
+                    return s;
+                };
+            }
+        }
+
+        /**
+         * \brief This class allows minimal access to private members of \ref NJointController in a sane fashion for \ref Publisher.
+         * \warning !! DO NOT ADD ANYTHING IF YOU DO NOT KNOW WAHT YOU ARE DOING! IF YOU DO SOMETHING WRONG YOU WILL CAUSE UNDEFINED BEHAVIOUR !!
+         */
+        class NJointControllerAttorneyForPublisher
+        {
+            friend class Publisher;
+            static bool GetStatusReportedActive(const NJointControllerPtr& nJointCtrl)
+            {
+                return nJointCtrl->statusReportedActive;
+            }
+            static bool GetStatusReportedRequested(const NJointControllerPtr& nJointCtrl)
+            {
+                return nJointCtrl->statusReportedRequested;
+            }
+            static void UpdateStatusReported(const NJointControllerPtr& nJointCtrl)
+            {
+                nJointCtrl->statusReportedActive = nJointCtrl->isActive.load();
+                nJointCtrl->statusReportedRequested = nJointCtrl->isRequested.load();
+            }
+            static void Publish(
+                const NJointControllerPtr& nJointCtrl,
+                const SensorAndControl& sac,
+                const DebugDrawerInterfacePrx& draw,
+                const DebugObserverInterfacePrx& observer
+            )
+            {
+                nJointCtrl ->publish(sac, draw, observer);
+            }
+            static void DeactivatePublishing(
+                const NJointControllerPtr& nJointCtrl,
+                const DebugDrawerInterfacePrx& draw,
+                const DebugObserverInterfacePrx& observer
+            )
+            {
+                nJointCtrl->deactivatePublish(draw, observer);
+            }
+        };
+        /**
+         * \brief This class allows minimal access to private members of \ref Devices in a sane fashion for \ref Publisher.
+         * \warning !! DO NOT ADD ANYTHING IF YOU DO NOT KNOW WAHT YOU ARE DOING! IF YOU DO SOMETHING WRONG YOU WILL CAUSE UNDEFINED BEHAVIOUR !!
+         */
+        class DevicesAttorneyForPublisher
+        {
+            friend class Publisher;
+            static const std::string& GetSensorDeviceName(Publisher* p, std::size_t idx)
+            {
+                return p->_module<Devices>().sensorDevices.at(idx)->getDeviceName();
+            }
+        };
+        /**
+         * \brief This class allows minimal access to private members of \ref Units in a sane fashion for \ref Publisher.
+         * \warning !! DO NOT ADD ANYTHING IF YOU DO NOT KNOW WAHT YOU ARE DOING! IF YOU DO SOMETHING WRONG YOU WILL CAUSE UNDEFINED BEHAVIOUR !!
+         */
+        class UnitsAttorneyForPublisher
+        {
+            friend class Publisher;
+            static const std::vector<RobotUnitSubUnitPtr>& GetSubUnits(Publisher* p)
+            {
+                return p->_module<Units>().subUnits;
+            }
+        };
+        /**
+         * \brief This class allows minimal access to private members of \ref ControllerManagement in a sane fashion for \ref Publisher.
+         * \warning !! DO NOT ADD ANYTHING IF YOU DO NOT KNOW WAHT YOU ARE DOING! IF YOU DO SOMETHING WRONG YOU WILL CAUSE UNDEFINED BEHAVIOUR !!
+         */
+        class ControllerManagementAttorneyForPublisher
+        {
+            friend class Publisher;
+            static const std::map<std::string, NJointControllerPtr>& GetNJointControllers(Publisher* p)
+            {
+                return p->_module<ControllerManagement>().nJointControllers;
+            }
+            static void RemoveNJointControllersToBeDeleted(Publisher* p, bool blocking, RobotUnitListenerPrx l)
+            {
+                p->_module<ControllerManagement>().removeNJointControllersToBeDeleted(blocking, l);
+            }
+        };
+    }
+}
+
+
+namespace armarx
+{
+    namespace RobotUnitModule
+    {
+        const std::map<std::string, NJointControllerPtr> &Publisher::getNJointControllers()
+        {
+            return ControllerManagementAttorneyForPublisher::GetNJointControllers(this);
+        }
+
+        std::string Publisher::getRobotUnitListenerTopicName(const Ice::Current &) const
+        {
+            return robotUnitListenerTopicName;
+        }
+
+        std::string Publisher::getDebugDrawerTopicName(const Ice::Current &) const
+        {
+            return debugDrawerUpdatesTopicName;
+        }
+
+        std::string Publisher::getDebugObserverTopicName(const Ice::Current &) const
+        {
+            return debugObserverTopicName;
+        }
+
+        RobotUnitListenerPrx Publisher::getRobotUnitListenerProxy(const Ice::Current&) const
+        {
+            ARMARX_CHECK_EXPRESSION(robotUnitListenerPrx);
+            return robotUnitListenerPrx;
+        }
+
+        DebugObserverInterfacePrx Publisher::getDebugObserverProxy(const Ice::Current&) const
+        {
+            ARMARX_CHECK_EXPRESSION(debugObserverPrx);
+            return debugObserverPrx;
+        }
+
+        DebugDrawerInterfacePrx Publisher::getDebugDrawerProxy(const Ice::Current&) const
+        {
+            ARMARX_CHECK_EXPRESSION(debugDrawerPrx);
+            return debugDrawerPrx;
+        }
+
+        void Publisher::_preOnConnectRobotUnit()
+        {
+            robotUnitListenerPrx = getTopic<RobotUnitListenerPrx>(getRobotUnitListenerTopicName());
+            debugDrawerPrx = getTopic<DebugDrawerInterfacePrx>(getDebugDrawerTopicName());
+            debugObserverPrx = getTopic<DebugObserverInterfacePrx>(getDebugObserverTopicName());
+        }
+
+        void Publisher::_preOnInitRobotUnit()
+        {
+            robotUnitListenerTopicName = getProperty<std::string>("RobotUnitListenerTopicName").getValue();
+            debugDrawerUpdatesTopicName = getProperty<std::string>("DebugDrawerUpdatesTopicName").getValue();
+            debugObserverTopicName = getProperty<std::string>("DebugObserverTopicName").getValue();
+
+            observerPublishSensorValues = getProperty<bool>("ObserverPublishSensorValues").getValue();
+            observerPublishControlTargets = getProperty<bool>("ObserverPublishControlTargets").getValue();
+            debugObserverSkipIterations = std::max(1ul, getProperty<std::uint64_t>("ObserverPrintEveryNthIterations").getValue());
+
+            publishPeriodMs = std::max(1ul, getProperty<std::size_t>("PublishPeriodMs").getValue());
+
+            offeringTopic(getRobotUnitListenerTopicName());
+            offeringTopic(getDebugDrawerTopicName());
+            offeringTopic(getDebugObserverTopicName());
+            getArmarXManager()->addObject(robotUnitObserver);
+        }
+
+        void Publisher::_icePropertiesInitialized()
+        {
+            robotUnitObserver = Component::create<RobotUnitObserver, RobotUnitObserverPtr>(getIceProperties(), "", getConfigDomain());
+            addPropertyUser(PropertyUserPtr::dynamicCast(robotUnitObserver));
+        }
+
+        void Publisher::_icePropertiesUpdated(const std::set<std::string> &changedProperties)
+        {
+            if (changedProperties.count("ObserverPublishSensorValues"))
+            {
+                observerPublishSensorValues = getProperty<bool>("ObserverPublishSensorValues").getValue();
+            }
+            if (changedProperties.count("ObserverPublishControlTargets"))
+            {
+                observerPublishControlTargets = getProperty<bool>("ObserverPublishControlTargets").getValue();
+            }
+            if (changedProperties.count("ObserverPrintEveryNthIterations"))
+            {
+                debugObserverSkipIterations = getProperty<std::uint64_t>("ObserverPrintEveryNthIterations").getValue();
+            }
+        }
+
+        void Publisher::_preFinishRunning()
+        {
+            if (publisherTask)
+            {
+                ARMARX_DEBUG << "shutting down publisher task";
+                publisherTask->stop();
+                std::this_thread::sleep_for(std::chrono::milliseconds {10});
+                while (publisherTask->isFunctionExecuting() || publisherTask->isRunning())
+                {
+                    ARMARX_FATAL << deactivateSpam(0.1) << "PUBLISHER TASK IS RUNNING AFTER IT WAS STOPPED!";
+                }
+                publisherTask = nullptr;
+                //since the drawer queues draw events and we want to clear the layers, we have to sleep here
+                std::this_thread::sleep_for(std::chrono::milliseconds {100});
+                ARMARX_DEBUG << "shutting down publisher task done";
+            }
+            for (const auto& pair : getNJointControllers())
+            {
+                ARMARX_DEBUG << "forcing deactivation of publishing for " << pair.first;
+                NJointControllerAttorneyForPublisher::DeactivatePublishing(pair.second, debugDrawerPrx, debugObserverPrx);
+            }
+        }
+
+        void Publisher::_postFinishControlThreadInitialization()
+        {
+            //start publisher
+            publishNewSensorDataTime = TimeUtil::GetTime();
+            publisherTask = new PublisherTaskT([&] {publish({});}, publishPeriodMs, false, getName() + "_PublisherTask");
+            ARMARX_INFO << "starting publisher with timestep " << publishPeriodMs;
+            publisherTask->setDelayWarningTolerance(10 * publishPeriodMs);
+            publisherTask->start();
+        }
+
+        void Publisher::publish(StringVariantBaseMap additionalMap, StringVariantBaseMap timingMap)
+        {
+            auto begPublish = Now();
+            static const int spamdelay = 30;
+
+            if (getRobotUnitState() != RobotUnitState::Running)
+            {
+                ARMARX_DEBUG << deactivateSpam(spamdelay) << "skipping publishing in state " << getRobotUnitState();
+                return;
+            }
+            if(isShuttingDown())
+            {
+                return;
+            }
+            GuardType guard;
+            try
+            {
+                guard = getGuard();
+            }
+            catch(...)
+            {
+                //shutting down
+                return;
+            }
+            throwIfStateIsNot(RobotUnitState::Running, __FUNCTION__);
+
+            //get batch proxies
+            auto debugObserverBatchPrx = debugObserverPrx->ice_batchOneway();
+            auto listenerBatchPrx = getRobotUnitListenerProxy()->ice_batchOneway();
+            //delete NJoint queued for deletion
+            ControllerManagementAttorneyForPublisher::RemoveNJointControllersToBeDeleted(this, false, listenerBatchPrx);
+            //swap buffers in
+            const bool haveActivatedControllersChanged = _module<ControlThreadDataBuffer>().activatedControllersChanged();
+            const bool haveSensorAndControlValsChanged = _module<ControlThreadDataBuffer>().sensorAndControlBufferChanged();
+            //setup datastructures
+            const auto& controlThreadOutputBuffer =  _module<ControlThreadDataBuffer>().getSensorAndControlBuffer();
+            const auto& activatedControllers   = _module<ControlThreadDataBuffer>().getActivatedControllers();
+            const auto& requestedJointControllers   = _module<ControlThreadDataBuffer>().getRequestedJointControllers();
+
+            const auto timestamp = controlThreadOutputBuffer.sensorValuesTimestamp;
+
+            const auto numSensorDevices  = _module<Devices>().getNumberOfSensorDevices();
+            const auto numControlDevices = _module<Devices>().getNumberOfControlDevices();
+
+            const bool publishToObserver = !(publishIterationCount % debugObserverSkipIterations);
+            const bool debugObserverPublishControlTargetsThisIteration = observerPublishControlTargets;
+            const bool debugObserverPublishSensorValuesThisIteration = observerPublishSensorValues;
+            StringVariantBaseMap ctrlDevMap, sensorDevMap;
+            //publish publishing meta state
+            additionalMap["haveActivatedControllersChanged"] = new TimedVariant {haveActivatedControllersChanged, timestamp};
+            additionalMap["haveSensorAndControlValsChanged"] = new TimedVariant {haveSensorAndControlValsChanged, timestamp};
+            additionalMap["publishToObserver"              ] = new TimedVariant {publishToObserver, timestamp};
+            //update
+            if (haveSensorAndControlValsChanged)
+            {
+                //update units
+                timingMap["publishTimings_UnitUpdate"] = new TimedVariant
+                {
+                    ARMARX_STOPWATCH(TimestampVariant)
+                    {
+                        ARMARX_DEBUG << deactivateSpam(spamdelay) << "updating units with new sensor values";
+                        publishNewSensorDataTime = TimeUtil::GetTime();
+                        for (const RobotUnitSubUnitPtr& rsu : UnitsAttorneyForPublisher::GetSubUnits(this))
+                        {
+                            if (rsu && rsu->getObjectScheduler() && rsu->getProxy())
+                            {
+                                timingMap["publishTimings_UnitUpdate_" + rsu->getName()] = new TimedVariant
+                                {
+                                    ARMARX_STOPWATCH(TimestampVariant){rsu->update(controlThreadOutputBuffer, activatedControllers);},
+                                    timestamp
+                                };
+                            }
+                        }
+                    },
+                    timestamp
+                };
+                //publish sensor updates
+
+                timingMap["publishTimings_SensorUpdates"] = new TimedVariant
+                {
+                    ARMARX_STOPWATCH(TimestampVariant)
+                    {
+                        for (std::size_t sensidx = 0 ; sensidx < numSensorDevices; ++sensidx)
+                        {
+                            const SensorValueBase& sensVal = *(controlThreadOutputBuffer.sensors.at(sensidx));
+                            auto variants = sensVal.toVariants(timestamp);
+
+                            if (!variants.empty())
+                            {
+                                SensorDeviceStatus status;
+                                status.deviceName = DevicesAttorneyForPublisher::GetSensorDeviceName(this, sensidx);
+                                status.sensorValue = std::move(variants);
+                                status.timestampUSec = MicroNow().count();
+                                if (debugObserverPublishSensorValuesThisIteration && publishToObserver)
+                                {
+                                    transformMapKeys(
+                                        variants, sensorDevMap,
+                                        detail::makeDebugObserverNameFixer(status.deviceName + "_" + sensVal.getSensorValueType(true) + "_")
+                                    );
+                                }
+                                listenerBatchPrx->sensorDeviceStatusChanged(status);
+                            }
+                        }
+                    },
+                    timestamp
+                };
+            }
+            else
+            {
+                const double sensSecondsAgo = (TimeUtil::GetTime() - publishNewSensorDataTime).toSecondsDouble();
+                if (sensSecondsAgo > 1)
+                {
+                    ARMARX_WARNING << deactivateSpam(spamdelay) << "armarx::RobotUnit::publish: Last sensor value update is "
+                                   << sensSecondsAgo << " seconds ago!";
+                }
+            }
+            if (haveSensorAndControlValsChanged || haveActivatedControllersChanged)
+            {
+                timingMap["publishTimings_ControlUpdates"] = new TimedVariant
+                {
+                    ARMARX_STOPWATCH(TimestampVariant)
+                    {
+                        for (std::size_t ctrlidx = 0 ; ctrlidx < numControlDevices; ++ctrlidx)
+                        {
+                            const ControlDevice& ctrlDev = *(_module<Devices>().getControlDevices().at(ctrlidx));
+
+                            StringToStringVariantBaseMapMap variants;
+                            for (const auto& ctrlVal : controlThreadOutputBuffer.control.at(ctrlidx))
+                            {
+                                const auto& controlMode = ctrlVal->getControlMode();
+                                variants[controlMode] = ctrlVal->toVariants(timestamp);
+                                if (
+                                    haveSensorAndControlValsChanged &&
+                                    !variants[controlMode].empty() &&
+                                    debugObserverPublishControlTargetsThisIteration  &&
+                                    publishToObserver
+                                )
+                                {
+                                    transformMapKeys(
+                                        variants[controlMode], ctrlDevMap,
+                                        detail::makeDebugObserverNameFixer(ctrlDev.getDeviceName() + "_" + controlMode + "_")
+                                    );
+                                }
+                            }
+                            ControlDeviceStatus status;
+                            const auto activeJointCtrl = activatedControllers.jointControllers.at(ctrlidx);
+                            status.activeControlMode = activeJointCtrl ? activeJointCtrl->getControlMode() : std::string {"!!JointController is nullptr!!"};
+                            status.deviceName = ctrlDev.getDeviceName();
+                            ARMARX_CHECK_EXPRESSION(requestedJointControllers.at(ctrlidx));
+                            status.requestedControlMode = requestedJointControllers.at(ctrlidx)->getControlMode();
+                            status.controlTargetValues = std::move(variants);
+                            status.timestampUSec = MicroNow().count();
+                            listenerBatchPrx->controlDeviceStatusChanged(status);
+                        }
+                    },
+                    timestamp
+                };
+            }
+            //call publish hook + publish NJointController changes
+            timingMap["publishTimings_NJointControllerUpdates"] = new TimedVariant
+            {
+                ARMARX_STOPWATCH(TimestampVariant)
+                {
+                    for (const auto& pair : getNJointControllers())
+                    {
+                        const NJointControllerPtr& nJointCtrl = pair.second;
+                        timingMap["publishTimings_NJointControllerUpdates_" + nJointCtrl->getInstanceName()] = new TimedVariant
+                        {
+                            ARMARX_STOPWATCH(TimestampVariant)
+                            {
+                                //run some hook for active (used for visu)
+                                NJointControllerAttorneyForPublisher::Publish(nJointCtrl, controlThreadOutputBuffer, debugDrawerPrx, debugObserverBatchPrx);
+                                if (
+                                    NJointControllerAttorneyForPublisher::GetStatusReportedActive(nJointCtrl) != nJointCtrl->isControllerActive() ||
+                                    NJointControllerAttorneyForPublisher::GetStatusReportedRequested(nJointCtrl) != nJointCtrl->isControllerRequested()
+                                )
+                                {
+                                    NJointControllerAttorneyForPublisher::UpdateStatusReported(nJointCtrl);
+                                    listenerBatchPrx->nJointControllerStatusChanged(nJointCtrl->getControllerStatus());
+                                }
+                            },
+                            timestamp
+                        };
+                    }
+                },
+                timestamp
+            };
+
+            //report new class names
+            timingMap["publishTimings_ClassNameUpdates"] = new TimedVariant
+            {
+                ARMARX_STOPWATCH(TimestampVariant)
+                {
+                    const auto classNames = NJointControllerRegistry::getKeys();
+                    if (lastReportedClasses.size() != classNames.size())
+                    {
+                        for (const auto& name : classNames)
+                        {
+                            if (!lastReportedClasses.count(name))
+                            {
+                                listenerBatchPrx->nJointControllerClassAdded(name);
+                                lastReportedClasses.emplace(name);
+                            }
+                        }
+                    }
+                },
+                timestamp
+            };
+            timingMap["publishTimings_RobotUnitListenerFlush"] = new TimedVariant
+            {
+                ARMARX_STOPWATCH(TimestampVariant){listenerBatchPrx->ice_flushBatchRequests();}, timestamp
+            };
+
+            if (publishToObserver)
+            {
+                timingMap["publishTimings_LastRobotUnitObserverFlush"] =
+                    new TimedVariant {TimestampVariant{lastRobotUnitObserverFlush.count()}, timestamp};
+                timingMap["publishTimings_LastPublishLoop"] = new TimedVariant {TimestampVariant{lastPublishLoop.count()}, timestamp};
+                lastRobotUnitObserverFlush = ARMARX_STOPWATCH()
+                {
+                    if (robotUnitObserver->getState() >= eManagedIceObjectStarted)
+                    {
+                        robotUnitObserver->offerOrUpdateDataFieldsFlatCopy(robotUnitObserver->additionalChannel, additionalMap);
+                        robotUnitObserver->updateChannel(robotUnitObserver->additionalChannel);
+                        robotUnitObserver->offerOrUpdateDataFieldsFlatCopy(robotUnitObserver->timingChannel, timingMap);
+                        robotUnitObserver->updateChannel(robotUnitObserver->timingChannel);
+                        robotUnitObserver->offerOrUpdateDataFieldsFlatCopy(robotUnitObserver->controlDevicesChannel, ctrlDevMap);
+                        robotUnitObserver->updateChannel(robotUnitObserver->controlDevicesChannel);
+                        robotUnitObserver->offerOrUpdateDataFieldsFlatCopy(robotUnitObserver->sensorDevicesChannel, sensorDevMap);
+                        robotUnitObserver->updateChannel(robotUnitObserver->sensorDevicesChannel);
+
+                    }
+                    debugObserverBatchPrx->ice_flushBatchRequests();
+                };
+            }
+            else
+            {
+                lastRobotUnitObserverFlush = std::chrono::microseconds {0};
+            }
+
+            //warn if there are unset jointCtrl controllers
+            {
+                const auto& jointCtrls = _module<ControlThreadDataBuffer>().getActivatedJointControllers();
+                if (std::any_of(jointCtrls.begin(), jointCtrls.end(), [](const JointController * jointCtrl)
+            {
+                return !jointCtrl;
+            }))
+                {
+                    ARMARX_WARNING << "armarx::RobotUnit::publish: Some activated JointControllers are reported to be nullptr! "
+                                   << "(did you forget to call rtSwitchControllerSetup()?)";
+                }
+            }
+            ++publishIterationCount;
+            lastPublishLoop = MicroToNow(begPublish);
+        }
+    }
+}
diff --git a/source/RobotAPI/components/units/RobotUnit/RobotUnitModules/RobotUnitModulePublisher.h b/source/RobotAPI/components/units/RobotUnit/RobotUnitModules/RobotUnitModulePublisher.h
new file mode 100644
index 0000000000000000000000000000000000000000..21cb1a18a5a794de8139bda0ffb72d4d50de62e6
--- /dev/null
+++ b/source/RobotAPI/components/units/RobotUnit/RobotUnitModules/RobotUnitModulePublisher.h
@@ -0,0 +1,216 @@
+/*
+ * This file is part of ArmarX.
+ *
+ * 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    RobotAPI::ArmarXObjects::RobotUnit
+ * @author     Raphael Grimm ( raphael dot grimm 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/services/tasks/TaskUtil.h>
+#include <ArmarXCore/observers/DebugObserver.h>
+
+#include <RobotAPI/interface/units/RobotUnit/RobotUnitInterface.h>
+#include <RobotAPI/interface/visualization/DebugDrawerInterface.h>
+
+#include "RobotUnitModuleBase.h"
+#include "../RobotUnitObserver.h"
+
+namespace armarx
+{
+    TYPEDEF_PTRS_HANDLE(RobotUnitObserver);
+    namespace RobotUnitModule
+    {
+        class PublisherPropertyDefinitions: public ModuleBasePropertyDefinitions
+        {
+        public:
+            PublisherPropertyDefinitions(std::string prefix): ModuleBasePropertyDefinitions(prefix)
+            {
+                defineOptionalProperty<std::string>(
+                    "RobotUnitListenerTopicName", "RobotUnitListenerTopic",
+                    "The topic receiving events for RobotUnitListener");
+                defineOptionalProperty<std::string>(
+                    "DebugDrawerUpdatesTopicName", "DebugDrawerUpdates",
+                    "The topic receiving events for debug drawing");
+                defineOptionalProperty<std::size_t>(
+                    "PublishPeriodMs", 10,
+                    "Milliseconds between each publish");
+
+                defineOptionalProperty<bool>(
+                    "ObserverPublishSensorValues", true,
+                    "Whether sensor values are send to the observer", PropertyDefinitionBase::eModifiable);
+                defineOptionalProperty<bool>(
+                    "ObserverPublishControlTargets", true,
+                    "Whether control targets are send to the observer", PropertyDefinitionBase::eModifiable);
+                defineOptionalProperty<std::string>(
+                    "DebugObserverTopicName", "DebugObserver", "The topic where updates are send to");
+                defineOptionalProperty<std::uint64_t>(
+                    "ObserverPrintEveryNthIterations", 1,
+                    "Only every nth iteration data is send to the debug observer", PropertyDefinitionBase::eModifiable);
+            }
+        };
+
+        /**
+         * @brief This \ref ModuleBase "Module" manages publishing of all data to Topics,
+         * updating of all units managed by \ref Units "the Units module" and calling of \ref NJointController hooks.
+         *
+         * @see ModuleBase
+         */
+        class Publisher : virtual public ModuleBase, virtual public RobotUnitPublishingInterface
+        {
+            friend class ModuleBase;
+        public:
+            /**
+             * @brief Returns the singleton instance of this class
+             * @return The singleton instance of this class
+             */
+            static Publisher& Instance()
+            {
+                return ModuleBase::Instance<Publisher>();
+            }
+            // //////////////////////////////////////////////////////////////////////////////////////// //
+            // ///////////////////////////////// RobotUnitModule hooks //////////////////////////////// //
+            // //////////////////////////////////////////////////////////////////////////////////////// //
+        private:
+            /// @see ModuleBase::_icePropertiesInitialized
+            void _icePropertiesInitialized();
+            /// @see ModuleBase::_icePropertiesUpdated
+            void _icePropertiesUpdated(const std::set<std::string>& changedProperties);
+
+            /// @see ModuleBase::_preOnInitRobotUnit
+            void _preOnInitRobotUnit();
+            /// @see ModuleBase::_preOnConnectRobotUnit
+            void _preOnConnectRobotUnit();
+            /// @see ModuleBase::_postFinishControlThreadInitialization
+            void _postFinishControlThreadInitialization();
+            /// @see ModuleBase::_preFinishRunning
+            void _preFinishRunning();
+            // //////////////////////////////////////////////////////////////////////////////////////// //
+            // ///////////////////////////////////// ice interface //////////////////////////////////// //
+            // //////////////////////////////////////////////////////////////////////////////////////// //
+        public:
+            /**
+             * @brief Returns the name of the used DebugDrawerTopic
+             * @return The name of the used DebugDrawerTopic
+             */
+            std::string getDebugDrawerTopicName(const Ice::Current& = GlobalIceCurrent) const override;
+            /**
+             * @brief Returns the name of the used DebugObserverTopic
+             * @return The name of the used DebugObserverTopic
+             */
+            std::string getDebugObserverTopicName(const Ice::Current& = GlobalIceCurrent) const override;
+            /**
+             * @brief Returns the name of the used RobotUnitListenerTopic
+             * @return The name of the used RobotUnitListenerTopic
+             */
+            std::string getRobotUnitListenerTopicName(const Ice::Current& = GlobalIceCurrent) const override;
+
+            /**
+             * @brief Returns the used DebugDrawerProxy
+             * @return The used DebugDrawerProxy
+             */
+            DebugDrawerInterfacePrx getDebugDrawerProxy(const Ice::Current& = GlobalIceCurrent) const override;
+            /**
+             * @brief Returns the used RobotUnitListenerProxy
+             * @return The used RobotUnitListenerProxy
+             */
+            RobotUnitListenerPrx getRobotUnitListenerProxy(const Ice::Current& = GlobalIceCurrent) const override;
+            /**
+             * @brief Returns the used DebugObserverProxy
+             * @return The used DebugObserverProxy
+             */
+            DebugObserverInterfacePrx getDebugObserverProxy(const Ice::Current& = GlobalIceCurrent) const override;
+            // //////////////////////////////////////////////////////////////////////////////////////// //
+            // /////////////////////////////////// Module interface /////////////////////////////////// //
+            // //////////////////////////////////////////////////////////////////////////////////////// //
+        protected:
+            /**
+             * @brief Publishes data
+             * @param additionalMap Data published to the RobotUnitObserver's additional channel (This field is used by deriving classes)
+             * @param timingMap Data published to the RobotUnitObserver's timing channel (This field is used by deriving classes)
+             */
+            virtual void publish(StringVariantBaseMap additionalMap = {}, StringVariantBaseMap timingMap = {});
+            // //////////////////////////////////////////////////////////////////////////////////////// //
+            // //////////////////////////////////// implementation //////////////////////////////////// //
+            // //////////////////////////////////////////////////////////////////////////////////////// //
+        private:
+            /**
+             * @brief Returns a map containing all current NJointControllers.
+             * @return A map containing all current NJointControllers.
+             */
+            const std::map<std::string, NJointControllerPtr>& getNJointControllers();
+            /**
+             * @brief Returns the used RobotUnitObserver
+             * @return The used RobotUnitObserver
+             */
+            const RobotUnitObserverPtr& getRobotUnitObserver() const
+            {
+                ARMARX_CHECK_EXPRESSION(robotUnitObserver);
+                return robotUnitObserver;
+            }
+            // //////////////////////////////////////////////////////////////////////////////////////// //
+            // ///////////////////////////////////////// Data ///////////////////////////////////////// //
+            // //////////////////////////////////////////////////////////////////////////////////////// //
+        private:
+            using PublisherTaskT = SimplePeriodicTask<std::function<void(void)>>;
+
+            /// @brief The name of the used RobotUnitListenerTopic
+            std::string robotUnitListenerTopicName;
+            /// @brief The name of the used DebugDrawerTopic
+            std::string debugDrawerUpdatesTopicName;
+            /// @brief The name of the used DebugObserverTopic
+            std::string debugObserverTopicName;
+
+            /// @brief The used DebugDrawerProxy
+            DebugDrawerInterfacePrx debugDrawerPrx;
+            /// @brief The used DebugObserverProxy
+            DebugObserverInterfacePrx debugObserverPrx;
+
+            /// @brief the number of calles to \ref publish
+            std::uint64_t publishIterationCount {0};
+
+            /// @brief The time required by the last iteration of \ref publish to publish sensor data
+            IceUtil::Time publishNewSensorDataTime;
+            /// @brief The thread executing the publisher loop
+            PublisherTaskT::pointer_type publisherTask; ///TODO use std thread
+            /// @brief The already reported classes of \ref NJointController "NJointControllers"
+            std::set<std::string> lastReportedClasses;
+
+            /// @brief Whether \ref SensorValueBase "SensorValues" should be published to the observers
+            std::atomic_bool observerPublishSensorValues;
+            /// @brief Whether \ref ControlTargetBase "ControlTargets" should be published to the observers
+            std::atomic_bool observerPublishControlTargets;
+            /// @brief How many iterations of \ref publish shold not publish data to the debug observer.
+            std::atomic<std::uint64_t> debugObserverSkipIterations;
+
+            /// @brief The time required by the last iteration of \ref publish to flush the debug observer
+            std::chrono::microseconds lastRobotUnitObserverFlush;
+            /// @brief The time required by the last iteration of \ref publish
+            std::chrono::microseconds lastPublishLoop;
+
+            /// @brief The used RobotUnitObserver
+            RobotUnitObserverPtr robotUnitObserver;
+
+            /// @brief The period of the publisher loop
+            std::size_t publishPeriodMs{1};
+
+            /// @brief A proxy to the used RobotUnitListener topic
+            RobotUnitListenerPrx robotUnitListenerPrx;
+        };
+    }
+}
diff --git a/source/RobotAPI/components/units/RobotUnit/RobotUnitModules/RobotUnitModuleRobotData.cpp b/source/RobotAPI/components/units/RobotUnit/RobotUnitModules/RobotUnitModuleRobotData.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..12a389a88f1492772b1e124f3a896d37576391ec
--- /dev/null
+++ b/source/RobotAPI/components/units/RobotUnit/RobotUnitModules/RobotUnitModuleRobotData.cpp
@@ -0,0 +1,120 @@
+/*
+ * This file is part of ArmarX.
+ *
+ * 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    RobotAPI::ArmarXObjects::RobotUnit
+ * @author     Raphael Grimm ( raphael dot grimm at kit dot edu )
+ * @date       2018
+ * @copyright  http://www.gnu.org/licenses/gpl-2.0.txt
+ *             GNU General Public License
+ */
+
+#include <VirtualRobot/XML/RobotIO.h>
+#include <VirtualRobot/RobotNodeSet.h>
+
+#include <ArmarXCore/core/system/cmake/CMakePackageFinder.h>
+#include <ArmarXCore/core/system/ArmarXDataPath.h>
+
+#include "RobotUnitModuleRobotData.h"
+
+namespace armarx
+{
+    namespace RobotUnitModule
+    {
+        const std::string &RobotData::getRobotPlatformName() const
+        {
+            ARMARX_CHECK_EXPRESSION_W_HINT(robot, __FUNCTION__ << " should only be called after _preOnInitRobotUnit was called");
+            return robotPlatformName;
+        }
+
+        const std::string &RobotData::getRobotNodetSeName() const
+        {
+            ARMARX_CHECK_EXPRESSION_W_HINT(robot, __FUNCTION__ << " should only be called after _preOnInitRobotUnit was called");
+            return robotNodeSetName;
+        }
+
+        const std::string &RobotData::getRobotProjectName() const
+        {
+            ARMARX_CHECK_EXPRESSION_W_HINT(robot, __FUNCTION__ << " should only be called after _preOnInitRobotUnit was called");
+            return robotProjectName;
+        }
+
+        const std::string &RobotData::getRobotFileName() const
+        {
+            ARMARX_CHECK_EXPRESSION_W_HINT(robot, __FUNCTION__ << " should only be called after _preOnInitRobotUnit was called");
+            return robotFileName;
+        }
+
+        std::string RobotData::getRobotName() const
+        {
+            std::lock_guard<std::mutex> guard{robotMutex};
+            ARMARX_CHECK_EXPRESSION_W_HINT(robot, __FUNCTION__ << " should only be called after _preOnInitRobotUnit was called");
+            return robot->getName();
+        }
+
+        VirtualRobot::RobotPtr RobotData::cloneRobot(bool updateCollisionModel) const
+        {
+            std::lock_guard<std::mutex> guard{robotMutex};
+            ARMARX_CHECK_EXPRESSION_W_HINT(robot, __FUNCTION__ << " should only be called after _preOnInitRobotUnit was called");
+            ARMARX_CHECK_EXPRESSION(robot);
+            const VirtualRobot::RobotPtr clone = robot->clone();
+            clone->setUpdateVisualization(false);
+            clone->setUpdateCollisionModel(updateCollisionModel);
+            return clone;
+        }
+
+        void armarx::RobotUnitModule::RobotData::_preOnInitRobotUnit()
+        {
+            robotNodeSetName    = getProperty<std::string>("RobotNodeSetName").getValue();
+            robotProjectName    = getProperty<std::string>("RobotFileNameProject").getValue();
+            robotFileName       = getProperty<std::string>("RobotFileName").getValue();
+            robotPlatformName   = getProperty<std::string>("PlatformName").getValue();
+
+            //load robot
+            {
+                Ice::StringSeq includePaths;
+                if (!robotProjectName.empty())
+                {
+                    CMakePackageFinder finder(robotProjectName);
+                    Ice::StringSeq projectIncludePaths;
+                    auto pathsString = finder.getDataDir();
+                    boost::split(projectIncludePaths,
+                                 pathsString,
+                                 boost::is_any_of(";,"),
+                                 boost::token_compress_on);
+                    includePaths.insert(includePaths.end(), projectIncludePaths.begin(), projectIncludePaths.end());
+                }
+                if (!ArmarXDataPath::getAbsolutePath(robotFileName, robotFileName, includePaths))
+                {
+                    throw UserException("Could not find robot file " + robotFileName);
+                }
+                // read the robot
+                try
+                {
+                    robot = VirtualRobot::RobotIO::loadRobot(robotFileName, VirtualRobot::RobotIO::eFull);
+                }
+                catch (VirtualRobot::VirtualRobotException& e)
+                {
+                    throw UserException(e.what());
+                }
+                ARMARX_INFO << "Loaded robot:"
+                            << "\n\tProject      : " << robotProjectName
+                            << "\n\tRobot file   : " << robotFileName
+                            << "\n\tRobotNodeSet : " << robotNodeSetName
+                            << "\n\tNodeNames    : " << robot->getRobotNodeSet(robotNodeSetName)->getNodeNames();
+                ARMARX_CHECK_NOT_NULL(robot);
+            }
+        }
+    }
+}
diff --git a/source/RobotAPI/components/units/RobotUnit/RobotUnitModules/RobotUnitModuleRobotData.h b/source/RobotAPI/components/units/RobotUnit/RobotUnitModules/RobotUnitModuleRobotData.h
new file mode 100644
index 0000000000000000000000000000000000000000..b8c1161301acbe11c730c86048a0fffe79c52ecc
--- /dev/null
+++ b/source/RobotAPI/components/units/RobotUnit/RobotUnitModules/RobotUnitModuleRobotData.h
@@ -0,0 +1,135 @@
+/*
+ * This file is part of ArmarX.
+ *
+ * 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    RobotAPI::ArmarXObjects::RobotUnit
+ * @author     Raphael Grimm ( raphael dot grimm at kit dot edu )
+ * @date       2018
+ * @copyright  http://www.gnu.org/licenses/gpl-2.0.txt
+ *             GNU General Public License
+ */
+
+#pragma once
+
+#include <VirtualRobot/Robot.h>
+
+#include <ArmarXCore/core/services/tasks/TaskUtil.h>
+#include <ArmarXCore/core/ArmarXManager.h>
+#include <ArmarXCore/observers/DebugObserver.h>
+
+#include "RobotUnitModuleBase.h"
+
+namespace armarx
+{
+    namespace RobotUnitModule
+    {
+        class RobotDataPropertyDefinitions: public ModuleBasePropertyDefinitions
+        {
+        public:
+            RobotDataPropertyDefinitions(std::string prefix): ModuleBasePropertyDefinitions(prefix)
+            {
+                defineRequiredProperty<std::string>(
+                    "RobotFileName", "Robot file name, e.g. robot_model.xml");
+                defineOptionalProperty<std::string>(
+                    "RobotFileNameProject", "",
+                    "Project in which the robot filename is located (if robot is loaded from an external project)");
+
+                defineOptionalProperty<std::string>(
+                    "RobotNodeSetName", "Robot",
+                    "Robot node set name as defined in robot xml file, e.g. 'LeftArm'");
+                defineOptionalProperty<std::string>(
+                    "PlatformName", "Platform",
+                    "Name of the platform (will publish values on PlatformName + 'State')");
+            }
+        };
+
+        /**
+         * @brief This \ref ModuleBase "Module" holds all high-level data about the robot.
+         *
+         * @see ModuleBase
+         */
+        class RobotData : virtual public ModuleBase
+        {
+            friend class ModuleBase;
+        public:
+            /**
+             * @brief Returns the singleton instance of this class
+             * @return The singleton instance of this class
+             */
+            static RobotData& Instance()
+            {
+                return ModuleBase::Instance<RobotData>();
+            }
+            // //////////////////////////////////////////////////////////////////////////////////////// //
+            // ///////////////////////////////// RobotUnitModule hooks //////////////////////////////// //
+            // //////////////////////////////////////////////////////////////////////////////////////// //
+        private:
+            /// @see ModuleBase::_preOnInitRobotUnit
+            void _preOnInitRobotUnit();
+            // //////////////////////////////////////////////////////////////////////////////////////// //
+            // /////////////////////////////////// Module interface /////////////////////////////////// //
+            // //////////////////////////////////////////////////////////////////////////////////////// //
+        public:
+            /**
+             * @brief Returns the name of the robot's platform
+             * @return The name of the robot's platform
+             */
+            const std::string& getRobotPlatformName() const;
+            /**
+             * @brief Returns the name of the robot's RobotNodeSet
+             * @return The name of the robot's RobotNodeSet
+             */
+            const std::string& getRobotNodetSeName() const;            
+            /**
+             * @brief Returns the name of the project containing the robot's model
+             * @return The name of the project containing the robot's model
+             */
+            const std::string& getRobotProjectName() const;
+            /**
+             * @brief Returns the file name of the robot's model
+             * @return The file name of the robot's model
+             */
+            const std::string& getRobotFileName() const;
+
+            /**
+             * @brief Returns the robot's name
+             * @return The robot's name
+             */
+            std::string getRobotName() const;
+
+            /**
+             * @brief Returns a clone of the robot's model
+             * @return A clone of the robot's model
+             */
+            VirtualRobot::RobotPtr cloneRobot(bool updateCollisionModel = false) const;
+            // //////////////////////////////////////////////////////////////////////////////////////// //
+            // ///////////////////////////////////////// Data ///////////////////////////////////////// //
+            // //////////////////////////////////////////////////////////////////////////////////////// //
+        private:
+            /// @brief The name of the robot's RobotNodeSet
+            std::string robotNodeSetName;
+            /// @brief The name of the project containing the robot's model
+            std::string robotProjectName;
+            /// @brief The file name of the robot's model
+            std::string robotFileName;
+            /// @brief The name of the robot's platform
+            std::string robotPlatformName;
+
+            /// @brief The robot's model.
+            boost::shared_ptr<VirtualRobot::Robot> robot;
+            /// @brief A mutex guarding \ref robot
+            mutable std::mutex robotMutex;
+        };
+    }
+}
diff --git a/source/RobotAPI/components/units/RobotUnit/RobotUnitModules/RobotUnitModuleSelfCollisionChecker.cpp b/source/RobotAPI/components/units/RobotUnit/RobotUnitModules/RobotUnitModuleSelfCollisionChecker.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..1f4b83449c63f57d7b7971ecb9b6769803587f2b
--- /dev/null
+++ b/source/RobotAPI/components/units/RobotUnit/RobotUnitModules/RobotUnitModuleSelfCollisionChecker.cpp
@@ -0,0 +1,268 @@
+/*
+ * This file is part of ArmarX.
+ *
+ * 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    RobotAPI::ArmarXObjects::RobotUnit
+ * @author     Raphael Grimm ( raphael dot grimm at kit dot edu )
+ * @date       2018
+ * @copyright  http://www.gnu.org/licenses/gpl-2.0.txt
+ *             GNU General Public License
+ */
+
+#include <VirtualRobot/RobotNodeSet.h>
+#include <VirtualRobot/Obstacle.h>
+
+#include "RobotUnitModuleSelfCollisionChecker.h"
+#include "RobotUnitModuleRobotData.h"
+
+#include "../NJointControllers/NJointController.h"
+
+namespace armarx
+{
+    namespace RobotUnitModule
+    {
+        void SelfCollisionChecker::_preOnInitRobotUnit()
+        {
+            {
+                const std::string colModelsString = getProperty<std::string>("SelfCollisionpairsToCheck").getValue();
+                std::vector<std::string> groups;
+                if (!colModelsString.empty())
+                {
+                    groups = armarx::Split(colModelsString, ";", true, true);
+                }
+                for (std::string& group : groups)
+                {
+                    // Removing parentheses
+                    boost::trim_if(group, boost::is_any_of(" \t{}"));
+                    std::set<std::string> nodes;
+                    {
+                        auto splittedRaw = armarx::Split(group, ",", true, true);
+                        if(splittedRaw.size() < 2)
+                        {
+                            continue;
+                        }
+                        for(auto& subentry : splittedRaw)
+                        {
+                            boost::trim_if(subentry, boost::is_any_of(" \t{}"));
+                            if(selfCollisionAvoidanceRobot->hasRobotNodeSet(subentry))
+                            {
+                                //the entry is a set
+                                for(const auto& node : selfCollisionAvoidanceRobot->getRobotNodeSet(subentry)->getAllRobotNodes())
+                                {
+                                    if (!node->getCollisionModel())
+                                    {
+
+                                        ARMARX_WARNING << "Self Collision Avoidance: No collision model found for '"
+                                                       << node->getName() << "'";
+                                        continue;
+                                    }
+                                    nodes.emplace(node->getName());
+                                }
+                            }
+                            else if(selfCollisionAvoidanceRobot->hasRobotNode(subentry))
+                            {
+                                //the entry is a node
+                                if (!selfCollisionAvoidanceRobot->getRobotNode(subentry)->getCollisionModel())
+                                {
+
+                                    ARMARX_WARNING << "Self Collision Avoidance: No collision model found for '"
+                                                   << selfCollisionAvoidanceRobot->getRobotNode(subentry)->getName() << "'";
+                                    continue;
+                                }
+                                nodes.emplace(subentry);
+                            }
+                            else if(subentry == "FLOOR")
+                            {
+                                //the entry is the floor
+                                nodes.emplace(subentry);
+                            }
+                            else
+                            {
+                                ARMARX_ERROR << "No RobotNodeSet or RobotNode with name '"
+                                             << subentry
+                                             << "' defined in " << _module<RobotData>().getRobotFileName() << ". Skipping.";
+                                continue;
+                            }
+                        }
+                    }
+
+
+
+                    for(auto it1 = nodes.begin(); it1 != nodes.end(); ++it1)
+                    {
+                        auto it2 = it1;
+                        ++it2;
+                        for(; it2 != nodes.end(); ++it2)
+                        {
+                            namePairsToCheck.emplace(*it1, *it2);
+                        }
+                    }
+                }
+            }
+            setSelfCollisionAvoidanceFrequency(getProperty<float>("SelfCollisionCheckFrequency").getValue());
+        }
+
+        void SelfCollisionChecker::_postOnInitRobotUnit()
+        {
+            setSelfCollisionAvoidanceDistance(getProperty<float>("MinSelfDistance").getValue());
+        }
+
+        void SelfCollisionChecker::setSelfCollisionAvoidanceDistance(Ice::Float distance, const Ice::Current&)
+        {
+            std::lock_guard<std::mutex> guard{selfCollisionDataMutex};
+            if(distance < 0)
+            {
+                throw InvalidArgumentException{
+                    std::string{__FILE__} + ": " + BOOST_CURRENT_FUNCTION + ": illegal distance:" + std::to_string(distance)
+                };
+            }
+            if(distance == minSelfDistance && !nodePairsToCheck.empty())
+            {
+                return;
+            }
+            //reset data
+            ARMARX_CHECK_GREATER(distance,0);
+            minSelfDistance = distance;
+            selfCollisionAvoidanceRobot = _module<RobotData>().cloneRobot(true);
+            selfCollisionAvoidanceRobotNodes = selfCollisionAvoidanceRobot->getRobotNodes();
+            nodePairsToCheck.clear();
+            //set floor
+            {
+                floor.reset(new VirtualRobot::SceneObjectSet("FLOORSET"));
+                VirtualRobot::ObstaclePtr boxOb = VirtualRobot::Obstacle::createBox(200000, 200000, std::min(0.001f, minSelfDistance / 2));
+                boxOb->setGlobalPose(Eigen::Matrix4f::Identity());
+                boxOb->setName("FLOOR");
+                floor->addSceneObject(boxOb);
+            }
+            //inflate robot
+            for (const auto& node : selfCollisionAvoidanceRobotNodes)
+            {
+                if (node->getCollisionModel())
+                {
+                    node->getCollisionModel()->inflateModel(minSelfDistance / 2.f);
+                }
+            }
+            //collect pairs
+            for(const auto& pair : namePairsToCheck)
+            {
+                VirtualRobot::SceneObjectPtr first  =
+                        (pair.first  == "FLOOR") ?
+                            floor->getSceneObject(0) :
+                            selfCollisionAvoidanceRobot->getRobotNode(pair.first );
+
+                VirtualRobot::SceneObjectPtr second =
+                        (pair.second == "FLOOR") ?
+                            floor->getSceneObject(0) :
+                            selfCollisionAvoidanceRobot->getRobotNode(pair.second);
+
+                nodePairsToCheck.emplace_back(first, second);
+            }
+        }
+
+        void SelfCollisionChecker::setSelfCollisionAvoidanceFrequency(Ice::Float freq, const Ice::Current&)
+        {
+            if(freq < 0)
+            {
+                throw InvalidArgumentException{
+                    std::string{__FILE__} + ": " + BOOST_CURRENT_FUNCTION + ": illegal frequency:" + std::to_string(freq)
+                };
+            }
+            checkFrequency = freq;
+        }
+
+        bool SelfCollisionChecker::isSelfCollisionCheckEnabled(const Ice::Current&) const
+        {
+            return checkFrequency != 0;
+        }
+
+        float SelfCollisionChecker::getSelfCollisionAvoidanceFrequency(const Ice::Current&) const
+        {
+            return checkFrequency;
+        }
+
+        float SelfCollisionChecker::getSelfCollisionAvoidanceDistance(const Ice::Current&) const
+        {
+            return minSelfDistance;
+        }
+
+        void SelfCollisionChecker::componentPropertiesUpdated(const std::set<std::string> &changed)
+        {
+            if(changed.count("SelfCollisionCheckFrequency"))
+            {
+                setSelfCollisionAvoidanceFrequency(getProperty<float>("SelfCollisionCheckFrequency").getValue());
+            }
+            if(changed.count("MinSelfDistance"))
+            {
+                setSelfCollisionAvoidanceDistance(getProperty<float>("MinSelfDistance").getValue());
+            }
+        }
+
+        void SelfCollisionChecker::_postFinishControlThreadInitialization()
+        {
+            selfCollisionAvoidanceThread = std::thread{[&]{selfCollisionAvoidanceTask();}};
+        }
+
+        void SelfCollisionChecker::selfCollisionAvoidanceTask()
+        {
+            while(true)
+            {
+                const auto startT = std::chrono::high_resolution_clock::now();
+                //done
+                if(isShuttingDown())
+                {
+                    return;
+                }
+                const auto freq = checkFrequency.load();
+                if (
+                        _module<ControlThread>().getEmergencyStopState() ||
+                        freq == 0
+                        )
+                {
+                    //currently wait
+                    std::this_thread::sleep_for(std::chrono::microseconds{1000});
+                    continue;
+                }
+                //update robot + check
+                {
+                    std::lock_guard<std::mutex> guard{selfCollisionDataMutex};
+                    //update robot
+                    _module<ControlThreadDataBuffer>().updateVirtualRobot(selfCollisionAvoidanceRobot, selfCollisionAvoidanceRobotNodes);
+                    //check
+                    for(const auto& pair : nodePairsToCheck)
+                    {
+                        if(selfCollisionAvoidanceRobot->getCollisionChecker()->checkCollision(pair.first, pair.second))
+                        {
+                            ARMARX_WARNING << "COLLISION: '" << pair.first->getName() << "' and '" << pair.second->getName() << "'";
+                            _module<Units>().getEmergencyStopMaster()->setEmergencyStopState(EmergencyStopState::eEmergencyStopActive);
+                            // since at least one of the NJoint-Controllers is going to cause a collision, we just kick them all.
+                            _module<ControlThreadDataBuffer>().setActivateControllersRequest({});
+                            continue;
+                        }
+                    }
+                }
+                //sleep remaining
+                std::this_thread::sleep_until(startT + std::chrono::microseconds{static_cast<int64_t>(1000000 / freq)});
+            }
+        }
+
+        void SelfCollisionChecker::_preFinishRunning()
+        {
+            ARMARX_INFO << "Stopping Self Collision Avoidance.";
+            if (selfCollisionAvoidanceThread.joinable())
+            {
+                selfCollisionAvoidanceThread.join();
+            }
+        }
+    }
+}
diff --git a/source/RobotAPI/components/units/RobotUnit/RobotUnitModules/RobotUnitModuleSelfCollisionChecker.h b/source/RobotAPI/components/units/RobotUnit/RobotUnitModules/RobotUnitModuleSelfCollisionChecker.h
new file mode 100644
index 0000000000000000000000000000000000000000..5fb8e2faae8b826afe9c5ea977c718053803cbc1
--- /dev/null
+++ b/source/RobotAPI/components/units/RobotUnit/RobotUnitModules/RobotUnitModuleSelfCollisionChecker.h
@@ -0,0 +1,165 @@
+/*
+ * This file is part of ArmarX.
+ *
+ * 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    RobotAPI::ArmarXObjects::RobotUnit
+ * @author     Raphael Grimm ( raphael dot grimm at kit dot edu )
+ * @date       2018
+ * @copyright  http://www.gnu.org/licenses/gpl-2.0.txt
+ *             GNU General Public License
+ */
+
+#pragma once
+
+#include <thread>
+
+#include <VirtualRobot/Robot.h>
+
+#include <ArmarXCore/core/services/tasks/PeriodicTask.h>
+
+#include <RobotAPI/interface/units/RobotUnit/RobotUnitInterface.h>
+#include "RobotUnitModuleBase.h"
+
+namespace armarx
+{
+    namespace RobotUnitModule
+    {
+        class SelfCollisionCheckerPropertyDefinitions: public ModuleBasePropertyDefinitions
+        {
+        public:
+            SelfCollisionCheckerPropertyDefinitions(std::string prefix): ModuleBasePropertyDefinitions(prefix)
+            {
+                defineOptionalProperty<float>(
+                    "SelfCollisionCheckFrequency", 10,
+                    "Frequency [Hz] of self collision checking (default = 10). If set to 0, no cllisions will be checked.",
+                    PropertyDefinitionBase::eModifiable);
+                defineOptionalProperty<float>(
+                    "MinSelfDistance", 20,
+                    "Minimum allowed distance (mm) between each collision model before entering emergency stop (default = 20).",
+                    PropertyDefinitionBase::eModifiable);
+                defineOptionalProperty<std::string>(
+                    "SelfCollisionpairsToCheck", "",
+                    "Comma seperated list of groups (two or more) of collision models (RobotNodeSets or RobotNodes) that "
+                    "should be checked against each other by collision avoidance \n"
+                    "(e.g. {rnsColModel1,rnsColModel2};{rnsColModel3,rnsColModel4}; .... "
+                    "says that rnsColModel1 will be only checked against rnsColModel2 and rnsColModel3 will only be checked against rnsColModel4). \n"
+                    "Following predefined descriptors can be used: 'FLOOR' which represents a virtual collision model of the floor.");
+            }
+        };
+
+        /**
+         * @brief This \ref ModuleBase "Module" manages self collision avoidance.
+         * If the distance between a pair of bodies falls below a threshold, the the emergency stop is activated.
+         *
+         * @see ModuleBase
+         */
+        class SelfCollisionChecker : virtual public ModuleBase, virtual public RobotUnitSelfCollisionCheckerInterface
+        {
+            friend class ModuleBase;
+        public:
+            /**
+             * @brief Returns the singleton instance of this class
+             * @return The singleton instance of this class
+             */
+            static SelfCollisionChecker& Instance()
+            {
+                return ModuleBase::Instance<SelfCollisionChecker>();
+            }
+            // //////////////////////////////////////////////////////////////////////////////////////// //
+            // ///////////////////////////////// RobotUnitModule hooks //////////////////////////////// //
+            // //////////////////////////////////////////////////////////////////////////////////////// //
+        private:
+            /// @see ModuleBase::_preOnInitRobotUnit
+            void _preOnInitRobotUnit();
+            /// @see ModuleBase::_postOnInitRobotUnit
+            void _postOnInitRobotUnit();
+            /// @see ModuleBase::_postFinishControlThreadInitialization
+            void _postFinishControlThreadInitialization();
+            /// @see ModuleBase::_preFinishRunning
+            void _preFinishRunning();
+            // //////////////////////////////////////////////////////////////////////////////////////// //
+            // ///////////////////////////////////// ice interface //////////////////////////////////// //
+            // //////////////////////////////////////////////////////////////////////////////////////// //
+        public:
+            /**
+             * @brief Sets the minimal distance (mm) between a configured pair of bodies to 'distance'.
+             * @param distance The minimal distance (mm) between a pair of bodies.
+             */
+            void setSelfCollisionAvoidanceDistance(Ice::Float distance, const Ice::Current& = GlobalIceCurrent) override;
+            /**
+             * @brief Sets the frequency of self collision checks.
+             * @param freq The frequency of self collision checks.
+             */
+            void setSelfCollisionAvoidanceFrequency(Ice::Float freq, const Ice::Current& = GlobalIceCurrent) override;
+
+            /**
+             * @brief Returns whether the frequency of self collision checks is above 0.
+             * @return Whether the frequency of self collision checks is above 0.
+             */
+            bool isSelfCollisionCheckEnabled(const Ice::Current& = GlobalIceCurrent) const override;
+            /**
+             * @brief Returns the frequency of self collision checks.
+             * @return The frequency of self collision checks.
+             */
+            float getSelfCollisionAvoidanceFrequency(const Ice::Current& = GlobalIceCurrent) const override;
+            /**
+             * @brief Returns the minimal distance (mm) between a pair of bodies.
+             * @return The minimal distance (mm) between a pair of bodies.
+             */
+            float getSelfCollisionAvoidanceDistance(const Ice::Current& = GlobalIceCurrent) const override;
+            // //////////////////////////////////////////////////////////////////////////////////////// //
+            // ////////////////////////////////// Component interface ///////////////////////////////// //
+            // //////////////////////////////////////////////////////////////////////////////////////// //
+        public:
+            /// @see armarx::Component::componentPropertiesUpdated
+            void componentPropertiesUpdated(const std::set<std::string>& changed) override;
+            // //////////////////////////////////////////////////////////////////////////////////////// //
+            // //////////////////////////////////// implementation //////////////////////////////////// //
+            // //////////////////////////////////////////////////////////////////////////////////////// //
+        private:
+            /// @brief The Loop executing the self collision check
+            void selfCollisionAvoidanceTask();
+            // //////////////////////////////////////////////////////////////////////////////////////// //
+            // ///////////////////////////////////////// Data ///////////////////////////////////////// //
+            // //////////////////////////////////////////////////////////////////////////////////////// //
+        private:
+            /// @brief The thread executing \ref selfCollisionAvoidanceTask
+            std::thread selfCollisionAvoidanceThread;
+            // //////////////////////////////////////////////////////////////////////////////////////// //
+            // //////////////////////////////////////// config //////////////////////////////////////// //
+            // //////////////////////////////////////////////////////////////////////////////////////// //
+        private:
+            /// @brief The list of pairs of collision models that should be checked agaisnt each other (names only)
+            std::set< std::pair<std::string, std::string>> namePairsToCheck;
+            /// @brief The frequency of self collision checks.
+            std::atomic<float> checkFrequency{0};
+            // //////////////////////////////////////////////////////////////////////////////////////// //
+            // /////////////////////////////////////// col data /////////////////////////////////////// //
+            // //////////////////////////////////////////////////////////////////////////////////////// //
+        private:
+            ///@ brief The mutex guarding data used for self collision checks.
+            std::mutex selfCollisionDataMutex;
+            /// @brief Min allowed distance (mm) between each pair of collision models
+            std::atomic<float> minSelfDistance{0};
+            /// @brief The list of pairs of collision models that should be checked agaisnt each other (model nodes only)
+            std::vector<std::pair<VirtualRobot::SceneObjectPtr, VirtualRobot::SceneObjectPtr>> nodePairsToCheck;
+            /// @brief The Robot used for self collison checks
+            VirtualRobot::RobotPtr selfCollisionAvoidanceRobot;
+            /// @brief The Robot Nodes of the Robot used for collision checks
+            std::vector<VirtualRobot::RobotNodePtr> selfCollisionAvoidanceRobotNodes;
+            /// @brief A Collision object for the floor
+            VirtualRobot::SceneObjectSetPtr floor;
+        };
+    }
+}
diff --git a/source/RobotAPI/components/units/RobotUnit/RobotUnitModules/RobotUnitModuleUnits.cpp b/source/RobotAPI/components/units/RobotUnit/RobotUnitModules/RobotUnitModuleUnits.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..accc6c49421fa76142ed857de4b842d0ea8eb1c7
--- /dev/null
+++ b/source/RobotAPI/components/units/RobotUnit/RobotUnitModules/RobotUnitModuleUnits.cpp
@@ -0,0 +1,541 @@
+/*
+ * This file is part of ArmarX.
+ *
+ * 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    RobotAPI::ArmarXObjects::RobotUnit
+ * @author     Raphael Grimm ( raphael dot grimm at kit dot edu )
+ * @date       2018
+ * @copyright  http://www.gnu.org/licenses/gpl-2.0.txt
+ *             GNU General Public License
+ */
+
+#include <ArmarXCore/core/IceManager.h>
+#include <ArmarXCore/core/IceGridAdmin.h>
+
+#include "RobotUnitModuleUnits.h"
+
+#include "../Units/ForceTorqueSubUnit.h"
+#include "../Units/InertialMeasurementSubUnit.h"
+#include "../Units/KinematicSubUnit.h"
+#include "../Units/PlatformSubUnit.h"
+#include "../Units/TCPControllerSubUnit.h"
+#include "../Units/TrajectoryControllerSubUnit.h"
+
+#include "../SensorValues/SensorValue1DoFActuator.h"
+
+#include "../RobotUnit.h"
+
+namespace armarx
+{
+    namespace RobotUnitModule
+    {
+        class RobotUnitEmergencyStopMaster :
+            virtual public ManagedIceObject,
+            virtual public EmergencyStopMasterInterface
+        {
+        public:
+            RobotUnitEmergencyStopMaster(ControlThread* controlThreadModule, std::string emergencyStopTopicName) :
+                controlThreadModule {controlThreadModule},
+                emergencyStopTopicName {emergencyStopTopicName}
+            {
+                ARMARX_CHECK_NOT_NULL(controlThreadModule);
+                ARMARX_CHECK_EXPRESSION(!emergencyStopTopicName.empty());
+            }
+
+            virtual void setEmergencyStopState(EmergencyStopState state, const Ice::Current& = GlobalIceCurrent) final
+            {
+                if(getEmergencyStopState() == state)
+                {
+                    return;
+                }
+                controlThreadModule->setEmergencyStopStateNoReportToTopic(state);
+                emergencyStopTopic->reportEmergencyStopState(state);
+            }
+            virtual EmergencyStopState getEmergencyStopState(const Ice::Current& = GlobalIceCurrent) const final
+            {
+                return controlThreadModule->getEmergencyStopState();
+            }
+
+        protected:
+            virtual void onInitComponent() final
+            {
+                armarx::ManagedIceObject::offeringTopic(emergencyStopTopicName);
+            }
+            virtual void onConnectComponent() final
+            {
+                emergencyStopTopic = armarx::ManagedIceObject::getTopic<EmergencyStopListenerPrx>(emergencyStopTopicName);
+                setEmergencyStopState(EmergencyStopState::eEmergencyStopInactive);
+            }
+
+            virtual std::string getDefaultName() const final
+            {
+                return "EmergencyStopMaster";
+            }
+
+        protected:
+            ControlThread* const controlThreadModule;
+            const std::string emergencyStopTopicName;
+            EmergencyStopListenerPrx emergencyStopTopic;
+        };
+    }
+}
+
+namespace armarx
+{
+    namespace RobotUnitModule
+    {
+        Ice::ObjectProxySeq Units::getUnits(const Ice::Current &) const
+        {
+            std::vector<ManagedIceObjectPtr> unitsCopy;
+            {
+                auto guard = getGuard();
+                //copy to keep lock retention time low
+                unitsCopy = units;
+            }
+            Ice::ObjectProxySeq r;
+            r.reserve(unitsCopy.size());
+            for (const ManagedIceObjectPtr& unit : unitsCopy)
+            {
+                r.emplace_back(unit->getProxy(-1, true));
+            }
+            return r;
+        }
+
+        Ice::ObjectPrx Units::getUnit(const std::string &staticIceId, const Ice::Current &) const
+        {
+            //no lock required
+            ManagedIceObjectPtr unit = getUnit(staticIceId);
+            if (unit)
+            {
+                return unit->getProxy(-1, true);
+            }
+            return nullptr;
+        }
+
+        const EmergencyStopMasterInterfacePtr &Units::getEmergencyStopMaster() const
+        {
+            return emergencyStopMaster;
+        }
+
+        void Units::initializeDefaultUnits()
+        {
+            auto beg = MicroNow();
+            {
+                auto guard = getGuard();
+                throwIfStateIsNot(RobotUnitState::InitializingUnits, __FUNCTION__);
+                ARMARX_INFO << "initializing default units";
+                initializeKinematicUnit();
+                ARMARX_DEBUG << "KinematicUnit initialized";
+                initializePlatformUnit();
+                ARMARX_DEBUG << "PlatformUnit initialized";
+                initializeForceTorqueUnit();
+                ARMARX_DEBUG << "ForceTorqueUnit initialized";
+                initializeInertialMeasurementUnit();
+                ARMARX_DEBUG << "InertialMeasurementUnit initialized";
+                initializeTrajectoryControllerUnit();
+                ARMARX_DEBUG << "TrajectoryControllerUnit initialized";
+                initializeTcpControllerUnit();
+                ARMARX_DEBUG << "TcpControllerUnit initialized";
+            }
+            ARMARX_INFO << "initializing default units...done! " << (MicroNow() - beg).count() << " us";
+        }
+
+        void Units::initializeKinematicUnit()
+        {
+            /// TODO move init code to Kinematic sub unit
+            using UnitT = KinematicSubUnit;
+            using IfaceT = KinematicUnitInterface;
+
+            auto guard = getGuard();
+            throwIfStateIsNot(RobotUnitState::InitializingUnits, __FUNCTION__);
+            //check if unit is already added
+            if (getUnit(IfaceT::ice_staticId()))
+            {
+                return;
+            }
+            //add ctrl et al
+            std::map<std::string, UnitT::ActuatorData> devs;
+            for (const ControlDevicePtr& controlDevice : _module<Devices>().getControlDevices().values())
+            {
+                ARMARX_CHECK_EXPRESSION(controlDevice);
+                const auto& controlDeviceName = controlDevice->getDeviceName();
+                if (!controlDevice->hasTag(ControlDeviceTags::CreateNoDefaultController))
+                {
+                    UnitT::ActuatorData ad;
+                    ad.name = controlDeviceName;
+                    ad.sensorDeviceIndex =
+                            _module<Devices>().getSensorDevices().has(controlDeviceName) ?
+                                _module<Devices>().getSensorDevices().index(controlDeviceName) :
+                                std::numeric_limits<std::size_t>::max();
+                    /// TODO use better kinematic unit controllers (posThroughVel + ramps)
+    #define initializeKinematicUnit_tmp_helper(mode, CtargT, ctrl)                                                          \
+                    {                                                                                                                   \
+        const auto& controlMode = mode;                                                                                 \
+        NJointKinematicUnitPassThroughControllerPtr& pt = ctrl;                                                           \
+        JointController* jointCtrl = controlDevice->getJointController(controlMode);                                           \
+        if (jointCtrl && jointCtrl->getControlTarget()->isA<CtargT>())                                                            \
+                    {                                                                                                               \
+        NJointKinematicUnitPassThroughControllerConfigPtr config = new NJointKinematicUnitPassThroughControllerConfig;  \
+        config->controlMode=controlMode;                                                                            \
+        config->deviceName=controlDeviceName;                                                                       \
+        const NJointControllerPtr& nJointCtrl = _module<ControllerManagement>().createNJointController(                                                       \
+        "NJointKinematicUnitPassThroughController",                                   \
+        "NJointKU_PTCtrl_"+controlDeviceName+"_"+controlMode,                         \
+        config,                                                                     \
+        false, true);                                                               \
+        pt = NJointKinematicUnitPassThroughControllerPtr::dynamicCast(nJointCtrl);                                          \
+        ARMARX_CHECK_EXPRESSION(pt);                                                                                \
+                }                                                                                                               \
+                }
+                    initializeKinematicUnit_tmp_helper(ControlModes::Position1DoF, ControlTarget1DoFActuatorPosition, ad.ctrlPos)
+                            initializeKinematicUnit_tmp_helper(ControlModes::Velocity1DoF, ControlTarget1DoFActuatorVelocity, ad.ctrlVel)
+                            initializeKinematicUnit_tmp_helper(ControlModes::Torque1DoF  , ControlTarget1DoFActuatorTorque  , ad.ctrlTor)
+            #undef initializeKinematicUnit_tmp_helper
+
+
+                            if (ad.ctrlPos || ad.ctrlTor || ad.ctrlVel)
+                    {
+                        devs[controlDeviceName] = std::move(ad);
+                    }
+                }
+            }
+            if (devs.empty())
+            {
+                ARMARX_IMPORTANT << "No joint devices found - skipping adding of KinematicUnit";
+                return;
+            }
+            ARMARX_CHECK_EXPRESSION_W_HINT(!devs.empty(), "no 1DoF ControlDevice found with matching SensorDevice");
+            //add it
+            const std::string configName = getProperty<std::string>("KinematicUnitName");
+            const std::string confPre = getConfigDomain() + "." + configName + ".";
+            Ice::PropertiesPtr properties = getIceProperties()->clone();
+            //properties->setProperty(confPre + "MinimumLoggingLevel", getProperty<std::string>("MinimumLoggingLevel").getValue());
+            //fill properties
+            properties->setProperty(confPre + "RobotNodeSetName", _module<RobotData>().getRobotNodetSeName());
+            properties->setProperty(confPre + "RobotFileName", _module<RobotData>().getRobotFileName());
+            properties->setProperty(confPre + "RobotFileNameProject", _module<RobotData>().getRobotProjectName());
+            ARMARX_DEBUG << "creating unit " << configName << " using these properties: " << properties->getPropertiesForPrefix("");
+            IceInternal::Handle<UnitT> unit = Component::create<UnitT>(properties, configName, getConfigDomain());
+
+            //fill devices (sensor + controller)
+            unit->setupData(
+                        getProperty<std::string>("RobotFileName").getValue(),
+                        _module<RobotData>().cloneRobot(),
+                        std::move(devs),
+                        _module<Devices>().getControlModeGroups().groups,
+                        _module<Devices>().getControlModeGroups().groupsMerged,
+                        dynamic_cast<RobotUnit*>(this)
+                        );
+            //add
+            addUnit(std::move(unit));
+        }
+
+        void Units::initializePlatformUnit()
+        {
+            using UnitT = PlatformSubUnit;
+            using IfaceT = PlatformUnitInterface;
+
+            auto guard = getGuard();
+            throwIfStateIsNot(RobotUnitState::InitializingUnits, __FUNCTION__);
+            //check if unit is already added
+            if (getUnit(IfaceT::ice_staticId()))
+            {
+                return;
+            }
+            //is there a platform dev?
+            if (_module<RobotData>().getRobotPlatformName().empty())
+            {
+                ARMARX_INFO << "no platform unit created since no platform name was given";
+                return;
+            }
+            if (!_module<Devices>().getControlDevices().has(_module<RobotData>().getRobotPlatformName()))
+            {
+                ARMARX_WARNING << "no platform unit created since the platform control device with name '"
+                               << _module<RobotData>().getRobotPlatformName() << "' was not found";
+                return;
+            }
+            const ControlDevicePtr& controlDevice = _module<Devices>().getControlDevices().at(_module<RobotData>().getRobotPlatformName());
+            const SensorDevicePtr&  sensorDevice = _module<Devices>().getSensorDevices().at(_module<RobotData>().getRobotPlatformName());
+            JointController* jointVel = controlDevice->getJointController(ControlModes::HolonomicPlatformVelocity);
+            ARMARX_CHECK_EXPRESSION(jointVel);
+            ARMARX_CHECK_EXPRESSION(sensorDevice->getSensorValue()->asA<SensorValueHolonomicPlatform>());
+            //add it
+            const std::string configName = getProperty<std::string>("PlatformUnitName");
+            const std::string confPre = getConfigDomain() + "." + configName + ".";
+            Ice::PropertiesPtr properties = getIceProperties()->clone();
+            //properties->setProperty(confPre + "MinimumLoggingLevel", getProperty<std::string>("MinimumLoggingLevel").getValue());
+            //fill properties
+            properties->setProperty(confPre + "PlatformName", _module<RobotData>().getRobotPlatformName());
+            ARMARX_DEBUG << "creating unit " << configName << " using these properties: " << properties->getPropertiesForPrefix("");
+            IceInternal::Handle<UnitT> unit = Component::create<UnitT>(properties , configName, getConfigDomain());
+            //config
+            NJointHolonomicPlatformUnitVelocityPassThroughControllerConfigPtr config = new NJointHolonomicPlatformUnitVelocityPassThroughControllerConfig;
+            config->initialVelocityX = 0;
+            config->initialVelocityY = 0;
+            config->initialVelocityRotation = 0;
+            config->platformName = _module<RobotData>().getRobotPlatformName();
+            auto ctrl = NJointHolonomicPlatformUnitVelocityPassThroughControllerPtr::dynamicCast(
+                        _module<ControllerManagement>().createNJointController(
+                            "NJointHolonomicPlatformUnitVelocityPassThroughController", configName + "_VelPTContoller",
+                            config, false, true
+                            )
+                        );
+            ARMARX_CHECK_EXPRESSION(ctrl);
+            unit->pt = ctrl;
+            unit->platformSensorIndex = _module<Devices>().getSensorDevices().index(_module<RobotData>().getRobotPlatformName());
+            //add
+            addUnit(std::move(unit));
+        }
+
+        void Units::initializeForceTorqueUnit()
+        {
+            using UnitT = ForceTorqueSubUnit;
+            using IfaceT = ForceTorqueUnitInterface;
+
+            auto guard = getGuard();
+            throwIfStateIsNot(RobotUnitState::InitializingUnits, __FUNCTION__);
+            //check if unit is already added
+            if (getUnit(IfaceT::ice_staticId()))
+            {
+                return;
+            }
+            //check if it is required
+            std::vector<ForceTorqueSubUnit::DeviceData> ftdevs;
+            for (const SensorDevicePtr& ftSensorDevice : _module<Devices>().getSensorDevices().values())
+            {
+                if (ftSensorDevice->getSensorValue()->isA<SensorValueForceTorque>())
+                {
+                    ForceTorqueSubUnit::DeviceData ftSensorData;
+                    ftSensorData.sensorIndex = _module<Devices>().getSensorDevices().index(ftSensorDevice->getDeviceName());
+                    ftSensorData.deviceName = ftSensorDevice->getDeviceName();
+                    ftSensorData.frame = ftSensorDevice->getReportingFrame();
+                    ARMARX_CHECK_EXPRESSION_W_HINT(
+                                !ftSensorData.frame.empty(),
+                                "The sensor device '" << ftSensorData.deviceName << "' (index: " << ftSensorData.sensorIndex
+                                << ") reports force torque values but returns an empty string as reporting frame"
+                                );
+                    ARMARX_CHECK_EXPRESSION_W_HINT(
+                                unitCreateRobot->hasRobotNode(ftSensorData.frame),
+                                "The sensor device '" << ftSensorData.deviceName << "' (index: " << ftSensorData.sensorIndex
+                                << ") reports force torque values but returns a reporting frame '" << ftSensorData.frame
+                                << "' which is not present in the robot '" << _module<RobotData>().getRobotName() << "'"
+                                );
+                    ftdevs.emplace_back(std::move(ftSensorData));
+                }
+            }
+            if (ftdevs.empty())
+            {
+                ARMARX_IMPORTANT << "no force torque unit created since there are no force torque sensor devices";
+                return;
+            }
+            //add it
+            const std::string configName = getProperty<std::string>("ForceTorqueUnitName");
+            const std::string confPre = getConfigDomain() + "." + configName + ".";
+            Ice::PropertiesPtr properties = getIceProperties()->clone();
+            //properties->setProperty(confPre + "MinimumLoggingLevel", getProperty<std::string>("MinimumLoggingLevel").getValue());
+            //fill properties
+            properties->setProperty(confPre + "AgentName", _module<RobotData>().getRobotName());
+            properties->setProperty(confPre + "ForceTorqueTopicName", getProperty<std::string>("ForceTorqueTopicName").getValue());
+            ARMARX_DEBUG << "creating unit " << configName << " using these properties: " << properties->getPropertiesForPrefix("");
+            IceInternal::Handle<UnitT> unit = Component::create<UnitT>(properties, configName, getConfigDomain());
+            unit->devs = ftdevs;
+            //add
+            addUnit(std::move(unit));
+        }
+
+        void Units::initializeInertialMeasurementUnit()
+        {
+            using UnitT = InertialMeasurementSubUnit;
+            using IfaceT = InertialMeasurementUnitInterface;
+
+            auto guard = getGuard();
+            throwIfStateIsNot(RobotUnitState::InitializingUnits, __FUNCTION__);
+            //check if unit is already added
+            if (getUnit(IfaceT::ice_staticId()))
+            {
+                return;
+            }
+            //check if it is required
+            std::map<std::string, std::size_t> imudevs;
+            for (auto i : getIndices(_module<Devices>().getSensorDevices().keys()))
+            {
+                const SensorDevicePtr& sensorDevice = _module<Devices>().getSensorDevices().at(i);
+                if (sensorDevice->getSensorValue()->isA<SensorValueIMU>())
+                {
+                    imudevs[sensorDevice->getDeviceName()] = i;
+                }
+            }
+            if (imudevs.empty())
+            {
+                ARMARX_IMPORTANT << "no inertial measurement unit created since there are no imu sensor devices";
+                return;
+            }
+            //add it
+            const std::string configName = getProperty<std::string>("InertialMeasurementUnitName");
+            const std::string confPre = getConfigDomain() + "." + configName + ".";
+            Ice::PropertiesPtr properties = getIceProperties()->clone();
+            //properties->setProperty(confPre + "MinimumLoggingLevel", getProperty<std::string>("MinimumLoggingLevel").getValue());
+            //fill properties
+            properties->setProperty(confPre + "IMUTopicName", getProperty<std::string>("IMUTopicName").getValue());
+            IceInternal::Handle<UnitT> unit = Component::create<UnitT>(properties, configName, getConfigDomain());
+            unit->devs = imudevs;
+            //add
+            addUnit(std::move(unit));
+        }
+
+        void Units::initializeTrajectoryControllerUnit()
+        {
+            auto guard = getGuard();
+            throwIfStateIsNot(RobotUnitState::InitializingUnits, __FUNCTION__);
+            using UnitT = TrajectoryControllerSubUnit;
+            if (!getProperty<bool>("CreateTrajectoryPlayer").getValue())
+            {
+                return;
+            }
+
+            //check if unit is already added
+            if (getUnit(UnitT::ice_staticId()) || !trajectoryControllerSubUnit)
+            {
+                return;
+            }
+            (TrajectoryControllerSubUnitPtr::dynamicCast(trajectoryControllerSubUnit))->setup(_modulePtr<RobotUnit>());
+            addUnit(trajectoryControllerSubUnit);
+            trajectoryControllerSubUnit = nullptr;
+        }
+
+        void Units::initializeTcpControllerUnit()
+        {
+            auto guard = getGuard();
+            throwIfStateIsNot(RobotUnitState::InitializingUnits, __FUNCTION__);
+
+            if (!getProperty<bool>("CreateTrajectoryPlayer").getValue())
+            {
+                return;
+            }
+            using UnitT = TCPControllerSubUnit;
+
+            //check if unit is already added
+            if (getUnit(UnitT::ice_staticId()))
+            {
+                return;
+            }
+            (TCPControllerSubUnitPtr::dynamicCast(tcpControllerSubUnit))->setup(_modulePtr<RobotUnit>(), _module<RobotData>().cloneRobot());
+            addUnit(tcpControllerSubUnit);
+            tcpControllerSubUnit = nullptr;
+        }
+
+        void Units::addUnit(ManagedIceObjectPtr unit)
+        {
+            auto guard = getGuard();
+            throwIfStateIsNot(RobotUnitState::InitializingUnits, __FUNCTION__);
+            getArmarXManager()->addObjectAsync(unit, "", true, false);
+            //maybe add it to the sub units
+            RobotUnitSubUnitPtr rsu = RobotUnitSubUnitPtr::dynamicCast(unit);
+            if (rsu)
+            {
+                subUnits.emplace_back(std::move(rsu));
+            }
+            units.emplace_back(std::move(unit));
+        }
+
+        void Units::_icePropertiesInitialized()
+        {
+            Ice::PropertiesPtr properties = getIceProperties()->clone();
+            const std::string& configDomain = "ArmarX";
+            // create TCPControlSubUnit
+
+            {
+                const std::string configNameTCPControlUnit = getProperty<std::string>("TCPControlUnitName");
+                tcpControllerSubUnit = Component::create<TCPControllerSubUnit, TCPControllerSubUnitPtr>(properties, configNameTCPControlUnit, configDomain);
+                addPropertyUser(PropertyUserPtr::dynamicCast(tcpControllerSubUnit));
+            }
+
+            // create TrajectoryControllerSubUnit
+
+            {
+                const std::string configNameTrajectoryControllerUnit = getProperty<std::string>("TrajectoryControllerUnitName");
+                const std::string confPre = configDomain + "." + configNameTrajectoryControllerUnit + ".";
+                properties->setProperty(confPre + "KinematicUnitName", getProperty<std::string>("KinematicUnitName").getValue());
+                trajectoryControllerSubUnit = Component::create<TrajectoryControllerSubUnit, TrajectoryControllerSubUnitPtr>(properties, configNameTrajectoryControllerUnit, configDomain);
+                addPropertyUser(PropertyUserPtr::dynamicCast(trajectoryControllerSubUnit));
+            }
+        }
+
+        void Units::_preFinishRunning()
+        {
+            //remove all units
+            subUnits.clear();
+            for (ManagedIceObjectPtr& unit : units)
+            {
+                getArmarXManager()->removeObjectBlocking(unit->getName());
+            }
+            units.clear();
+        }
+
+        void Units::_preOnInitRobotUnit()
+        {
+            ARMARX_DEBUG << "add emergency stop master";
+            {
+                emergencyStopMaster = new RobotUnitEmergencyStopMaster {&_module<ControlThread>(),  getProperty<std::string>("EmergencyStopTopic").getValue()};
+                ManagedIceObjectPtr obj = ManagedIceObjectPtr::dynamicCast(emergencyStopMaster);
+                ARMARX_CHECK_EXPRESSION_W_HINT(obj, "RobotUnitEmergencyStopMaster");
+                getArmarXManager()->addObject(obj, getProperty<std::string>("EmergencyStopMasterName").getValue(), true);
+                auto prx = obj->getProxy(-1);
+                try
+                {
+                    getArmarXManager()->getIceManager()->getIceGridSession()->getAdmin()->addObject(prx);
+                }
+                catch (const IceGrid::ObjectExistsException&)
+                {
+                    getArmarXManager()->getIceManager()->getIceGridSession()->getAdmin()->updateObject(prx);
+                }
+                catch (std::exception& e)
+                {
+                    ARMARX_WARNING << "add the robot unit as emergency stop master to the ice grid admin!\nThere was an exception:\n" << e.what();
+                }
+            }
+            ARMARX_DEBUG << "add emergency stop master...done!";
+        }
+
+        void Units::_postOnInitRobotUnit()
+        {
+            unitCreateRobot = _module<RobotData>().cloneRobot();
+        }
+
+        void Units::_postOnExitRobotUnit()
+        {
+            ARMARX_DEBUG << "remove EmergencyStopMaster";
+            try
+            {
+                getArmarXManager()->removeObjectBlocking(ManagedIceObjectPtr::dynamicCast(emergencyStopMaster));
+                getArmarXManager()->getIceManager()->removeObject(getProperty<std::string>("EmergencyStopMasterName").getValue());
+            }
+            catch (...) {}
+            ARMARX_DEBUG << "remove EmergencyStopMaster...done!";
+        }
+
+        const ManagedIceObjectPtr &Units::getUnit(const std::string &staticIceId) const
+        {
+            auto guard = getGuard();
+            for (const ManagedIceObjectPtr& unit : units)
+            {
+                if (unit->ice_isA(staticIceId))
+                {
+                    return unit;
+                }
+            }
+            return ManagedIceObject::NullPtr;
+        }
+    }
+}
diff --git a/source/RobotAPI/components/units/RobotUnit/RobotUnitModules/RobotUnitModuleUnits.h b/source/RobotAPI/components/units/RobotUnit/RobotUnitModules/RobotUnitModuleUnits.h
new file mode 100644
index 0000000000000000000000000000000000000000..692f2aa43a240686076e09a2b823f7b13a41edfb
--- /dev/null
+++ b/source/RobotAPI/components/units/RobotUnit/RobotUnitModules/RobotUnitModuleUnits.h
@@ -0,0 +1,292 @@
+/*
+ * This file is part of ArmarX.
+ *
+ * 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    RobotAPI::ArmarXObjects::RobotUnit
+ * @author     Raphael Grimm ( raphael dot grimm at kit dot edu )
+ * @date       2018
+ * @copyright  http://www.gnu.org/licenses/gpl-2.0.txt
+ *             GNU General Public License
+ */
+
+#pragma once
+
+#include <RobotAPI/interface/units/RobotUnit/RobotUnitInterface.h>
+
+#include "RobotUnitModuleBase.h"
+#include "../Units/RobotUnitSubUnit.h"
+
+namespace armarx
+{
+    namespace RobotUnitModule
+    {
+        class UnitsPropertyDefinitions: public ModuleBasePropertyDefinitions
+        {
+        public:
+            UnitsPropertyDefinitions(std::string prefix): ModuleBasePropertyDefinitions(prefix)
+            {
+                defineOptionalProperty<std::string>(
+                    "KinematicUnitName", "KinematicUnit",
+                    "The name of the created kinematic unit");
+
+                defineOptionalProperty<std::string>(
+                    "PlatformUnitName", "PlatformUnit",
+                    "The name of the created platform unit");
+
+                defineOptionalProperty<std::string>(
+                    "ForceTorqueUnitName", "ForceTorqueUnit",
+                    "The name of the created force troque unit (empty = default)");
+                defineOptionalProperty<std::string>(
+                    "ForceTorqueTopicName", "ForceTorqueValues",
+                    "Name of the topic on which the force torque sensor values are provided");
+
+                defineOptionalProperty<std::string>(
+                    "InertialMeasurementUnitName", "InertialMeasurementUnit",
+                    "The name of the created inertial measurement unit (empty = default)");
+                defineOptionalProperty<std::string>(
+                    "IMUTopicName", "IMUValues",
+                    "Name of the IMU Topic.");
+
+                defineOptionalProperty<bool>(
+                    "CreateTCPControlUnit", false,
+                    "If true the TCPControl SubUnit is created and added");
+                defineOptionalProperty<std::string>(
+                    "TCPControlUnitName", "TCPControlUnit",
+                    "Name of the TCPControlUnit.");
+
+                defineOptionalProperty<bool>(
+                    "CreateTrajectoryPlayer", true,
+                    "If true the TrajectoryPlayer SubUnit is created and added");
+                defineOptionalProperty<std::string>(
+                    "TrajectoryControllerUnitName", "TrajectoryPlayer",
+                    "Name of the TrajectoryControllerUnit. The respective component outside of the RobotUnit is TrajectoryPlayer");
+
+                defineOptionalProperty<std::string>(
+                    "EmergencyStopMasterName", "EmergencyStopMaster",
+                    "The name used to register as an EmergencyStopMaster");
+                defineOptionalProperty<std::string>(
+                    "EmergencyStopTopic", "EmergencyStop",
+                    "The name of the topic over which changes of the emergencyStopState are sent.");
+            }
+        };
+
+        /**
+         * @brief This \ref ModuleBase "Module" manages all Units of a \ref RobotUnit
+         *
+         * These are the managed Units:
+         *   - \ref getKinematicUnit "KinematicUnit"
+         *   - \ref getForceTorqueUnit "ForceTorqueUnit"
+         *   - \ref getInertialMeasurementUnit "InertialMeasurementUnit"
+         *   - \ref getPlatformUnit "PlatformUnit"
+         *   - \ref getTCPControlUnit "TCPControlUnit"
+         *   - \ref getTrajectoryPlayer "TrajectoryPlayer"
+         *
+         * @see ModuleBase
+         */
+        class Units : virtual public ModuleBase, virtual public RobotUnitUnitInterface
+        {
+            friend class ModuleBase;
+        public:
+            /**
+             * @brief Returns the singleton instance of this class
+             * @return The singleton instance of this class
+             */
+            static Units& Instance();
+            // //////////////////////////////////////////////////////////////////////////////////////// //
+            // ///////////////////////////////// RobotUnitModule hooks //////////////////////////////// //
+            // //////////////////////////////////////////////////////////////////////////////////////// //
+        private:
+            /// @see ModuleBase::_preOnInitRobotUnit
+            void _preOnInitRobotUnit();
+            /// @see ModuleBase::_postOnInitRobotUnit
+            void _postOnInitRobotUnit();
+            /// @see ModuleBase::_icePropertiesInitialized
+            void _icePropertiesInitialized();
+            /// @see ModuleBase::_preFinishRunning
+            void _preFinishRunning();
+            /// @see ModuleBase::_postOnExitRobotUnit
+            void _postOnExitRobotUnit();
+            // //////////////////////////////////////////////////////////////////////////////////////// //
+            // ///////////////////////////////////// ice interface //////////////////////////////////// //
+            // //////////////////////////////////////////////////////////////////////////////////////// //
+        public:
+            /**
+             * @brief Returns proxies to all units
+             * @return Proxies to all units
+             */
+            Ice::ObjectProxySeq getUnits(const Ice::Current&) const;
+            /**
+             * @brief Returns a proxy to the Unit with the given ice id (or null if there is none)
+             * @param staticIceId The Unit's ice id
+             * @return A proxy to the Unit with the given ice id (or null if there is none)
+             */
+            Ice::ObjectPrx getUnit(const std::string& staticIceId, const Ice::Current&) const;
+
+            /**
+             * @brief Returns a proxy to the KinematicUnit
+             * @return A proxy to the KinematicUnit
+             */
+            KinematicUnitInterfacePrx getKinematicUnit(const Ice::Current&) const override;
+            /**
+             * @brief Returns a proxy to the ForceTorqueUnit
+             * @return A proxy to the ForceTorqueUnit
+             */
+            ForceTorqueUnitInterfacePrx getForceTorqueUnit(const Ice::Current&) const override;
+            /**
+             * @brief Returns a proxy to the InertialMeasurementUnit
+             * @return A proxy to the InertialMeasurementUnit
+             */
+            InertialMeasurementUnitInterfacePrx getInertialMeasurementUnit(const Ice::Current&) const override;
+            /**
+             * @brief Returns a proxy to the PlatformUnit
+             * @return A proxy to the PlatformUnit
+             */
+            PlatformUnitInterfacePrx getPlatformUnit(const Ice::Current&) const override;
+            /**
+             * @brief Returns a proxy to the TCPControlUnit
+             * @return A proxy to the TCPControlUnit
+             */
+            TCPControlUnitInterfacePrx getTCPControlUnit(const Ice::Current&) const override;
+            /**
+             * @brief Returns a proxy to the TrajectoryPlayer
+             * @return A proxy to the TrajectoryPlayer
+             */
+            TrajectoryPlayerInterfacePrx getTrajectoryPlayer(const Ice::Current&) const override;
+            // //////////////////////////////////////////////////////////////////////////////////////// //
+            // /////////////////////////////////// Module interface /////////////////////////////////// //
+            // //////////////////////////////////////////////////////////////////////////////////////// //
+        public:
+            //general getters
+            /**
+             * @brief Returns a pointer to the Unit with the given ice id (or null if there is none)
+             * @param staticIceId The Unit's ice id
+             * @return A pointer to the Unit with the given ice id (or null if there is none)
+             */
+            const ManagedIceObjectPtr& getUnit(const std::string& staticIceId) const;
+
+            /**
+             * @brief Returns a pointer to the Unit for the given type (or null if there is none)
+             * @return A pointer to the Unit for the given type (or null if there is none)
+             */
+            template<class T> typename T::PointerType getUnit() const;
+            /**
+             * @brief Returns a proxy to the Unit for the given type (or null if there is none)
+             * @return A proxy to the Unit for the given type (or null if there is none)
+             */
+            template<class T> typename T::ProxyType getUnitPrx() const;
+
+            //specific getters
+            /**
+             * @brief Returns a pointer to the KinematicUnit
+             * @return A pointer to the KinematicUnit
+             */
+            KinematicUnitInterfacePtr getKinematicUnit() const;
+            /**
+             * @brief Returns a pointer to the ForceTorqueUnit
+             * @return A pointer to the ForceTorqueUnit
+             */
+            ForceTorqueUnitInterfacePtr getForceTorqueUnit() const;
+            /**
+             * @brief Returns a pointer to the InertialMeasurementUnit
+             * @return A pointer to the InertialMeasurementUnit
+             */
+            InertialMeasurementUnitInterfacePtr getInertialMeasurementUnit() const;
+            /**
+             * @brief Returns a pointer to the PlatformUnit
+             * @return A pointer to the PlatformUnit
+             */
+            PlatformUnitInterfacePtr getPlatformUnit() const;
+            /**
+             * @brief Returns a pointer to the TCPControlUnit
+             * @return A pointer to the TCPControlUnit
+             */
+            TCPControlUnitInterfacePtr getTCPControlUnit() const;
+            /**
+             * @brief Returns a pointer to the TrajectoryPlayer
+             * @return A pointer to the TrajectoryPlayer
+             */
+            TrajectoryPlayerInterfacePtr getTrajectoryPlayer() const;
+            /**
+             * @brief Returns a pointer to the EmergencyStopMaster
+             * @return A pointer to the EmergencyStopMaster
+             */
+            const EmergencyStopMasterInterfacePtr& getEmergencyStopMaster() const;
+            // //////////////////////////////////////////////////////////////////////////////////////// //
+            // //////////////////////////////////// implementation //////////////////////////////////// //
+            // //////////////////////////////////////////////////////////////////////////////////////// //
+        protected:
+            /**
+             * @brief Calls all init hooks for all managed Units
+             *
+             * The called hooks are
+             *   - \ref initializeKinematicUnit
+             *   - \ref initializePlatformUnit
+             *   - \ref initializeForceTorqueUnit
+             *   - \ref initializeInertialMeasurementUnit
+             *   - \ref initializeTrajectoryControllerUnit
+             *   - \ref initializeTcpControllerUnit
+             */
+            virtual void initializeDefaultUnits();
+            /// @brief Initializes the KinematicUnit
+            virtual void initializeKinematicUnit();
+            /// @brief Initializes the PlatformUnit
+            virtual void initializePlatformUnit();
+            /// @brief Initializes the ForceTorqueUnit
+            virtual void initializeForceTorqueUnit();
+            /// @brief Initializes the InertialMeasurementUnit
+            virtual void initializeInertialMeasurementUnit();
+            /// @brief Initializes the TrajectoryControllerUnit
+            virtual void initializeTrajectoryControllerUnit();
+            /// @brief Initializes the TcpControllerUnit
+            virtual void initializeTcpControllerUnit();
+            /**
+             * @brief Registers a unit for management (the Unit is added and removed to the \ref ArmarXManager
+             * and updated with new values.
+             * @param unit The Unit to add.
+             */
+            void addUnit(ManagedIceObjectPtr unit);
+            // //////////////////////////////////////////////////////////////////////////////////////// //
+            // ///////////////////////////////////////// Data ///////////////////////////////////////// //
+            // //////////////////////////////////////////////////////////////////////////////////////// //
+        private:
+            /// @brief holds all units managed by the RobotUnit
+            std::vector<ManagedIceObjectPtr> units;
+            /// @brief holds a copy of all units managed by the RobotUnit derived from RobotUnitSubUnit
+            /// this is done to prevent casting
+            std::vector<RobotUnitSubUnitPtr> subUnits;
+
+            /// @brief Pointer to the EmergencyStopMaster used by the \ref RobotUnit
+            EmergencyStopMasterInterfacePtr emergencyStopMaster;
+
+            /// @brief Temporary ptr to the TCPControlUnit
+            ManagedIceObjectPtr tcpControllerSubUnit;
+            /// @brief Temporary ptr to the TrajectoryPlayer
+            ManagedIceObjectPtr trajectoryControllerSubUnit;
+
+            /// @brief A copy of the VirtualRobot to be used inside of this Module
+            VirtualRobot::RobotPtr unitCreateRobot;
+            // //////////////////////////////////////////////////////////////////////////////////////// //
+            // /////////////////////////////////////// Attorneys ////////////////////////////////////// //
+            // //////////////////////////////////////////////////////////////////////////////////////// //
+        private:
+            /**
+            * \brief This class allows minimal access to private members of \ref Units in a sane fashion for \ref Publisher.
+            * \warning !! DO NOT ADD ADDITIONAL FRIENDS IF YOU DO NOT KNOW WAHT YOU ARE DOING! IF YOU DO SOMETHING WRONG YOU WILL CAUSE UNDEFINED BEHAVIOUR !!
+            */
+            friend class UnitsAttorneyForPublisher;
+        };
+    }
+}
+
+#include "RobotUnitModuleUnits.ipp"
diff --git a/source/RobotAPI/components/units/RobotUnit/RobotUnitModules/RobotUnitModuleUnits.ipp b/source/RobotAPI/components/units/RobotUnit/RobotUnitModules/RobotUnitModuleUnits.ipp
new file mode 100644
index 0000000000000000000000000000000000000000..557577805b7e10f27d68779300fe1ee3c9b98b11
--- /dev/null
+++ b/source/RobotAPI/components/units/RobotUnit/RobotUnitModules/RobotUnitModuleUnits.ipp
@@ -0,0 +1,98 @@
+/*
+ * This file is part of ArmarX.
+ *
+ * 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    RobotAPI::ArmarXObjects::RobotUnit
+ * @author     Raphael Grimm ( raphael dot grimm at kit dot edu )
+ * @date       2018
+ * @copyright  http://www.gnu.org/licenses/gpl-2.0.txt
+ *             GNU General Public License
+ */
+
+#pragma once
+
+#include "RobotUnitModuleUnits.h"
+
+namespace armarx
+{
+    namespace RobotUnitModule
+    {
+        inline Units& Units::Instance()
+        {
+            return ModuleBase::Instance<Units>();
+        }
+
+        inline KinematicUnitInterfacePrx Units::getKinematicUnit(const Ice::Current&) const
+        {
+            return getUnitPrx<KinematicUnitInterface>();
+        }
+        inline ForceTorqueUnitInterfacePrx Units::getForceTorqueUnit(const Ice::Current&) const
+        {
+            return getUnitPrx<ForceTorqueUnitInterface>();
+        }
+        inline InertialMeasurementUnitInterfacePrx Units::getInertialMeasurementUnit(const Ice::Current&) const
+        {
+            return getUnitPrx<InertialMeasurementUnitInterface>();
+        }
+        inline PlatformUnitInterfacePrx Units::getPlatformUnit(const Ice::Current&) const
+        {
+            return getUnitPrx<PlatformUnitInterface>();
+        }
+        inline TCPControlUnitInterfacePrx Units::getTCPControlUnit(const Ice::Current&) const
+        {
+            return getUnitPrx<TCPControlUnitInterface>();
+        }
+        inline TrajectoryPlayerInterfacePrx Units::getTrajectoryPlayer(const Ice::Current&) const
+        {
+            return getUnitPrx<TrajectoryPlayerInterface>();
+        }
+
+        template<class T>
+        inline typename T::PointerType Units::getUnit() const
+        {
+            return T::PointerType::dynamicCast(getUnit(T::ice_staticId()));
+        }
+
+        template<class T>
+        inline typename T::ProxyType Units::getUnitPrx() const
+        {
+            return T::ProxyType::uncheckedCast(getUnit(T::ice_staticId(), GlobalIceCurrent));
+        }
+
+        inline KinematicUnitInterfacePtr Units::getKinematicUnit() const
+        {
+            return getUnit<KinematicUnitInterface>();
+        }
+        inline ForceTorqueUnitInterfacePtr Units::getForceTorqueUnit() const
+        {
+            return getUnit<ForceTorqueUnitInterface>();
+        }
+        inline InertialMeasurementUnitInterfacePtr Units::getInertialMeasurementUnit() const
+        {
+            return getUnit<InertialMeasurementUnitInterface>();
+        }
+        inline PlatformUnitInterfacePtr Units::getPlatformUnit() const
+        {
+            return getUnit<PlatformUnitInterface>();
+        }
+        inline TCPControlUnitInterfacePtr Units::getTCPControlUnit() const
+        {
+            return getUnit<TCPControlUnitInterface>();
+        }
+        inline TrajectoryPlayerInterfacePtr Units::getTrajectoryPlayer() const
+        {
+            return getUnit<TrajectoryPlayerInterface>();
+        }
+    }
+}
diff --git a/source/RobotAPI/components/units/RobotUnit/RobotUnitModules/RobotUnitModules.h b/source/RobotAPI/components/units/RobotUnit/RobotUnitModules/RobotUnitModules.h
new file mode 100644
index 0000000000000000000000000000000000000000..75c57423496559a2a7cca4437f67e0ab3c0542bd
--- /dev/null
+++ b/source/RobotAPI/components/units/RobotUnit/RobotUnitModules/RobotUnitModules.h
@@ -0,0 +1,36 @@
+/*
+ * This file is part of ArmarX.
+ *
+ * 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    RobotAPI::ArmarXObjects::RobotUnit
+ * @author     Raphael Grimm ( raphael dot grimm at kit dot edu )
+ * @date       2018
+ * @copyright  http://www.gnu.org/licenses/gpl-2.0.txt
+ *             GNU General Public License
+ */
+
+#pragma once
+
+#include "RobotUnitModuleBase.h"
+
+#include "RobotUnitModuleDevices.h"
+#include "RobotUnitModuleControlThreadDataBuffer.h"
+#include "RobotUnitModuleControlThread.h"
+#include "RobotUnitModuleUnits.h"
+#include "RobotUnitModuleLogging.h"
+#include "RobotUnitModulePublisher.h"
+#include "RobotUnitModuleRobotData.h"
+#include "RobotUnitModuleControllerManagement.h"
+#include "RobotUnitModuleManagement.h"
+#include "RobotUnitModuleSelfCollisionChecker.h"
diff --git a/source/RobotAPI/components/units/RobotUnit/RobotUnitObserver.h b/source/RobotAPI/components/units/RobotUnit/RobotUnitObserver.h
index 499f042b367a77303f9cf69a451438836e1e7da8..173d6f616c41438d52850e24cae16ab7965e7e17 100644
--- a/source/RobotAPI/components/units/RobotUnit/RobotUnitObserver.h
+++ b/source/RobotAPI/components/units/RobotUnit/RobotUnitObserver.h
@@ -2,8 +2,16 @@
 
 #include <ArmarXCore/observers/Observer.h>
 
+#include "util.h"
+
 namespace armarx
 {
+    namespace RobotUnitModule
+    {
+        class Publisher;
+    }
+
+    TYPEDEF_PTRS_HANDLE(RobotUnitObserver);
 
     class RobotUnitObserver : public Observer
     {
@@ -20,7 +28,7 @@ namespace armarx
         void onInitObserver() override;
         void onConnectObserver() override;
 
-        friend class RobotUnit;
+        friend class RobotUnitModule::Publisher;
 
         // ManagedIceObject interface
     protected:
@@ -29,6 +37,5 @@ namespace armarx
             return "RobotUnitObserver";
         }
     };
-
-} // namespace armarx
+}
 
diff --git a/source/RobotAPI/components/units/RobotUnit/SensorValues/SensorValueBase.h b/source/RobotAPI/components/units/RobotUnit/SensorValues/SensorValueBase.h
index 293880b631ed97978cc2955ec1a14b8bbd254443..661ef61773d0a7de94ae228a03fd51b0dea7292a 100644
--- a/source/RobotAPI/components/units/RobotUnit/SensorValues/SensorValueBase.h
+++ b/source/RobotAPI/components/units/RobotUnit/SensorValues/SensorValueBase.h
@@ -28,6 +28,8 @@
 
 #include <ArmarXCore/observers/variant/TimedVariant.h>
 
+#include "../util/HeterogenousContinuousContainerMacros.h"
+
 #include "../util.h"
 
 namespace armarx
@@ -88,77 +90,49 @@ namespace armarx
         virtual std::string getDataFieldAsString(std::size_t i) const = 0;
 
         //management functions
-        virtual void _copyTo(SensorValueBase* target) const = 0;
         template<class T, class = typename std::enable_if<std::is_base_of<SensorValueBase, T>::value>::type>
         void _copyTo(std::unique_ptr<T>& target) const
         {
             _copyTo(target.get());
         }
 
-        virtual std::unique_ptr<SensorValueBase> _clone() const = 0;
-
-        virtual std::size_t _sizeInBytes() const = 0;
-        virtual std::size_t _alignof() const = 0;
-        virtual SensorValueBase* _placementConstruct(void* place) const = 0;
-
         ARMARX_META_MAKE_HAS_MEMBER_FNC_CHECK(
             SensorValueHasGetClassMemberInfo,
             GetClassMemberInfo, SensorValueInfo<T>(*)(void));
+
+        ARMARX_PLACEMENT_CONSTRUCTION_HELPER_BASE(SensorValueBase)
     };
 }
 
-#define DETAIL_SensorValueBase_DEFAULT_METHOD_IMPLEMENTATION                                                            \
-    using SensorValueBase = ::armarx::SensorValueBase;                                                                  \
-    using VariantBasePtr = ::armarx::VariantBasePtr;                                                                    \
-    virtual SensorValueBase* _placementConstruct(void* place) const  override                                           \
-    {                                                                                                                   \
-        return new(place) std::decay<decltype(*this)>::type;                                                            \
-    }                                                                                                                   \
-    virtual std::size_t _sizeInBytes() const override                                                                   \
-    {                                                                                                                   \
-        return sizeof(std::decay<decltype(*this)>::type);                                                               \
-    }                                                                                                                   \
-    virtual std::size_t _alignof() const override                                                                       \
-    {                                                                                                                   \
-        return alignof(std::decay<decltype(*this)>::type);                                                              \
-    }                                                                                                                   \
-    virtual void _copyTo(SensorValueBase* target) const override                                                        \
-    {                                                                                                                   \
-        const auto targAsThis = target->asA<std::decay<decltype(*this)>::type>();                                       \
-        ARMARX_CHECK_NOT_NULL(targAsThis);                                                                              \
-        *targAsThis = *this;                                                                                            \
-    }                                                                                                                   \
-    virtual std::unique_ptr<SensorValueBase> _clone() const override                                                    \
-    {                                                                                                                   \
-        std::unique_ptr<SensorValueBase> c {new std::decay<decltype(*this)>::type};                                     \
-        SensorValueBase::_copyTo(c);                                                                                    \
-        return c;                                                                                                       \
-    }                                                                                                                   \
-    virtual std::string getSensorValueType(bool withoutNamespaceSpecifier = false) const override                       \
-    {                                                                                                                   \
-        return armarx::GetTypeString(*this, withoutNamespaceSpecifier);                                                 \
-    }                                                                                                                   \
-    void _check_for_static_GetClassMemberInfo_overload()                                                                \
-    {                                                                                                                   \
-        static_assert(SensorValueHasGetClassMemberInfo<std::decay<decltype(*this)>::type>::value,                       \
-                      "This class has to implement GetClassMemberInfo() returning "                                     \
-                      "an instance of SensorValueInfo<THIS_CLASS_TYPE>");                                               \
-    }                                                                                                                   \
-    virtual std::map<std::string, armarx::VariantBasePtr> toVariants(const IceUtil::Time& timestamp) const override     \
-    {                                                                                                                   \
-        return SensorValueInfo<std::decay<decltype(*this)>::type>::ToVariants(timestamp,this);                          \
-    }                                                                                                                   \
-    virtual std::size_t getNumberOfDataFields() const override                                                          \
-    {                                                                                                                   \
-        return SensorValueInfo<std::decay<decltype(*this)>::type>::GetNumberOfDataFields();                             \
-    }                                                                                                                   \
-    virtual std::string getDataFieldAsString(std::size_t i) const override                                              \
-    {                                                                                                                   \
-        return SensorValueInfo<std::decay<decltype(*this)>::type>::GetDataFieldAsString(this, i);                       \
-    }                                                                                                                   \
-    virtual std::vector<std::string> getDataFieldNames() const override                                                 \
-    {                                                                                                                   \
-        return SensorValueInfo<std::decay<decltype(*this)>::type>::GetDataFieldNames();                                 \
+#define DETAIL_SensorValueBase_DEFAULT_METHOD_IMPLEMENTATION                                        \
+    ARMARX_PLACEMENT_CONSTRUCTION_HELPER                                                            \
+    using SensorValueBase = ::armarx::SensorValueBase;                                              \
+    using VariantBasePtr = ::armarx::VariantBasePtr;                                                \
+    std::string getSensorValueType(bool withoutNamespaceSpecifier = false) const override           \
+    {                                                                                               \
+        return armarx::GetTypeString(*this, withoutNamespaceSpecifier);                             \
+    }                                                                                               \
+    void _check_for_static_GetClassMemberInfo_overload()                                            \
+    {                                                                                               \
+        static_assert(SensorValueHasGetClassMemberInfo<std::decay<decltype(*this)>::type>::value,   \
+                      "This class has to implement GetClassMemberInfo() returning "                 \
+                      "an instance of SensorValueInfo<THIS_CLASS_TYPE>");                           \
+    }                                                                                               \
+    std::map<std::string, VariantBasePtr> toVariants(const IceUtil::Time& timestamp) const override \
+    {                                                                                               \
+        return SensorValueInfo<std::decay<decltype(*this)>::type>::ToVariants(timestamp,this);      \
+    }                                                                                               \
+    std::size_t getNumberOfDataFields() const override                                              \
+    {                                                                                               \
+        return SensorValueInfo<std::decay<decltype(*this)>::type>::GetNumberOfDataFields();         \
+    }                                                                                               \
+    std::string getDataFieldAsString(std::size_t i) const override                                  \
+    {                                                                                               \
+        return SensorValueInfo<std::decay<decltype(*this)>::type>::GetDataFieldAsString(this, i);   \
+    }                                                                                               \
+    std::vector<std::string> getDataFieldNames() const override                                     \
+    {                                                                                               \
+        return SensorValueInfo<std::decay<decltype(*this)>::type>::GetDataFieldNames();             \
     }
 
 namespace armarx
@@ -173,4 +147,3 @@ namespace armarx
         }
     };
 }
-
diff --git a/source/RobotAPI/components/units/RobotUnit/SyntaxCheck.cpp b/source/RobotAPI/components/units/RobotUnit/SyntaxCheck.cpp
index 0abba9c4e92641556a49aa5a43afea6db08c2bf2..9b84a642a771e169886e6232bf9207387b75a5bc 100644
--- a/source/RobotAPI/components/units/RobotUnit/SyntaxCheck.cpp
+++ b/source/RobotAPI/components/units/RobotUnit/SyntaxCheck.cpp
@@ -19,6 +19,81 @@
  * @copyright  http://www.gnu.org/licenses/gpl-2.0.txt
  *             GNU General Public License
  */
+
+
+//#include "RobotUnit.h"
+
+//#include "NJointControllers/NJointController.h"
+
+//#include "RobotUnitModules/RobotUnitModuleBase.h"
+
+///////////////////////////////////
+
+//#include "RobotUnit.h"
+//#include "NJointControllers/NJointController.h"
+
+//#include "NJointControllers/NJointController.h"
+//#include "RobotUnit.h"
+
+//#include "NJointControllers/NJointController.h"
+//#include "RobotUnitModules/RobotUnitModuleBase.h"
+
+//#include "RobotUnitModules/RobotUnitModuleBase.h"
+//#include "NJointControllers/NJointController.h"
+
+//#include "RobotUnit.h"
+//#include "RobotUnitModules/RobotUnitModuleBase.h"
+
+//#include "RobotUnitModules/RobotUnitModuleBase.h"
+//#include "RobotUnit.h"
+
+////////////////////////////////////
+
+
+//#include "RobotUnit.h"
+//#include "NJointControllers/NJointController.h"
+//#include "RobotUnitModules/RobotUnitModuleBase.h"
+
+#include "NJointControllers/NJointController.h"
+#include "RobotUnit.h"
+#include "RobotUnitModules/RobotUnitModuleBase.h"
+
+//#include "NJointControllers/NJointController.h"
+//#include "RobotUnitModules/RobotUnitModuleBase.h"
+//#include "RobotUnit.h"
+
+//#include "RobotUnitModules/RobotUnitModuleBase.h"
+//#include "NJointControllers/NJointController.h"
+//#include "RobotUnit.h"
+
+//#include "RobotUnit.h"
+//#include "RobotUnitModules/RobotUnitModuleBase.h"
+//#include "NJointControllers/NJointController.h"
+
+//#include "RobotUnitModules/RobotUnitModuleBase.h"
+//#include "RobotUnit.h"
+//#include "NJointControllers/NJointController.h"
+
+
+///////////////////////////////////
+
+//#include <atomic>
+//#include <chrono>
+//#include <mutex>
+
+//#include <boost/preprocessor/variadic/to_seq.hpp>
+//#include <boost/preprocessor/seq/for_each.hpp>
+//#include <boost/current_function.hpp>
+
+//#include <VirtualRobot/Robot.h>
+
+//#include <ArmarXCore/core/Component.h>
+
+//#include <RobotAPI/interface/units/RobotUnit/RobotUnitInterface.h>
+
+
+
+/*
 #include "BasicControllers.h"
 #include "Constants.h"
 #include "ControlModes.h"
@@ -51,3 +126,4 @@
 #include "util.h"
 
 //this file is only for syntax checks
+*/
diff --git a/source/RobotAPI/components/units/RobotUnit/Units/KinematicSubUnit.h b/source/RobotAPI/components/units/RobotUnit/Units/KinematicSubUnit.h
index ea17140882f751e83b18b4210bca26c19e7457ee..70f0922a15a5e3687a7f9c70477047d195aa7432 100644
--- a/source/RobotAPI/components/units/RobotUnit/Units/KinematicSubUnit.h
+++ b/source/RobotAPI/components/units/RobotUnit/Units/KinematicSubUnit.h
@@ -39,7 +39,7 @@
 
 namespace armarx
 {
-    class RobotUnit;
+    TYPEDEF_PTRS_HANDLE(RobotUnit);
 
     TYPEDEF_PTRS_HANDLE(KinematicSubUnit);
     class KinematicSubUnit:
diff --git a/source/RobotAPI/components/units/RobotUnit/Units/RobotUnitSubUnit.h b/source/RobotAPI/components/units/RobotUnit/Units/RobotUnitSubUnit.h
index 74d52cb225de13b3b027a800d8f979523a931f69..c84b344b6155615f39da64e53c158c018bcf3427 100644
--- a/source/RobotAPI/components/units/RobotUnit/Units/RobotUnitSubUnit.h
+++ b/source/RobotAPI/components/units/RobotUnit/Units/RobotUnitSubUnit.h
@@ -37,4 +37,3 @@ namespace armarx
         virtual void update(const SensorAndControl& sc, const JointAndNJointControllers& c) = 0;
     };
 }
-
diff --git a/source/RobotAPI/components/units/RobotUnit/Units/TCPControllerSubUnit.cpp b/source/RobotAPI/components/units/RobotUnit/Units/TCPControllerSubUnit.cpp
index 6dca346a5c2bd056a5d402f7edb55926fd455650..f1cf80f9216e7f582386333a73c97527c26d6402 100644
--- a/source/RobotAPI/components/units/RobotUnit/Units/TCPControllerSubUnit.cpp
+++ b/source/RobotAPI/components/units/RobotUnit/Units/TCPControllerSubUnit.cpp
@@ -40,8 +40,6 @@ void TCPControllerSubUnit::setup(RobotUnit* rUnit, VirtualRobot::RobotPtr robot)
     ARMARX_CHECK_EXPRESSION(!robotUnit);
     ARMARX_CHECK_EXPRESSION(rUnit);
     robotUnit = rUnit;
-
-    robotSync.reset(new RobotSynchronization(robotUnit, coordinateTransformationRobot, coordinateTransformationRobot->getRobotNodeNames()));
 }
 
 void TCPControllerSubUnit::setCycleTime(Ice::Int, const Ice::Current& c)
@@ -92,7 +90,7 @@ void TCPControllerSubUnit::setTCPVelocity(const std::string& nodeSetName, const
         tcpController = ctrl;
     }
 
-    robotSync->sync();
+    robotUnit->updateVirtualRobot(coordinateTransformationRobot);
 
     float xVel = 0.f;
     float yVel = 0.f;
diff --git a/source/RobotAPI/components/units/RobotUnit/Units/TCPControllerSubUnit.h b/source/RobotAPI/components/units/RobotUnit/Units/TCPControllerSubUnit.h
index 7ba8b05af8bdf2e7a4ca3d271a5cf0e68cedecc7..2dd3c3c6f3a5a6922fe47dcd99777b40bcb08797 100644
--- a/source/RobotAPI/components/units/RobotUnit/Units/TCPControllerSubUnit.h
+++ b/source/RobotAPI/components/units/RobotUnit/Units/TCPControllerSubUnit.h
@@ -23,7 +23,6 @@
 #pragma once
 
 #include <RobotAPI/interface/units/TCPControlUnit.h>
-#include "../RobotSynchronization.h"
 
 #include "RobotUnitSubUnit.h"
 #include "../NJointControllers/NJointTCPController.h"
@@ -31,7 +30,7 @@
 
 namespace armarx
 {
-    class RobotUnit;
+    TYPEDEF_PTRS_HANDLE(RobotUnit);
 
     TYPEDEF_PTRS_HANDLE(TCPControllerSubUnit);
     class TCPControllerSubUnit :
@@ -53,7 +52,6 @@ namespace armarx
         //        mutable std::mutex dataMutex;
         RobotUnit* robotUnit = NULL;
         VirtualRobot::RobotPtr coordinateTransformationRobot;
-        RobotSynchronizationPtr robotSync;
 
         // ManagedIceObject interface
     protected:
diff --git a/source/RobotAPI/components/units/RobotUnit/Units/TrajectoryControllerSubUnit.h b/source/RobotAPI/components/units/RobotUnit/Units/TrajectoryControllerSubUnit.h
index f5c0170911f01d3c6b0c0c42fc197a56ee73d593..ab598eb70242718fed9661aafb82fed61ba15f3f 100644
--- a/source/RobotAPI/components/units/RobotUnit/Units/TrajectoryControllerSubUnit.h
+++ b/source/RobotAPI/components/units/RobotUnit/Units/TrajectoryControllerSubUnit.h
@@ -30,7 +30,6 @@
 
 #include "KinematicSubUnit.h"
 
-
 namespace armarx
 {
     class TrajectoryControllerSubUnitPropertyDefinitions:
@@ -164,4 +163,3 @@ namespace armarx
         RecursiveMutex controllerMutex;
     };
 }
-
diff --git a/source/RobotAPI/components/units/RobotUnit/util.h b/source/RobotAPI/components/units/RobotUnit/util.h
index c83cc4b68ab1a4a92c370f3cb3c8c442dbc82b99..091333dbb03f8921cd7a6778622b9af361367757 100644
--- a/source/RobotAPI/components/units/RobotUnit/util.h
+++ b/source/RobotAPI/components/units/RobotUnit/util.h
@@ -19,7 +19,6 @@
  * @copyright  http://www.gnu.org/licenses/gpl-2.0.txt
  *             GNU General Public License
  */
-
 #pragma once
 
 #include <ArmarXCore/core/util/PropagateConst.h>
@@ -32,4 +31,3 @@
 #include "util/introspection/ClassMemberInfo.h"
 
 #include <type_traits>
-
diff --git a/source/RobotAPI/components/units/RobotUnit/util/AtomicWrapper.h b/source/RobotAPI/components/units/RobotUnit/util/AtomicWrapper.h
index 0ad2e3cc01e3ee0a41710acfa186bc6e8093fa5a..639e9efb425ff7109ef25f01ff28eefa10fc5a53 100644
--- a/source/RobotAPI/components/units/RobotUnit/util/AtomicWrapper.h
+++ b/source/RobotAPI/components/units/RobotUnit/util/AtomicWrapper.h
@@ -19,7 +19,6 @@
  * @copyright  http://www.gnu.org/licenses/gpl-2.0.txt
  *             GNU General Public License
  */
-
 #pragma once
 
 #include <atomic>
diff --git a/source/RobotAPI/components/units/RobotUnit/util/ControlThreadOutputBuffer.cpp b/source/RobotAPI/components/units/RobotUnit/util/ControlThreadOutputBuffer.cpp
index 8d74623f09e12dfddb8c5df596e4d9b3af4c74b3..4355bed67a563a1b97c62012bae2caa473f517ff 100644
--- a/source/RobotAPI/components/units/RobotUnit/util/ControlThreadOutputBuffer.cpp
+++ b/source/RobotAPI/components/units/RobotUnit/util/ControlThreadOutputBuffer.cpp
@@ -30,10 +30,6 @@ namespace armarx
     ControlThreadOutputBuffer::Entry& ControlThreadOutputBuffer::getWriteBuffer()
     {
         ARMARX_CHECK_EXPRESSION(isInitialized);
-        if (useTripleBuffer)
-        {
-            return *tripleBuffer.getWriteBuffer();
-        }
         return entries.at(toBounds(writePosition));
     }
 
@@ -41,21 +37,12 @@ namespace armarx
     {
         ARMARX_CHECK_EXPRESSION(isInitialized);
         getWriteBuffer().iteration = writePosition;
-        if (useTripleBuffer)
-        {
-            tripleBuffer.commitWrite();
-        }
         ++writePosition;
     }
 
     const ControlThreadOutputBuffer::Entry& ControlThreadOutputBuffer::getReadBuffer() const
     {
         ARMARX_CHECK_EXPRESSION(isInitialized);
-        if (useTripleBuffer)
-        {
-            return *tripleBuffer.getReadBuffer();
-        }
-
         if (!onePastReadPosition)
         {
             //data is not initialized
@@ -67,10 +54,6 @@ namespace armarx
     bool ControlThreadOutputBuffer::updateReadBuffer() const
     {
         ARMARX_CHECK_EXPRESSION(isInitialized);
-        if (useTripleBuffer)
-        {
-            return tripleBuffer.updateReadBuffer();
-        }
         std::size_t writePosition = this->writePosition;
         if (onePastReadPosition == writePosition)
         {
@@ -84,14 +67,12 @@ namespace armarx
     void ControlThreadOutputBuffer::resetLoggingPosition() const
     {
         ARMARX_CHECK_EXPRESSION(isInitialized);
-        ARMARX_CHECK_EXPRESSION(!useTripleBuffer);
         onePastLoggingReadPosition = writePosition.load();
     }
 
     void ControlThreadOutputBuffer::foreachNewLoggingEntry(std::function<void (const ControlThreadOutputBuffer::Entry&)> consumer)
     {
         ARMARX_CHECK_EXPRESSION(isInitialized);
-        ARMARX_CHECK_EXPRESSION(!useTripleBuffer);
         if (writePosition - onePastLoggingReadPosition >= numEntries)
         {
             ARMARX_ERROR << "There are " << writePosition - onePastLoggingReadPosition
@@ -135,11 +116,7 @@ namespace armarx
         ARMARX_CHECK_EXPRESSION(!isInitialized);
         this->numEntries = numEntries;
         //decide whether to use a triple buffer (in case no rtlogging is used)
-        if (!numEntries)
-        {
-            useTripleBuffer = true;
-            numEntries = 3;
-        }
+        ARMARX_CHECK_NOT_EQUAL(numEntries, 0);
         entries.reserve(numEntries);
         entries.emplace_back(
             controlDevices, sensorDevices,
@@ -150,16 +127,6 @@ namespace armarx
             entries.emplace_back(entries.at(0));
         }
 
-        //init triple buffer if we use it
-        if (useTripleBuffer)
-        {
-            ARMARX_DEBUG << "Using a triplebuffer.";
-            tripleBuffer.reinitAllBuffers(&entries.at(0), &entries.at(1), &entries.at(2));
-        }
-        else
-        {
-            ARMARX_DEBUG << "Using a circular buffer.";
-        }
         isInitialized = true;
         return entries.at(0).getDataBufferSize();
     }
@@ -207,7 +174,7 @@ namespace armarx
         return *this;
     }
 
-    void detail::RtMessageLogEntryBase::print(Ice::Int rtThreadId) const
+    void detail::RtMessageLogEntryBase::print(Ice::Int controlThreadId) const
     {
         if (printMsg)
         {
@@ -216,7 +183,7 @@ namespace armarx
             (*loghelper(file().c_str(), line(), func().c_str())
              ->setBacktrace(false)
              ->setTag({"RtLogMessages"})
-             ->setThreadId(rtThreadId)
+             ->setThreadId(controlThreadId)
             )
                     << loggingLevel
                     <<  ::deactivateSpam(deactivateSpamSec, to_string(deactivateSpamTag_))
@@ -252,7 +219,7 @@ namespace armarx
             const RtMessageLogEntryBase* entry = other.entries.at(idx);
             ARMARX_CHECK_NOT_NULL(entry);
             maxAlign = std::max(maxAlign, entry->_alignof());
-            void* place = std::align(entry->_alignof(), entry->_sizeInBytes(), bufferPlace, bufferSpace);
+            void* place = std::align(entry->_alignof(), entry->_sizeof(), bufferPlace, bufferSpace);
             const auto hint = ARMARX_STREAM_PRINTER
             {
                 out << "entry " << idx << " of " << other.entriesWritten
@@ -261,7 +228,7 @@ namespace armarx
                     << "\nbuffer size        = " << buffer.size()
                     << "\nbuffer place       = " << bufferPlace
                     << "\nbuffer space       = " << bufferSpace
-                    << "\nentry size         = " << entry->_sizeInBytes()
+                    << "\nentry size         = " << entry->_sizeof()
                     << "\nentry align        = " << entry->_alignof()
                     << "\n"
                     << "\nother buffer size  = " << other.buffer.size()
@@ -274,7 +241,7 @@ namespace armarx
             ARMARX_CHECK_LESS_EQUAL_W_HINT(static_cast<void*>(&buffer.front()), static_cast<void*>(place), hint);
             ARMARX_CHECK_LESS_EQUAL_W_HINT(static_cast<void*>(place), static_cast<void*>(&buffer.back()), hint);
             ARMARX_CHECK_LESS_EQUAL_W_HINT(
-                static_cast<void*>(static_cast<std::uint8_t*>(place) + entry->_sizeInBytes() - 1),
+                static_cast<void*>(static_cast<std::uint8_t*>(place) + entry->_sizeof() - 1),
                 static_cast<void*>(&buffer.back()),
                 hint
             );
@@ -283,8 +250,8 @@ namespace armarx
             ARMARX_CHECK_EXPRESSION(!entries.at(entriesWritten));
             //            ARMARX_IMPORTANT << "PRE";
             entries.at(entriesWritten++) = entry->_placementCopyConstruct(place);
-            bufferSpace -= entry->_sizeInBytes();
-            bufferPlace = static_cast<std::uint8_t*>(place) + entry->_sizeInBytes();
+            bufferSpace -= entry->_sizeof();
+            bufferPlace = static_cast<std::uint8_t*>(place) + entry->_sizeof();
             //            ARMARX_IMPORTANT << "POST";
         }
         ARMARX_CHECK_EQUAL(entriesWritten, other.entriesWritten);
@@ -377,7 +344,7 @@ namespace armarx
                 bytes += alignShift;
                 maxAlign = std::max(maxAlign, align);
 
-                bytes += sd->getSensorValue()->_sizeInBytes();
+                bytes += sd->getSensorValue()->_sizeof();
             }
             for (const ControlDevicePtr& cd : controlDevices.values())
             {
@@ -388,7 +355,7 @@ namespace armarx
                     bytes += alignShift;
                     maxAlign = std::max(maxAlign, align);
 
-                    bytes += ctrl->getControlTarget()->_sizeInBytes();
+                    bytes += ctrl->getControlTarget()->_sizeof();
                 }
             }
             return bytes + maxAlign - 1;
@@ -413,7 +380,7 @@ namespace armarx
         for (const SensorDevicePtr& sd : sensorDevices.values())
         {
             const SensorValueBase* sv = sd->getSensorValue();
-            sensors.emplace_back(sv->_placementConstruct(getAlignedPlace(sv->_sizeInBytes(), sv->_alignof())));
+            sensors.emplace_back(sv->_placementConstruct(getAlignedPlace(sv->_sizeof(), sv->_alignof())));
         }
 
         control.reserve(controlDevices.size());
@@ -426,7 +393,7 @@ namespace armarx
             for (const JointController* ctrl : ctrls)
             {
                 const ControlTargetBase* ct = ctrl->getControlTarget();
-                ctargs.emplace_back(ct->_placementConstruct(getAlignedPlace(ct->_sizeInBytes(), ct->_alignof())));
+                ctargs.emplace_back(ct->_placementConstruct(getAlignedPlace(ct->_sizeof(), ct->_alignof())));
                 ctargs.back()->reset();
             }
         }
@@ -457,7 +424,7 @@ namespace armarx
         sensors.reserve(other.sensors.size());
         for (const SensorValueBase* sv : other.sensors)
         {
-            sensors.emplace_back(sv->_placementConstruct(getAlignedPlace(sv->_sizeInBytes(), sv->_alignof())));
+            sensors.emplace_back(sv->_placementConstruct(getAlignedPlace(sv->_sizeof(), sv->_alignof())));
         }
 
         control.reserve(other.control.size());
@@ -468,7 +435,7 @@ namespace armarx
             ctargs.reserve(cdctargs.size());
             for (const ControlTargetBase* ct : cdctargs)
             {
-                ctargs.emplace_back(ct->_placementConstruct(getAlignedPlace(ct->_sizeInBytes(), ct->_alignof())));
+                ctargs.emplace_back(ct->_placementConstruct(getAlignedPlace(ct->_sizeof(), ct->_alignof())));
                 ctargs.back()->reset();
             }
         }
diff --git a/source/RobotAPI/components/units/RobotUnit/util/ControlThreadOutputBuffer.h b/source/RobotAPI/components/units/RobotUnit/util/ControlThreadOutputBuffer.h
index 37a705e273c0f816f27d49aa5f5f125a96eb466a..dcfcb94cb0ca285ae8544fb3883f84bf02d8d490 100644
--- a/source/RobotAPI/components/units/RobotUnit/util/ControlThreadOutputBuffer.h
+++ b/source/RobotAPI/components/units/RobotUnit/util/ControlThreadOutputBuffer.h
@@ -21,30 +21,9 @@
  */
 
 #pragma once
-#include <memory>
 
-#if __GNUC__< 5
-namespace std
-{
-    inline void* align(size_t alignment, size_t bytes, void*& bufferPlace, size_t& bufferSpace) noexcept
-    {
-        const auto uiptr = reinterpret_cast<uintptr_t>(bufferPlace);
-        const auto alignedPlace = (uiptr - 1u + alignment) & -alignment;
-        const auto spaceRequired = alignedPlace - uiptr;
-        if ((bytes + spaceRequired) > bufferSpace)
-        {
-            return nullptr;
-        }
-        else
-        {
-            bufferSpace -= spaceRequired;
-            return bufferPlace = reinterpret_cast<void*>(alignedPlace);
-        }
-    }
-}
-#endif
+#include "HeterogenousContinuousContainer.h"
 
-#include <memory>
 #include <vector>
 
 #include <ArmarXCore/core/exceptions/local/ExpressionException.h>
@@ -66,26 +45,22 @@ namespace armarx
             RtMessageLogEntryBase():
                 time {IceUtil::Time::now()}
             {}
+            virtual ~RtMessageLogEntryBase() = default;
 
             RtMessageLogEntryBase& setLoggingLevel(MessageType lvl);
             RtMessageLogEntryBase& deactivateSpam(float sec);
             RtMessageLogEntryBase& deactivateSpamTag(std::uint64_t tag);
 
-            void print(Ice::Int rtThreadId) const;
+            void print(Ice::Int controlThreadId) const;
             virtual std::size_t line() const = 0;
             virtual std::string file() const = 0;
             virtual std::string func() const = 0;
             virtual std::string format() const = 0;
             IceUtil::Time getTime() const;
+
+            ARMARX_MINIMAL_PLACEMENT_CONSTRUCTION_HELPER_BASE(RtMessageLogEntryBase)
         protected:
             friend struct RtMessageLogBuffer;
-
-            virtual std::size_t _sizeInBytes() const = 0;
-            virtual std::size_t _alignof() const = 0;
-            virtual RtMessageLogEntryBase* _placementCopyConstruct(void* place) const = 0;
-
-            virtual ~RtMessageLogEntryBase() = default;
-
         private:
             MessageType loggingLevel {eUNDEFINED};
             float deactivateSpamSec {0};
@@ -99,12 +74,11 @@ namespace armarx
             static RtMessageLogEntryDummy Instance;
         protected:
             std::string format() const final override;
-            std::size_t _sizeInBytes() const final override;
-            std::size_t _alignof() const final override;
-            RtMessageLogEntryBase* _placementCopyConstruct(void*) const final override;
             std::size_t line() const final override;
             std::string file() const final override;
             std::string func() const final override;
+
+            ARMARX_MINIMAL_PLACEMENT_CONSTRUCTION_HELPER
         };
     }
 }
@@ -112,6 +86,12 @@ namespace armarx
 {
     class RobotUnit;
     class ControlThreadOutputBuffer;
+
+    namespace RobotUnitModule
+    {
+        class Logging;
+    }
+
     namespace detail
     {
         struct RtMessageLogBuffer
@@ -139,6 +119,7 @@ namespace armarx
             friend struct ControlThreadOutputBufferEntry;
             friend class ::armarx::ControlThreadOutputBuffer;
             friend class ::armarx::RobotUnit;
+            friend class ::armarx::RobotUnitModule::Logging;
 
             const std::size_t initialBufferSize;
             const std::size_t initialBufferEntryNumbers;
@@ -197,6 +178,11 @@ namespace armarx
 
 namespace armarx
 {
+    namespace RobotUnitModule
+    {
+        class Logging;
+    }
+
     struct ControlThreadOutputBuffer
     {
         using Entry = detail::ControlThreadOutputBufferEntry;
@@ -233,14 +219,13 @@ namespace armarx
         RtMessageLogEntryBase* addMessageToLog(Ts&& ...args);
 
     private:
-        friend class RobotUnit;
+        friend class RobotUnitModule::Logging;   ///TODO change code to make this unnecessary
         /// @brief this pointer is used for rt message logging and is not null in the control thread
         static thread_local ControlThreadOutputBuffer* RtLoggingInstance;
 
         std::size_t toBounds(std::size_t idx) const;
 
         //settings and initialization:
-        bool useTripleBuffer {false};
         bool isInitialized {false};
         std::size_t numEntries {0};
 
@@ -248,7 +233,6 @@ namespace armarx
         mutable std::atomic_size_t onePastLoggingReadPosition {0};
         mutable std::atomic_size_t onePastReadPosition {0};
 
-        TripleBuffer<Entry*> tripleBuffer;
         std::vector<Entry> entries;
         std::vector<std::uint8_t> data;
 
@@ -270,12 +254,7 @@ namespace armarx
     {                                                                                           \
         using TupleT = decltype(std::make_tuple(__VA_ARGS__));                                  \
         const TupleT tuple;                                                                     \
-        RtMessageLogEntryBase* _placementCopyConstruct(void* place) const final override        \
-        {                                                                                       \
-            return new(place) RtMessageLogEntry(*this);                                         \
-        }                                                                                       \
-        std::size_t _sizeInBytes() const final override {return sizeof(RtMessageLogEntry);}     \
-        std::size_t _alignof() const final override {return alignof(RtMessageLogEntry);}        \
+        ARMARX_MINIMAL_PLACEMENT_CONSTRUCTION_HELPER                                            \
         std::size_t line() const final override {return line_;}                                 \
         std::string file() const final override {return file_;}                                 \
         std::string func() const final override {return func_;}                                 \
@@ -314,21 +293,6 @@ namespace armarx
             throw std::logic_error {"called 'format' of RtMessageLogEntryDummy"};
         }
 
-        inline std::size_t RtMessageLogEntryDummy::_sizeInBytes() const
-        {
-            throw std::logic_error {"called '_sizeInBytes' of RtMessageLogEntryDummy"};
-        }
-
-        inline std::size_t RtMessageLogEntryDummy::_alignof() const
-        {
-            throw std::logic_error {"called '_alignof' of RtMessageLogEntryDummy"};
-        }
-
-        inline RtMessageLogEntryBase* RtMessageLogEntryDummy::_placementCopyConstruct(void*) const
-        {
-            throw std::logic_error {"called '_placementCopyConstruct' of RtMessageLogEntryDummy"};
-        }
-
         inline std::size_t RtMessageLogEntryDummy::line() const
         {
             throw std::logic_error {"called 'line' of RtMessageLogEntryDummy"};
@@ -400,10 +364,6 @@ namespace armarx
     template<class LoggingEntryT, class...Ts>
     inline ControlThreadOutputBuffer::RtMessageLogEntryBase* ControlThreadOutputBuffer::addMessageToLog(Ts&& ...args)
     {
-        if (useTripleBuffer)
-        {
-            return &detail::RtMessageLogEntryDummy::Instance;
-        }
         detail::RtMessageLogBuffer& messages = getWriteBuffer().messages;
         if (messages.entries.size() <= messages.entriesWritten)
         {
diff --git a/source/RobotAPI/components/units/RobotUnit/util/HeterogenousContinuousContainer.h b/source/RobotAPI/components/units/RobotUnit/util/HeterogenousContinuousContainer.h
new file mode 100644
index 0000000000000000000000000000000000000000..6d2118d46b7e8a0ec40728d471fd9c15248fd128
--- /dev/null
+++ b/source/RobotAPI/components/units/RobotUnit/util/HeterogenousContinuousContainer.h
@@ -0,0 +1,398 @@
+/*
+ * This file is part of ArmarX.
+ *
+ * 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    RobotAPI::RobotUnit
+ * @author     Raphael Grimm ( raphael dot grimm at kit dot edu )
+ * @date       2018
+ * @copyright  http://www.gnu.org/licenses/gpl-2.0.txt
+ *             GNU General Public License
+ */
+
+#pragma once
+
+#include <vector>
+
+#include <ArmarXCore/core/exceptions/local/ExpressionException.h>
+#include <ArmarXCore/core/util/TemplateMetaProgramming.h>
+#include <ArmarXCore/core/util/PropagateConst.h>
+
+#include "HeterogenousContinuousContainerMacros.h"
+
+#if __GNUC__< 5
+namespace std
+{
+    inline void* align(size_t alignment, size_t bytes, void*& bufferPlace, size_t& bufferSpace) noexcept
+    {
+        const auto uiptr = reinterpret_cast<uintptr_t>(bufferPlace);
+        const auto alignedPlace = (uiptr - 1u + alignment) & -alignment;
+        const auto spaceRequired = alignedPlace - uiptr;
+        if ((bytes + spaceRequired) > bufferSpace)
+        {
+            return nullptr;
+        }
+        else
+        {
+            bufferSpace -= spaceRequired;
+            return bufferPlace = reinterpret_cast<void*>(alignedPlace);
+        }
+    }
+}
+#endif
+
+namespace armarx
+{
+    namespace detail
+    {
+        template<class Base>
+        class HeterogenousContinuousContainerBase
+        {
+        public:
+            bool empty() const
+            {
+                return begin_ == current_;
+            }
+            bool owning() const
+            {
+                return storage_;
+            }
+            std::size_t getRemainingStorageCapacity() const
+            {
+                return static_cast<const std::uint8_t*>(end_) -
+                       static_cast<const std::uint8_t*>(current_);
+            }
+            std::size_t getStorageCapacity() const
+            {
+                return static_cast<const std::uint8_t*>(end_) -
+                       static_cast<const std::uint8_t*>(begin_);
+            }
+            std::size_t getUsedStorageCapacity() const
+            {
+                return static_cast<const std::uint8_t*>(current_) -
+                       static_cast<const std::uint8_t*>(begin_);
+            }
+            void assignStorage(void* begin, void* end)
+            {
+                ARMARX_CHECK_EXPRESSION(empty());
+                ARMARX_CHECK_LESS_EQUAL(begin, end);
+                storage_ = nullptr;
+                begin_ = begin;
+                current_ = begin;
+                end_ = end;
+            }
+            void setStorageCapacity(std::size_t sz)
+            {
+                ARMARX_CHECK_EXPRESSION(empty());
+                if(!sz)
+                {
+                    assignStorage(nullptr, nullptr);
+                    return;
+                }
+                //replache with void* aligned_alloc( std::size_t alignment, std::size_t size ) @c++17
+                sz += 63;
+                storage_.reset(new std::uint8_t[sz]);
+                begin_ = static_cast<void*>(storage_.get());
+                current_ = begin_;
+                end_ = static_cast<void*>(storage_.get() + sz);
+            }
+        protected:
+            template<class Derived>
+            Base* pushBack(const Derived* d)
+            {
+                static_assert(
+                    std::is_base_of<Base, Derived>::value,
+                    "HeterogenousContinuousContainerBase::pushBack: Derived must derive Base"
+                );
+                std::size_t space_ = getRemainingStorageCapacity();
+
+                void* ptr = std::align(d->_alignof(), d->_sizeof(), current_, space_);
+
+                if(!ptr)
+                {
+                    return nullptr;
+                }
+                current_ = static_cast<void*>(static_cast<std::uint8_t*>(ptr) + d->_sizeof());
+                return d->_placementCopyConstruct(ptr);
+            }
+            void clear()
+            {
+                current_ = begin_;
+            }
+        private:
+            std::unique_ptr<std::uint8_t[]> storage_{nullptr};
+            void* begin_{nullptr};
+            void* current_{nullptr};
+            void* end_{nullptr};
+        };
+    }
+
+    template<class Base, bool UsePropagateConst = true>
+    class HeterogenousContinuousContainer : public detail::HeterogenousContinuousContainerBase<Base>
+    {
+        using BaseContainer = detail::HeterogenousContinuousContainerBase<Base>;
+    public:
+        using ElementType = typename std::conditional<
+            UsePropagateConst,
+            PropagateConst<Base*>,
+            Base*
+        >::type;
+
+        HeterogenousContinuousContainer() = default;
+        HeterogenousContinuousContainer(HeterogenousContinuousContainer&&) = default;
+        HeterogenousContinuousContainer(const HeterogenousContinuousContainer& other, bool compressElems = false)
+        {
+            this->setStorageCapacity(compressElems ? other.getUsedStorageCapacity() : other.getStorageCapacity());
+            setElementCapacity(compressElems ? other.elements().size() : other.elements().capacity());
+            for(auto& e : other.elements())
+            {
+                pushBack(e);
+            }
+        }
+
+        HeterogenousContinuousContainer& operator=(HeterogenousContinuousContainer&&) = default;
+        HeterogenousContinuousContainer& operator=(const HeterogenousContinuousContainer& other)
+        {
+            clear();
+            setStorageCapacity(other.getStorageCapacity());
+            setElementCapacity(other.elements().capacity());
+            for(auto& e : other.elements())
+            {
+                pushBack(e);
+            }
+            return *this;
+        }
+
+        ~HeterogenousContinuousContainer()
+        {
+            clear();
+        }
+
+        std::size_t getElementCount() const
+        {
+            return elements_.size();
+        }
+        std::size_t getElementCapacity() const
+        {
+            return elements_.capacity();
+        }
+        std::size_t getRemainingElementCapacity() const
+        {
+            return getElementCapacity() - getElementCount();
+        }
+
+        void setElementCapacity(std::size_t cnt)
+        {
+            ARMARX_CHECK_EXPRESSION(this->empty());
+            if(elements_.capacity() > cnt)
+            {
+                //force the capacity to reduce
+                elements_ = std::vector<ElementType>{};
+            }
+            elements_.reserve(cnt);
+        }
+
+        template<class Derived>
+        Base* pushBack(const Derived* d)
+        {
+            static_assert(
+                std::is_base_of<Base, Derived>::value,
+                "HeterogenousContinuousContainerBase::pushBack: Derived must derive Base"
+            );
+            ARMARX_CHECK_NOT_NULL(d);
+            if(!getRemainingElementCapacity())
+            {
+                return nullptr;
+            }
+            Base* const ptr = BaseContainer::pushBack(d);
+            if(ptr)
+            {
+                elements_.emplace_back(ptr);
+            }
+            return ptr;
+        }
+        template<class Derived>
+        Base* pushBack(const PropagateConst<Derived*>& d)
+        {
+            return pushBack(*d);
+        }
+        template<class Derived>
+        Base* pushBack(const Derived& d)
+        {
+            return pushBack(&d);
+        }
+
+        std::vector<ElementType>& elements()
+        {
+            return elements_;
+        }
+        const std::vector<ElementType>& elements() const
+        {
+            return elements_;
+        }
+
+        void clear()
+        {
+            for(auto& e : elements_)
+            {
+                e->~Base();
+            }
+            elements_.clear();
+            BaseContainer::clear();
+        }
+    private:
+        std::vector<ElementType> elements_;
+    };
+
+    template<class Base, bool UsePropagateConst = true>
+    class HeterogenousContinuous2DContainer : public detail::HeterogenousContinuousContainerBase<Base>
+    {
+        using BaseContainer = detail::HeterogenousContinuousContainerBase<Base>;
+    public:
+        using ElementType = typename std::conditional<
+            UsePropagateConst,
+            PropagateConst<Base*>,
+            Base*
+        >::type;
+
+        HeterogenousContinuous2DContainer() = default;
+        HeterogenousContinuous2DContainer(HeterogenousContinuous2DContainer&&) = default;
+        HeterogenousContinuous2DContainer(const HeterogenousContinuous2DContainer& other, bool compressElems = false)
+        {
+            setStorageCapacity(compressElems ? other.getUsedStorageCapacity() : other.getStorageCapacity());
+            std::vector<std::size_t> elemCaps;
+            elemCaps.reserve(other.elements().size());
+            for(const auto& d1 : other.elements())
+            {
+                elemCaps.emplace_back(compressElems ? d1.size() : d1.capacity());
+            }
+            setElementCapacity(elemCaps);
+            for(std::size_t i = 0; i < other.elements().size(); ++i)
+            {
+                for(auto& e : other.elements().at(i))
+                {
+                    pushBack(i,e);
+                }
+            }
+        }
+
+        HeterogenousContinuous2DContainer& operator=(HeterogenousContinuous2DContainer&&) = default;
+        HeterogenousContinuous2DContainer& operator=(const HeterogenousContinuous2DContainer& other)
+        {
+            clear();
+            setStorageCapacity(other.getStorageCapacity());
+            std::vector<std::size_t> elemCaps;
+            elemCaps.reserve(other.elements().size());
+            for(const auto& d1 : other.elements())
+            {
+                elemCaps.emplace_back(d1.capacity());
+            }
+            setElementCapacity(elemCaps);
+            for(std::size_t i = 0; i < other.elements().size(); ++i)
+            {
+                for(auto& e : other.elements().at(i))
+                {
+                    pushBack(i,e);
+                }
+            }
+            return *this;
+        }
+
+        ~HeterogenousContinuous2DContainer()
+        {
+            clear();
+        }
+
+        std::size_t getElementCount(std::size_t d0) const
+        {
+            return elements_.at(d0).size();
+        }
+        std::size_t getElementCapacity(std::size_t d0) const
+        {
+            return elements_.at(d0).capacity();
+        }
+        std::size_t getRemainingElementCapacity(std::size_t d0) const
+        {
+            return getElementCapacity(d0) - getElementCount(d0);
+        }
+
+        void setElementCapacity(const std::vector<std::size_t>& cnt)
+        {
+            ARMARX_CHECK_EXPRESSION(this->empty());
+            elements_.resize(cnt.size());
+            for(std::size_t i = 0; i < cnt.size(); ++i)
+            {
+                if(elements_.at(i).capacity() > cnt)
+                {
+                    //force the capacity to reduce
+                    elements_.at(i) = std::vector<ElementType>{};
+                }
+                elements_.at(i).reserve(cnt.at(i));
+            }
+        }
+
+        template<class Derived>
+        Base* pushBack(std::size_t d0, const Derived* d)
+        {
+            static_assert(
+                std::is_base_of<Base, Derived>::value,
+                "HeterogenousContinuousContainerBase::pushBack: Derived must derive Base"
+            );
+            ARMARX_CHECK_NOT_NULL(d);
+            if(!getRemainingElementCapacity(d0))
+            {
+                return nullptr;
+            }
+            Base* const ptr = BaseContainer::pushBack(d);
+            if(ptr)
+            {
+                elements_.at(d0).emplace_back(ptr);
+            }
+            return ptr;
+        }
+        template<class Derived>
+        Base* pushBack(std::size_t d0, const PropagateConst<Derived*>& d)
+        {
+            return pushBack(d0, *d);
+        }
+        template<class Derived>
+        Base* pushBack(std::size_t d0, const Derived& d)
+        {
+            return pushBack(d0, &d);
+        }
+
+        std::vector<std::vector<ElementType>>& elements()
+        {
+            return elements_;
+        }
+        const std::vector<std::vector<ElementType>>& elements() const
+        {
+            return elements_;
+        }
+
+        void clear()
+        {
+            for(auto& d1 : elements_)
+            {
+                for(auto& e : d1)
+                {
+                    e->~Base();
+                }
+                d1.clear();
+            }
+            BaseContainer::clear();
+        }
+    private:
+        std::vector<std::vector<ElementType>> elements_;
+    };
+}
diff --git a/source/RobotAPI/components/units/RobotUnit/util/HeterogenousContinuousContainerMacros.h b/source/RobotAPI/components/units/RobotUnit/util/HeterogenousContinuousContainerMacros.h
new file mode 100644
index 0000000000000000000000000000000000000000..8178062c2939d175e37de8285ee9a9c365bfd568
--- /dev/null
+++ b/source/RobotAPI/components/units/RobotUnit/util/HeterogenousContinuousContainerMacros.h
@@ -0,0 +1,88 @@
+/*
+ * This file is part of ArmarX.
+ *
+ * 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    RobotAPI::RobotUnit
+ * @author     Raphael Grimm ( raphael dot grimm at kit dot edu )
+ * @date       2018
+ * @copyright  http://www.gnu.org/licenses/gpl-2.0.txt
+ *             GNU General Public License
+ */
+
+#pragma once
+
+#include <memory>
+#include <type_traits>
+
+#define ARMARX_MINIMAL_PLACEMENT_CONSTRUCTION_HELPER_BASE(CommonBaseType)   \
+    using _typeBase = CommonBaseType;                                       \
+    virtual std::size_t _alignof() const = 0;                               \
+    virtual std::size_t _sizeof() const = 0;                                \
+    virtual _typeBase* _placementCopyConstruct(void* place) const = 0;      \
+    std::size_t _accumulateSize(std::size_t offset = 0) const               \
+    {                                                                       \
+        return offset +                                                     \
+               (_alignof() - (offset % _alignof())) % _alignof() +          \
+               _sizeof();                                                   \
+    }
+
+#define ARMARX_PLACEMENT_CONSTRUCTION_HELPER_BASE(CommonBaseType)       \
+    ARMARX_MINIMAL_PLACEMENT_CONSTRUCTION_HELPER_BASE(CommonBaseType)   \
+    virtual void _copyTo(_typeBase* target) const = 0;                  \
+    virtual std::unique_ptr<_typeBase> _clone() const = 0;              \
+    virtual _typeBase* _placementConstruct(void* place) const = 0;
+
+#define ARMARX_MINIMAL_PLACEMENT_CONSTRUCTION_HELPER                \
+    std::size_t _alignof() const override                           \
+    {                                                               \
+        using _type = typename std::decay<decltype(*this)>::type;   \
+        return alignof(_type);                                      \
+    }                                                               \
+    std::size_t _sizeof() const override                            \
+    {                                                               \
+        using _type = typename std::decay<decltype(*this)>::type;   \
+        return sizeof(_type);                                       \
+    }                                                               \
+    _typeBase* _placementCopyConstruct(void* place) const override  \
+    {                                                               \
+        using _type = typename std::decay<decltype(*this)>::type;   \
+        return new(place) _type(*this);                             \
+    }                                                               \
+    void _checkBaseType()                                           \
+    {                                                               \
+        using _type = typename std::decay<decltype(*this)>::type;   \
+        static_assert(                                              \
+            std::is_base_of<_typeBase, _type>::value,               \
+            "This class has to derive the common base class");      \
+    }
+
+#define ARMARX_PLACEMENT_CONSTRUCTION_HELPER                        \
+    ARMARX_MINIMAL_PLACEMENT_CONSTRUCTION_HELPER                    \
+    void _copyTo(_typeBase* target) const override                  \
+    {                                                               \
+        using _type = typename std::decay<decltype(*this)>::type;   \
+        _type* const castedTarget = dynamic_cast<_type*>(target);   \
+        ARMARX_CHECK_NOT_NULL(castedTarget);                        \
+        *castedTarget = *this;                                      \
+    }                                                               \
+    std::unique_ptr<_typeBase> _clone() const override              \
+    {                                                               \
+        using _type = typename std::decay<decltype(*this)>::type;   \
+        return std::unique_ptr<_typeBase>{new _type(*this)};        \
+    }                                                               \
+    _typeBase* _placementConstruct(void* place) const override      \
+    {                                                               \
+        using _type = typename std::decay<decltype(*this)>::type;   \
+        return new(place) _type;                                    \
+    }
diff --git a/source/RobotAPI/components/units/RobotUnit/util/JointAndNJointControllers.h b/source/RobotAPI/components/units/RobotUnit/util/JointAndNJointControllers.h
index 37193e2728bb695eea96d2678c01f402fc7681d3..faee01fc2c8f714adef111b3ef3d483d54079e81 100644
--- a/source/RobotAPI/components/units/RobotUnit/util/JointAndNJointControllers.h
+++ b/source/RobotAPI/components/units/RobotUnit/util/JointAndNJointControllers.h
@@ -19,7 +19,6 @@
  * @copyright  http://www.gnu.org/licenses/gpl-2.0.txt
  *             GNU General Public License
  */
-
 #pragma once
 
 #include <vector>
diff --git a/source/RobotAPI/components/units/RobotUnit/util/Time.h b/source/RobotAPI/components/units/RobotUnit/util/Time.h
index 832ca38dd001f3ad890897adf95bf67d0b17f462..919ea91a7bfb378487614b8997dd044efa72e395 100644
--- a/source/RobotAPI/components/units/RobotUnit/util/Time.h
+++ b/source/RobotAPI/components/units/RobotUnit/util/Time.h
@@ -21,6 +21,7 @@
  */
 
 #pragma once
+
 #include <chrono>
 #include <ArmarXCore/core/time/TimeUtil.h>
 #include <ArmarXCore/observers/variant/TimestampVariant.h>
diff --git a/source/RobotAPI/components/units/RobotUnit/util/introspection/ClassMemberInfo.h b/source/RobotAPI/components/units/RobotUnit/util/introspection/ClassMemberInfo.h
index fc17efbbb5d3fb443410c50cf4b4a0473b7a5362..860e627af4d100e1a2fda8bb0f61afb25d725245 100644
--- a/source/RobotAPI/components/units/RobotUnit/util/introspection/ClassMemberInfo.h
+++ b/source/RobotAPI/components/units/RobotUnit/util/introspection/ClassMemberInfo.h
@@ -19,8 +19,8 @@
  * @copyright  http://www.gnu.org/licenses/gpl-2.0.txt
  *             GNU General Public License
  */
-
 #pragma once
+
 #include <ArmarXCore/core/util/algorithm.h>
 
 #include "ClassMemberInfoEntry.h"
diff --git a/source/RobotAPI/components/units/RobotUnit/util/introspection/ClassMemberInfoEntry.h b/source/RobotAPI/components/units/RobotUnit/util/introspection/ClassMemberInfoEntry.h
index c682df829d3ecc30bad2e4793f989914ab488953..9c1de849e80ba5853b28d45c99a08b0ed33fc00d 100644
--- a/source/RobotAPI/components/units/RobotUnit/util/introspection/ClassMemberInfoEntry.h
+++ b/source/RobotAPI/components/units/RobotUnit/util/introspection/ClassMemberInfoEntry.h
@@ -19,7 +19,6 @@
  * @copyright  http://www.gnu.org/licenses/gpl-2.0.txt
  *             GNU General Public License
  */
-
 #pragma once
 
 #include "DataFieldsInfo.h"
@@ -236,4 +235,3 @@ namespace armarx
         };
     }
 }
-
diff --git a/source/RobotAPI/components/units/RobotUnit/util/introspection/DataFieldsInfo.h b/source/RobotAPI/components/units/RobotUnit/util/introspection/DataFieldsInfo.h
index 8d902d9737de36042bf0eb4ccda80096f21d9120..15582f2ecc192c543211adfa25f0d19c859dfbd2 100644
--- a/source/RobotAPI/components/units/RobotUnit/util/introspection/DataFieldsInfo.h
+++ b/source/RobotAPI/components/units/RobotUnit/util/introspection/DataFieldsInfo.h
@@ -19,8 +19,8 @@
  * @copyright  http://www.gnu.org/licenses/gpl-2.0.txt
  *             GNU General Public License
  */
-
 #pragma once
+
 #include "../EigenForwardDeclarations.h"
 #include <string>
 #include <chrono>
@@ -248,4 +248,3 @@ namespace armarx
         };
     }
 }
-
diff --git a/source/RobotAPI/gui-plugins/RobotUnitPlugin/RobotUnitPlugin/RobotUnitPluginWidgetController.cpp b/source/RobotAPI/gui-plugins/RobotUnitPlugin/RobotUnitPlugin/RobotUnitPluginWidgetController.cpp
index 0d7911871493b5d79b86678631914ffd9f17da2b..0c4d6e2d110b42a09c4a4e934ed5d3828e33416c 100644
--- a/source/RobotAPI/gui-plugins/RobotUnitPlugin/RobotUnitPlugin/RobotUnitPluginWidgetController.cpp
+++ b/source/RobotAPI/gui-plugins/RobotUnitPlugin/RobotUnitPlugin/RobotUnitPluginWidgetController.cpp
@@ -108,7 +108,7 @@ void RobotUnitPluginWidgetController::onInitComponent()
 void RobotUnitPluginWidgetController::onConnectComponent()
 {
     robotUnitPrx = getProxy<RobotUnitInterfacePrx>(robotUnitProxyName);
-    listenerTopicName = robotUnitPrx->getListenerTopicName();
+    listenerTopicName = robotUnitPrx->getRobotUnitListenerTopicName();
     usingTopic(listenerTopicName);
     updateToolBarActionCheckedState();
     QMetaObject::invokeMethod(this, "startOnConnectTimer", Qt::QueuedConnection);
diff --git a/source/RobotAPI/interface/units/RobotUnit/RobotUnitInterface.ice b/source/RobotAPI/interface/units/RobotUnit/RobotUnitInterface.ice
index 49a8e8a19a8a1c83b72c96001a0e0dbdc8d3f520..f5906a1fc6a4ec9cd55d8a2819aab032782373a4 100644
--- a/source/RobotAPI/interface/units/RobotUnit/RobotUnitInterface.ice
+++ b/source/RobotAPI/interface/units/RobotUnit/RobotUnitInterface.ice
@@ -25,7 +25,8 @@
 #include <ArmarXCore/interface/core/UserException.ice>
 #include <ArmarXCore/interface/core/BasicTypes.ice>
 #include <ArmarXCore/interface/core/RemoteReferenceCount.ice>
-
+#include <ArmarXCore/interface/components/EmergencyStopInterface.ice>
+#include <ArmarXCore/interface/observers/ObserverInterface.ice>
 
 #include <ArmarXGui/interface/WidgetDescription.ice>
 
@@ -35,6 +36,10 @@
 #include <RobotAPI/interface/units/ForceTorqueUnit.ice>
 #include <RobotAPI/interface/units/InertialMeasurementUnit.ice>
 #include <RobotAPI/interface/units/PlatformUnitInterface.ice>
+#include <RobotAPI/interface/units/TCPControlUnit.ice>
+#include <RobotAPI/interface/components/TrajectoryPlayerInterface.ice>
+
+#include <RobotAPI/interface/visualization/DebugDrawerInterface.ice>
 
 module armarx
 {
@@ -90,84 +95,6 @@ module armarx
     };
     sequence<NJointControllerClassDescription> NJointControllerClassDescriptionSeq;
 
-    interface RobotUnitInterface
-    {
-        //controllers
-        //names
-        ["cpp:const"] idempotent Ice::StringSeq getNJointControllerNames();
-        ["cpp:const"] idempotent Ice::StringSeq getRequestedNJointControllerNames();
-        ["cpp:const"] idempotent Ice::StringSeq getActivatedNJointControllerNames();
-        //proxy/information
-        ["cpp:const"] idempotent NJointControllerInterface*               getNJointController(string name);
-        ["cpp:const"] idempotent StringNJointControllerPrxDictionary      getAllNJointControllers();
-
-        ["cpp:const"] idempotent NJointControllerStatus                   getNJointControllerStatus(string name) throws InvalidArgumentException;
-        ["cpp:const"] idempotent NJointControllerStatusSeq                getNJointControllerStatuses();
-
-        ["cpp:const"] idempotent NJointControllerDescription              getNJointControllerDescription(string name) throws InvalidArgumentException;
-        ["cpp:const"] idempotent NJointControllerDescriptionSeq           getNJointControllerDescriptions();
-
-        ["cpp:const"] idempotent NJointControllerDescriptionWithStatus    getNJointControllerDescriptionWithStatus(string name) throws InvalidArgumentException;
-        ["cpp:const"] idempotent NJointControllerDescriptionWithStatusSeq getNJointControllerDescriptionsWithStatuses();
-
-        //devices
-        ["cpp:const"] idempotent Ice::StringSeq                           getControlDeviceNames() throws LogicError;
-        ["cpp:const"] idempotent ControlDeviceDescription                 getControlDeviceDescription(string name) throws InvalidArgumentException, LogicError;
-        ["cpp:const"] idempotent ControlDeviceDescriptionSeq              getControlDeviceDescriptions() throws LogicError;
-        ["cpp:const"] idempotent ControlDeviceStatus                      getControlDeviceStatus(string name) throws InvalidArgumentException, LogicError;
-        ["cpp:const"] idempotent ControlDeviceStatusSeq                   getControlDeviceStatuses() throws LogicError;
-
-        ["cpp:const"] idempotent Ice::StringSeq                           getSensorDeviceNames() throws LogicError;
-        ["cpp:const"] idempotent SensorDeviceDescription                  getSensorDeviceDescription(string name) throws InvalidArgumentException, LogicError;
-        ["cpp:const"] idempotent SensorDeviceDescriptionSeq               getSensorDeviceDescriptions() throws LogicError;
-        ["cpp:const"] idempotent SensorDeviceStatus                       getSensorDeviceStatus(string name) throws InvalidArgumentException, LogicError;
-        ["cpp:const"] idempotent SensorDeviceStatusSeq                    getSensorDeviceStatuses() throws LogicError;
-        //classes
-        ["cpp:const"] idempotent Ice::StringSeq                           getNJointControllerClassNames();
-        ["cpp:const"] idempotent NJointControllerClassDescription         getNJointControllerClassDescription(string name) throws InvalidArgumentException;
-        ["cpp:const"] idempotent NJointControllerClassDescriptionSeq      getNJointControllerClassDescriptions();
-
-        //switching
-        void switchNJointControllerSetup(Ice::StringSeq newSetup) throws InvalidArgumentException, LogicError;
-
-        void activateNJointController(string controllerInstanceName) throws InvalidArgumentException, LogicError;
-        void activateNJointControllers(Ice::StringSeq controllerInstanceNames) throws InvalidArgumentException, LogicError;
-        void deactivateNJointController(string controllerInstanceName)throws InvalidArgumentException, LogicError;
-        void deactivateNJointControllers(Ice::StringSeq controllerInstanceNames)throws InvalidArgumentException, LogicError;
-
-        //creting controllers
-        NJointControllerInterface* createNJointController(string className, string instanceName, NJointControllerConfig config) throws InvalidArgumentException, LogicError;
-        NJointControllerInterface* createNJointControllerFromVariantConfig(string className, string instanceName, StringVariantBaseMap config) throws InvalidArgumentException, LogicError;
-        //deleting controllers
-        void deleteNJointController(string controllerInstanceName)throws InvalidArgumentException, LogicError;
-        void deleteNJointControllers(Ice::StringSeq controllerInstanceNames)throws InvalidArgumentException, LogicError;
-        //loading
-        bool loadLibFromPath(string path);
-        bool loadLibFromPackage(string package, string libname);
-
-        //units
-        ["cpp:const"] idempotent Object* getUnit(string staticIceId);
-        ["cpp:const"] idempotent Ice::ObjectProxySeq getUnits();
-        ["cpp:const"] idempotent KinematicUnitInterface* getKinematicUnit();
-        ["cpp:const"] idempotent ForceTorqueUnitInterface* getForceTorqueUnit();
-        ["cpp:const"] idempotent InertialMeasurementUnitInterface* getInertialMeasurementUnit();
-        ["cpp:const"] idempotent PlatformUnitInterface* getPlatformUnit();
-
-        //other
-        ["cpp:const"] idempotent string getListenerTopicName();
-        ["cpp:const"] idempotent bool isRunning();
-
-        //rt-logging
-        ["cpp:const"] idempotent bool isRtLoggingEnabled();
-        ["cpp:const"] idempotent Ice::StringSeq getLoggingNames();
-        RemoteReferenceCounterBase startRtLogging(string filePathFormatString, Ice::StringSeq loggingNames) throws LogicError, InvalidArgumentException;
-        RemoteReferenceCounterBase startRtLoggingWithAliasNames(string filePathFormatString, StringStringDictionary aliasNames) throws LogicError, InvalidArgumentException;
-        void addMarkerToRtLog(RemoteReferenceCounterBase token, string marker) throws LogicError;
-        void stopRtLogging(RemoteReferenceCounterBase token) throws LogicError;
-
-        ["cpp:const"] void writeRecentIterationsToFile(string filePathFormatString) throws LogicError, InvalidArgumentException;
-    };
-
     interface RobotUnitListener
     {
         void nJointControllerStatusChanged(NJointControllerStatus status);
@@ -177,5 +104,132 @@ module armarx
         void nJointControllerCreated(string instanceName);
         void nJointControllerDeleted(string instanceName);
     };
+
+    module RobotUnitModule
+    {
+        interface RobotUnitManagementInterface
+        {
+            //state
+            ["cpp:const"] idempotent bool isRunning();
+        };
+        interface RobotUnitLoggingInterface
+        {
+            //rt-logging
+            ["cpp:const"] idempotent Ice::StringSeq getLoggingNames();
+            RemoteReferenceCounterBase startRtLogging(string filePathFormatString, Ice::StringSeq loggingNames) throws LogicError, InvalidArgumentException;
+            RemoteReferenceCounterBase startRtLoggingWithAliasNames(string filePathFormatString, StringStringDictionary aliasNames) throws LogicError, InvalidArgumentException;
+            void addMarkerToRtLog(RemoteReferenceCounterBase token, string marker) throws LogicError;
+            void stopRtLogging(RemoteReferenceCounterBase token) throws LogicError;
+
+            ["cpp:const"] void writeRecentIterationsToFile(string filePathFormatString) throws LogicError, InvalidArgumentException;
+        };
+        interface RobotUnitUnitInterface
+        {
+            ["cpp:const"] idempotent Object* getUnit(string staticIceId);
+            ["cpp:const"] idempotent Ice::ObjectProxySeq getUnits();
+            ["cpp:const"] idempotent KinematicUnitInterface* getKinematicUnit();
+            ["cpp:const"] idempotent ForceTorqueUnitInterface* getForceTorqueUnit();
+            ["cpp:const"] idempotent InertialMeasurementUnitInterface* getInertialMeasurementUnit();
+            ["cpp:const"] idempotent PlatformUnitInterface* getPlatformUnit();
+            ["cpp:const"] idempotent TCPControlUnitInterface* getTCPControlUnit();
+            ["cpp:const"] idempotent TrajectoryPlayerInterface* getTrajectoryPlayer();
+
+
+
+        };
+        interface RobotUnitPublishingInterface
+        {
+            ["cpp:const"] idempotent string getRobotUnitListenerTopicName();
+            ["cpp:const"] idempotent string getDebugDrawerTopicName();
+            ["cpp:const"] idempotent string getDebugObserverTopicName();
+
+            ["cpp:const"] idempotent RobotUnitListener* getRobotUnitListenerProxy();
+            ["cpp:const"] idempotent DebugDrawerInterface* getDebugDrawerProxy();
+            ["cpp:const"] idempotent DebugObserverInterface* getDebugObserverProxy();
+        };
+        interface RobotUnitDevicesInterface
+        {
+            //devices
+            ["cpp:const"] idempotent Ice::StringSeq                           getControlDeviceNames() throws LogicError;
+            ["cpp:const"] idempotent ControlDeviceDescription                 getControlDeviceDescription(string name) throws InvalidArgumentException, LogicError;
+            ["cpp:const"] idempotent ControlDeviceDescriptionSeq              getControlDeviceDescriptions() throws LogicError;
+            ["cpp:const"] idempotent ControlDeviceStatus                      getControlDeviceStatus(string name) throws InvalidArgumentException, LogicError;
+            ["cpp:const"] idempotent ControlDeviceStatusSeq                   getControlDeviceStatuses() throws LogicError;
+
+            ["cpp:const"] idempotent Ice::StringSeq                           getSensorDeviceNames() throws LogicError;
+            ["cpp:const"] idempotent SensorDeviceDescription                  getSensorDeviceDescription(string name) throws InvalidArgumentException, LogicError;
+            ["cpp:const"] idempotent SensorDeviceDescriptionSeq               getSensorDeviceDescriptions() throws LogicError;
+            ["cpp:const"] idempotent SensorDeviceStatus                       getSensorDeviceStatus(string name) throws InvalidArgumentException, LogicError;
+            ["cpp:const"] idempotent SensorDeviceStatusSeq                    getSensorDeviceStatuses() throws LogicError;
+        };
+        interface RobotUnitControllerManagementInterface
+        {
+            //names
+            ["cpp:const"] idempotent Ice::StringSeq getNJointControllerNames();
+            ["cpp:const"] idempotent Ice::StringSeq getRequestedNJointControllerNames();
+            ["cpp:const"] idempotent Ice::StringSeq getActivatedNJointControllerNames();
+            //proxy/information
+            ["cpp:const"] idempotent NJointControllerInterface*               getNJointController(string name);
+            ["cpp:const"] idempotent StringNJointControllerPrxDictionary      getAllNJointControllers();
+
+            ["cpp:const"] idempotent NJointControllerStatus                   getNJointControllerStatus(string name) throws InvalidArgumentException;
+            ["cpp:const"] idempotent NJointControllerStatusSeq                getNJointControllerStatuses();
+
+            ["cpp:const"] idempotent NJointControllerDescription              getNJointControllerDescription(string name) throws InvalidArgumentException;
+            ["cpp:const"] idempotent NJointControllerDescriptionSeq           getNJointControllerDescriptions();
+
+            ["cpp:const"] idempotent NJointControllerDescriptionWithStatus    getNJointControllerDescriptionWithStatus(string name) throws InvalidArgumentException;
+            ["cpp:const"] idempotent NJointControllerDescriptionWithStatusSeq getNJointControllerDescriptionsWithStatuses();
+
+            //classes
+            ["cpp:const"] idempotent Ice::StringSeq                           getNJointControllerClassNames();
+            ["cpp:const"] idempotent NJointControllerClassDescription         getNJointControllerClassDescription(string name) throws InvalidArgumentException;
+            ["cpp:const"] idempotent NJointControllerClassDescriptionSeq      getNJointControllerClassDescriptions();
+
+            //switching
+            void switchNJointControllerSetup(Ice::StringSeq newSetup) throws InvalidArgumentException, LogicError;
+
+            void activateNJointController(string controllerInstanceName) throws InvalidArgumentException, LogicError;
+            void activateNJointControllers(Ice::StringSeq controllerInstanceNames) throws InvalidArgumentException, LogicError;
+            void deactivateNJointController(string controllerInstanceName)throws InvalidArgumentException, LogicError;
+            void deactivateNJointControllers(Ice::StringSeq controllerInstanceNames)throws InvalidArgumentException, LogicError;
+            //creting controllers
+            NJointControllerInterface* createNJointController(string className, string instanceName, NJointControllerConfig config) throws InvalidArgumentException, LogicError;
+            NJointControllerInterface* createNJointControllerFromVariantConfig(string className, string instanceName, StringVariantBaseMap config) throws InvalidArgumentException, LogicError;
+            //deleting controllers
+            void deleteNJointController(string controllerInstanceName)throws InvalidArgumentException, LogicError;
+            void deleteNJointControllers(Ice::StringSeq controllerInstanceNames)throws InvalidArgumentException, LogicError;
+
+            //loading libs
+            bool loadLibFromPath(string path);
+            bool loadLibFromPackage(string package, string libname);
+        };
+        interface RobotUnitSelfCollisionCheckerInterface
+        {
+            ["cpp:const"] idempotent bool isSelfCollisionCheckEnabled();
+            ["cpp:const"] idempotent float getSelfCollisionAvoidanceFrequency();
+            ["cpp:const"] idempotent float getSelfCollisionAvoidanceDistance();
+            idempotent void setSelfCollisionAvoidanceFrequency(float freq);
+            idempotent void setSelfCollisionAvoidanceDistance(float dist);
+        };
+        interface RobotUnitControlThreadInterface
+        {
+            idempotent void setEmergencyStopState(EmergencyStopState state);
+            ["cpp:const"] idempotent EmergencyStopState getEmergencyStopState();
+            ["cpp:const"] idempotent EmergencyStopState getRtEmergencyStopState();
+        };
+    };
+
+    interface RobotUnitInterface extends
+            RobotUnitModule::RobotUnitUnitInterface,
+            RobotUnitModule::RobotUnitDevicesInterface,
+            RobotUnitModule::RobotUnitLoggingInterface,
+            RobotUnitModule::RobotUnitPublishingInterface,
+            RobotUnitModule::RobotUnitManagementInterface,
+            RobotUnitModule::RobotUnitControlThreadInterface,
+            RobotUnitModule::RobotUnitControllerManagementInterface,
+            RobotUnitModule::RobotUnitSelfCollisionCheckerInterface
+    {
+    };
 };
 
diff --git a/source/RobotAPI/interface/units/TCPControlUnit.ice b/source/RobotAPI/interface/units/TCPControlUnit.ice
index 4e395feea18ae927ce31752a31f64f6e96b7558f..36d0bdf75b3ddde0c8b5a7535a785ed31810aca2 100644
--- a/source/RobotAPI/interface/units/TCPControlUnit.ice
+++ b/source/RobotAPI/interface/units/TCPControlUnit.ice
@@ -92,4 +92,3 @@ module armarx
     };
 
 };
-
diff --git a/source/RobotAPI/libraries/RobotAPINJointControllers/CMakeLists.txt b/source/RobotAPI/libraries/RobotAPINJointControllers/CMakeLists.txt
index 1d2c433b93afb51f8d5b3aba5788440fb6c7f0a9..5b48d4fe03f9d108934a8a5854d23f234d75f4c4 100644
--- a/source/RobotAPI/libraries/RobotAPINJointControllers/CMakeLists.txt
+++ b/source/RobotAPI/libraries/RobotAPINJointControllers/CMakeLists.txt
@@ -7,7 +7,8 @@ find_package(Eigen3 QUIET)
 find_package(Simox ${ArmarX_Simox_VERSION} QUIET)
 find_package(DMP QUIET)
 find_package(MMMCore QUIET)
-find_package(MMMToolsQUIET)
+find_package(MMMTools QUIET)
+find_package(IVT QUIET)
 
 armarx_build_if(Eigen3_FOUND "Eigen3 not available")
 armarx_build_if(Simox_FOUND "Simox-VirtualRobot not available")
diff --git a/source/RobotAPI/libraries/RobotAPINJointControllers/DMPController/NJointCCDMPController.cpp b/source/RobotAPI/libraries/RobotAPINJointControllers/DMPController/NJointCCDMPController.cpp
index c00253ed7a2524d5e6d8a591754f458ef2649168..46cda82c25f0d6d0b4db74b101c05a4ab5d44562 100644
--- a/source/RobotAPI/libraries/RobotAPINJointControllers/DMPController/NJointCCDMPController.cpp
+++ b/source/RobotAPI/libraries/RobotAPINJointControllers/DMPController/NJointCCDMPController.cpp
@@ -4,21 +4,21 @@ namespace armarx
 {
     NJointControllerRegistration<NJointCCDMPController> registrationControllerNJointCCDMPController("NJointCCDMPController");
 
-    NJointCCDMPController::NJointCCDMPController(armarx::NJointControllerDescriptionProviderInterfacePtr prov, const armarx::NJointControllerConfigPtr& config, const VirtualRobot::RobotPtr&)
+    NJointCCDMPController::NJointCCDMPController(const RobotUnitPtr&, const armarx::NJointControllerConfigPtr& config, const VirtualRobot::RobotPtr&)
     {
+        useSynchronizedRtRobot();
         cfg = NJointCCDMPControllerConfigPtr::dynamicCast(config);
-        ARMARX_CHECK_EXPRESSION(prov);
-        RobotUnitPtr robotUnit = RobotUnitPtr::dynamicCast(prov);
-        ARMARX_CHECK_EXPRESSION(robotUnit);
+        ARMARX_CHECK_NOT_NULL(cfg);
+        ARMARX_CHECK_GREATER_EQUAL(cfg->dmpNum, 0);
         ARMARX_CHECK_EXPRESSION(!cfg->nodeSetName.empty());
-        VirtualRobot::RobotNodeSetPtr rns = robotUnit->getRtRobot()->getRobotNodeSet(cfg->nodeSetName);
+        VirtualRobot::RobotNodeSetPtr rns = rtGetRobot()->getRobotNodeSet(cfg->nodeSetName);
 
         ARMARX_CHECK_EXPRESSION_W_HINT(rns, cfg->nodeSetName);
         for (size_t i = 0; i < rns->getSize(); ++i)
         {
             std::string jointName = rns->getNode(i)->getName();
-            ControlTargetBase* ct = prov->getControlTarget(jointName, ControlModes::Velocity1DoF);
-            const SensorValueBase* sv = prov->getSensorValue(jointName);
+            ControlTargetBase* ct = useControlTarget(jointName, ControlModes::Velocity1DoF);
+            const SensorValueBase* sv = useSensorValue(jointName);
             targets.push_back(ct->asA<ControlTarget1DoFActuatorVelocity>());
 
             const SensorValue1DoFActuatorTorque* torqueSensor = sv->asA<SensorValue1DoFActuatorTorque>();
@@ -36,7 +36,7 @@ namespace armarx
             gravityTorqueSensors.push_back(gravityTorqueSensor);
         };
 
-        tcp = (cfg->tcpName.empty()) ? rns->getTCP() : robotUnit->getRtRobot()->getRobotNode(cfg->tcpName);
+        tcp = (cfg->tcpName.empty()) ? rns->getTCP() : rtGetRobot()->getRobotNode(cfg->tcpName);
         ARMARX_CHECK_EXPRESSION_W_HINT(tcp, cfg->tcpName);
 
         // set tcp controller
@@ -168,20 +168,20 @@ namespace armarx
 
         // run DMP one after another
         Eigen::Matrix4f targetPose = Eigen::Matrix4f::Identity();
-        bool finished = true;
-        for (size_t i = 0; i < cfg->dmpNum; ++i)
+        //bool finished = true;
+        for (size_t i = 0; i < static_cast<size_t>(cfg->dmpNum); ++i)
         {
             double timeDuration = timeDurations[i];
             std::string dmpType = dmpTypes[i];
 
-            double amplitude = 1.0;
+            //double amplitude = 1.0;
             if (dmpType == "Periodic")
             {
                 if (canVals[i] <= 1e-8)
                 {
                     canVals[i] = timeDuration;
                 }
-                amplitude = amplitudes[i];
+                //amplitude = amplitudes[i];
             }
 
             if (canVals[i] > 1e-8)
@@ -196,7 +196,7 @@ namespace armarx
                                    (currentStates[i], canVals[i] / timeDurations[i], dmpDeltaT, targetSubStates[i]);
 
 
-                finished = false;
+                //finished = false;
 
             }
 
@@ -500,14 +500,14 @@ namespace armarx
     void NJointCCDMPController::runDMP(const Ice::Current&)
     {
 
+        const auto dmpNum = static_cast<std::size_t>(cfg->dmpNum);
         finished = false;
-
-        if (dmpTypes.size() != cfg->dmpNum ||
-            dmpPtrList.size() != cfg->dmpNum ||
-            learnedDMP.size() != cfg->dmpNum ||
-            canVals.size() != cfg->dmpNum ||
-            currentStates.size() != cfg->dmpNum ||
-            targetSubStates.size() != cfg->dmpNum)
+        if (dmpNum != dmpTypes.size()      ||
+            dmpNum != dmpPtrList.size()    ||
+            dmpNum != learnedDMP.size()    ||
+            dmpNum != canVals.size()       ||
+            dmpNum != currentStates.size() ||
+            dmpNum != targetSubStates.size())
         {
             ARMARX_ERROR << "Error: cannot run CCDMP controller. The reason is that some parameters have different sizes";
             return;
diff --git a/source/RobotAPI/libraries/RobotAPINJointControllers/DMPController/NJointCCDMPController.h b/source/RobotAPI/libraries/RobotAPINJointControllers/DMPController/NJointCCDMPController.h
index 7dc42afd1e8c99b9a5d269727cec270753abfc5c..e3917f63cf874b8b1b08f6922dd66f08f4da6821 100644
--- a/source/RobotAPI/libraries/RobotAPINJointControllers/DMPController/NJointCCDMPController.h
+++ b/source/RobotAPI/libraries/RobotAPINJointControllers/DMPController/NJointCCDMPController.h
@@ -54,7 +54,7 @@ namespace armarx
     {
     public:
         using ConfigPtrT = NJointCCDMPControllerConfigPtr;
-        NJointCCDMPController(NJointControllerDescriptionProviderInterfacePtr prov, const NJointControllerConfigPtr& config, const VirtualRobot::RobotPtr&);
+        NJointCCDMPController(const RobotUnitPtr& robotUnit, const NJointControllerConfigPtr& config, const VirtualRobot::RobotPtr&);
 
         // NJointControllerInterface interface
         std::string getClassName(const Ice::Current&) const;
diff --git a/source/RobotAPI/libraries/RobotAPINJointControllers/DMPController/NJointJSDMPController.cpp b/source/RobotAPI/libraries/RobotAPINJointControllers/DMPController/NJointJSDMPController.cpp
index bcf0d7893db6d82964c70cd456f85a2803e4f2b7..3bd5872a9f85027aa46b7b042a61f5d4d732fdb5 100644
--- a/source/RobotAPI/libraries/RobotAPINJointControllers/DMPController/NJointJSDMPController.cpp
+++ b/source/RobotAPI/libraries/RobotAPINJointControllers/DMPController/NJointJSDMPController.cpp
@@ -12,15 +12,15 @@ namespace armarx
         return "NJointJSDMPController";
     }
 
-    NJointJSDMPController::NJointJSDMPController(armarx::NJointControllerDescriptionProviderInterfacePtr prov, const armarx::NJointControllerConfigPtr& config, const VirtualRobot::RobotPtr&)
+    NJointJSDMPController::NJointJSDMPController(const RobotUnitPtr&, const armarx::NJointControllerConfigPtr& config, const VirtualRobot::RobotPtr&)
     {
         NJointJointSpaceDMPControllerConfigPtr cfg = NJointJointSpaceDMPControllerConfigPtr::dynamicCast(config);
         ARMARX_CHECK_EXPRESSION_W_HINT(cfg, "Needed type: NJointJointSpaceDMPControllerConfigPtr");
 
         for (std::string jointName : cfg->jointNames)
         {
-            ControlTargetBase* ct = prov->getControlTarget(jointName, ControlModes::Velocity1DoF);
-            const SensorValueBase* sv = prov->getSensorValue(jointName);
+            ControlTargetBase* ct = useControlTarget(jointName, ControlModes::Velocity1DoF);
+            const SensorValueBase* sv = useSensorValue(jointName);
             targets.insert(std::make_pair(jointName, ct->asA<ControlTarget1DoFActuatorVelocity>()));
             positionSensors.insert(std::make_pair(jointName, sv->asA<SensorValue1DoFActuatorPosition>()));
             torqueSensors.insert(std::make_pair(jointName, sv->asA<SensorValue1DoFActuatorTorque>()));
diff --git a/source/RobotAPI/libraries/RobotAPINJointControllers/DMPController/NJointJSDMPController.h b/source/RobotAPI/libraries/RobotAPINJointControllers/DMPController/NJointJSDMPController.h
index 625058be3fa1a6d22047392e6cd4dce582590afc..3b904713a90d8190b0691b2ce5d0250a5262e6ed 100644
--- a/source/RobotAPI/libraries/RobotAPINJointControllers/DMPController/NJointJSDMPController.h
+++ b/source/RobotAPI/libraries/RobotAPINJointControllers/DMPController/NJointJSDMPController.h
@@ -38,7 +38,7 @@ namespace armarx
     {
     public:
         using ConfigPtrT = NJointJointSpaceDMPControllerConfigPtr;
-        NJointJSDMPController(NJointControllerDescriptionProviderInterfacePtr prov, const NJointControllerConfigPtr& config, const VirtualRobot::RobotPtr&);
+        NJointJSDMPController(const RobotUnitPtr& robotUnit, const NJointControllerConfigPtr& config, const VirtualRobot::RobotPtr&);
 
         // NJointControllerInterface interface
         std::string getClassName(const Ice::Current&) const override;
diff --git a/source/RobotAPI/libraries/RobotAPINJointControllers/DMPController/NJointJointSpaceDMPController.cpp b/source/RobotAPI/libraries/RobotAPINJointControllers/DMPController/NJointJointSpaceDMPController.cpp
index 0626c1976c4bfe8f6b5de2eed7ba0298006a65f2..ac8005eba8c70cdfce5aa45d80bd189ef06f15c5 100644
--- a/source/RobotAPI/libraries/RobotAPINJointControllers/DMPController/NJointJointSpaceDMPController.cpp
+++ b/source/RobotAPI/libraries/RobotAPINJointControllers/DMPController/NJointJointSpaceDMPController.cpp
@@ -12,15 +12,15 @@ namespace armarx
         return "NJointJointSpaceDMPController";
     }
 
-    NJointJointSpaceDMPController::NJointJointSpaceDMPController(armarx::NJointControllerDescriptionProviderInterfacePtr prov, const armarx::NJointControllerConfigPtr& config, const VirtualRobot::RobotPtr&)
+    NJointJointSpaceDMPController::NJointJointSpaceDMPController(armarx::RobotUnitPtr prov, const armarx::NJointControllerConfigPtr& config, const VirtualRobot::RobotPtr&)
     {
         NJointJointSpaceDMPControllerConfigPtr cfg = NJointJointSpaceDMPControllerConfigPtr::dynamicCast(config);
         ARMARX_CHECK_EXPRESSION_W_HINT(cfg, "Needed type: NJointJointSpaceDMPControllerConfigPtr");
 
         for (std::string jointName : cfg->jointNames)
         {
-            ControlTargetBase* ct = prov->getControlTarget(jointName, ControlModes::Velocity1DoF);
-            const SensorValueBase* sv = prov->getSensorValue(jointName);
+            ControlTargetBase* ct = useControlTarget(jointName, ControlModes::Velocity1DoF);
+            const SensorValueBase* sv = useSensorValue(jointName);
             targets.insert(std::make_pair(jointName, ct->asA<ControlTarget1DoFActuatorVelocity>()));
             positionSensors.insert(std::make_pair(jointName, sv->asA<SensorValue1DoFActuatorPosition>()));
             torqueSensors.insert(std::make_pair(jointName, sv->asA<SensorValue1DoFActuatorTorque>()));
diff --git a/source/RobotAPI/libraries/RobotAPINJointControllers/DMPController/NJointJointSpaceDMPController.h b/source/RobotAPI/libraries/RobotAPINJointControllers/DMPController/NJointJointSpaceDMPController.h
index 173c7cfb146f2117b2c6a8df498baffa2eb21477..a4097a0ab06c4ce7d084af4e267ffe2360dceb8c 100644
--- a/source/RobotAPI/libraries/RobotAPINJointControllers/DMPController/NJointJointSpaceDMPController.h
+++ b/source/RobotAPI/libraries/RobotAPINJointControllers/DMPController/NJointJointSpaceDMPController.h
@@ -38,7 +38,7 @@ namespace armarx
     {
     public:
         using ConfigPtrT = NJointJointSpaceDMPControllerConfigPtr;
-        NJointJointSpaceDMPController(NJointControllerDescriptionProviderInterfacePtr prov, const NJointControllerConfigPtr& config, const VirtualRobot::RobotPtr&);
+        NJointJointSpaceDMPController(RobotUnitPtr prov, const NJointControllerConfigPtr& config, const VirtualRobot::RobotPtr&);
 
         // NJointControllerInterface interface
         std::string getClassName(const Ice::Current&) const override;
diff --git a/source/RobotAPI/libraries/RobotAPINJointControllers/DMPController/NJointTSDMPController.cpp b/source/RobotAPI/libraries/RobotAPINJointControllers/DMPController/NJointTSDMPController.cpp
index 9dfb86763888c436e53384b6019d849582d9c966..2f95ef4b734ac289e4c84b6f11c4b27f426170b9 100644
--- a/source/RobotAPI/libraries/RobotAPINJointControllers/DMPController/NJointTSDMPController.cpp
+++ b/source/RobotAPI/libraries/RobotAPINJointControllers/DMPController/NJointTSDMPController.cpp
@@ -4,21 +4,19 @@ namespace armarx
 {
     NJointControllerRegistration<NJointTSDMPController> registrationControllerNJointTSDMPController("NJointTSDMPController");
 
-    NJointTSDMPController::NJointTSDMPController(armarx::NJointControllerDescriptionProviderInterfacePtr prov, const armarx::NJointControllerConfigPtr& config, const VirtualRobot::RobotPtr&)
+    NJointTSDMPController::NJointTSDMPController(const RobotUnitPtr&, const armarx::NJointControllerConfigPtr& config, const VirtualRobot::RobotPtr&)
     {
+        useSynchronizedRtRobot();
         cfg = NJointTaskSpaceDMPControllerConfigPtr::dynamicCast(config);
-        ARMARX_CHECK_EXPRESSION(prov);
-        RobotUnitPtr robotUnit = RobotUnitPtr::dynamicCast(prov);
-        ARMARX_CHECK_EXPRESSION(robotUnit);
         ARMARX_CHECK_EXPRESSION(!cfg->nodeSetName.empty());
-        VirtualRobot::RobotNodeSetPtr rns = robotUnit->getRtRobot()->getRobotNodeSet(cfg->nodeSetName);
+        VirtualRobot::RobotNodeSetPtr rns = rtGetRobot()->getRobotNodeSet(cfg->nodeSetName);
 
         ARMARX_CHECK_EXPRESSION_W_HINT(rns, cfg->nodeSetName);
         for (size_t i = 0; i < rns->getSize(); ++i)
         {
             std::string jointName = rns->getNode(i)->getName();
-            ControlTargetBase* ct = prov->getControlTarget(jointName, ControlModes::Velocity1DoF);
-            const SensorValueBase* sv = prov->getSensorValue(jointName);
+            ControlTargetBase* ct = useControlTarget(jointName, ControlModes::Velocity1DoF);
+            const SensorValueBase* sv = useSensorValue(jointName);
             targets.push_back(ct->asA<ControlTarget1DoFActuatorVelocity>());
 
             const SensorValue1DoFActuatorTorque* torqueSensor = sv->asA<SensorValue1DoFActuatorTorque>();
@@ -36,7 +34,7 @@ namespace armarx
             gravityTorqueSensors.push_back(gravityTorqueSensor);
         };
 
-        tcp = (cfg->tcpName.empty()) ? rns->getTCP() : robotUnit->getRtRobot()->getRobotNode(cfg->tcpName);
+        tcp = (cfg->tcpName.empty()) ? rns->getTCP() : rtGetRobot()->getRobotNode(cfg->tcpName);
         ARMARX_CHECK_EXPRESSION_W_HINT(tcp, cfg->tcpName);
 
         // set tcp controller
diff --git a/source/RobotAPI/libraries/RobotAPINJointControllers/DMPController/NJointTSDMPController.h b/source/RobotAPI/libraries/RobotAPINJointControllers/DMPController/NJointTSDMPController.h
index 620b5c81145b5fb4be3755ad37bdf48c19ed5924..a072119a1b2fd8bf15ceb305f1e3397026474d10 100644
--- a/source/RobotAPI/libraries/RobotAPINJointControllers/DMPController/NJointTSDMPController.h
+++ b/source/RobotAPI/libraries/RobotAPINJointControllers/DMPController/NJointTSDMPController.h
@@ -54,7 +54,7 @@ namespace armarx
     {
     public:
         using ConfigPtrT = NJointTaskSpaceDMPControllerConfigPtr;
-        NJointTSDMPController(NJointControllerDescriptionProviderInterfacePtr prov, const NJointControllerConfigPtr& config, const VirtualRobot::RobotPtr&);
+        NJointTSDMPController(const RobotUnitPtr&, const NJointControllerConfigPtr& config, const VirtualRobot::RobotPtr&);
 
         // NJointControllerInterface interface
         std::string getClassName(const Ice::Current&) const;
diff --git a/source/RobotAPI/libraries/RobotAPINJointControllers/DMPController/NJointTaskSpaceDMPController.cpp b/source/RobotAPI/libraries/RobotAPINJointControllers/DMPController/NJointTaskSpaceDMPController.cpp
index f7a2de6fee95c7a188cd816158d88836c974e9c2..a210d04f27abcfafd3dcd73eef9a697ad77e02bb 100644
--- a/source/RobotAPI/libraries/RobotAPINJointControllers/DMPController/NJointTaskSpaceDMPController.cpp
+++ b/source/RobotAPI/libraries/RobotAPINJointControllers/DMPController/NJointTaskSpaceDMPController.cpp
@@ -4,21 +4,19 @@ namespace armarx
 {
     NJointControllerRegistration<NJointTaskSpaceDMPController> registrationControllerNJointTaskSpaceDMPController("NJointTaskSpaceDMPController");
 
-    NJointTaskSpaceDMPController::NJointTaskSpaceDMPController(armarx::NJointControllerDescriptionProviderInterfacePtr prov, const armarx::NJointControllerConfigPtr& config, const VirtualRobot::RobotPtr&)
+    NJointTaskSpaceDMPController::NJointTaskSpaceDMPController(const RobotUnitPtr& robotUnit, const armarx::NJointControllerConfigPtr& config, const VirtualRobot::RobotPtr&)
     {
+        useSynchronizedRtRobot();
         cfg = NJointTaskSpaceDMPControllerConfigPtr::dynamicCast(config);
-        ARMARX_CHECK_EXPRESSION(prov);
-        RobotUnitPtr robotUnit = RobotUnitPtr::dynamicCast(prov);
-        ARMARX_CHECK_EXPRESSION(robotUnit);
         ARMARX_CHECK_EXPRESSION(!cfg->nodeSetName.empty());
-        VirtualRobot::RobotNodeSetPtr rns = robotUnit->getRtRobot()->getRobotNodeSet(cfg->nodeSetName);
+        VirtualRobot::RobotNodeSetPtr rns = rtGetRobot()->getRobotNodeSet(cfg->nodeSetName);
 
         ARMARX_CHECK_EXPRESSION_W_HINT(rns, cfg->nodeSetName);
         for (size_t i = 0; i < rns->getSize(); ++i)
         {
             std::string jointName = rns->getNode(i)->getName();
-            ControlTargetBase* ct = prov->getControlTarget(jointName, ControlModes::Velocity1DoF);
-            const SensorValueBase* sv = prov->getSensorValue(jointName);
+            ControlTargetBase* ct = useControlTarget(jointName, ControlModes::Velocity1DoF);
+            const SensorValueBase* sv = useSensorValue(jointName);
             targets.push_back(ct->asA<ControlTarget1DoFActuatorVelocity>());
 
             const SensorValue1DoFActuatorTorque* torqueSensor = sv->asA<SensorValue1DoFActuatorTorque>();
@@ -36,7 +34,7 @@ namespace armarx
             gravityTorqueSensors.push_back(gravityTorqueSensor);
         };
 
-        tcp = (cfg->tcpName.empty()) ? rns->getTCP() : robotUnit->getRtRobot()->getRobotNode(cfg->tcpName);
+        tcp = (cfg->tcpName.empty()) ? rns->getTCP() : rtGetRobot()->getRobotNode(cfg->tcpName);
         ARMARX_CHECK_EXPRESSION_W_HINT(tcp, cfg->tcpName);
 
         // set tcp controller
diff --git a/source/RobotAPI/libraries/RobotAPINJointControllers/DMPController/NJointTaskSpaceDMPController.h b/source/RobotAPI/libraries/RobotAPINJointControllers/DMPController/NJointTaskSpaceDMPController.h
index b5f3fa66e39c20002747e7e02372e7f45c5aed86..edcb07cffe543ca68bd7505c501bbd705954ca85 100644
--- a/source/RobotAPI/libraries/RobotAPINJointControllers/DMPController/NJointTaskSpaceDMPController.h
+++ b/source/RobotAPI/libraries/RobotAPINJointControllers/DMPController/NJointTaskSpaceDMPController.h
@@ -57,7 +57,7 @@ namespace armarx
     {
     public:
         using ConfigPtrT = NJointTaskSpaceDMPControllerConfigPtr;
-        NJointTaskSpaceDMPController(NJointControllerDescriptionProviderInterfacePtr prov, const NJointControllerConfigPtr& config, const VirtualRobot::RobotPtr&);
+        NJointTaskSpaceDMPController(const RobotUnitPtr& robotUnit, const NJointControllerConfigPtr& config, const VirtualRobot::RobotPtr&);
 
         // NJointControllerInterface interface
         std::string getClassName(const Ice::Current&) const;