diff --git a/source/RobotAPI/components/ArViz/Coin/VisualizationRobot.cpp b/source/RobotAPI/components/ArViz/Coin/VisualizationRobot.cpp
index 7c466cdacab7c4a95862d2a7e9508d2d8dda450f..0e2ae813fbef99c1ce24e35c8be0be63deeeff8b 100644
--- a/source/RobotAPI/components/ArViz/Coin/VisualizationRobot.cpp
+++ b/source/RobotAPI/components/ArViz/Coin/VisualizationRobot.cpp
@@ -110,7 +110,7 @@ namespace armarx::viz::coin
                            << "\nFilename: " << element.filename;
             return true;
         }
-        IceUtil::Time time_load = IceUtil::Time::now();
+        //IceUtil::Time time_load = IceUtil::Time::now();
 
         bool drawStyleChanged = loadedDrawStyle != element.drawStyle;
         if (robotChanged || drawStyleChanged)
@@ -118,7 +118,7 @@ namespace armarx::viz::coin
             recreateVisualizationNodes(element.drawStyle);
             loadedDrawStyle = element.drawStyle;
         }
-        IceUtil::Time time_style = IceUtil::Time::now();
+        //IceUtil::Time time_style = IceUtil::Time::now();
 
         // Set pose, configuration and so on
 
@@ -132,33 +132,40 @@ namespace armarx::viz::coin
         // robot.setGlobalPose(pose, false);
 
         robot.setJointValues(element.jointValues);
-        IceUtil::Time time_set = IceUtil::Time::now();
+        //IceUtil::Time time_set = IceUtil::Time::now();
 
         if (loadedDrawStyle & data::ModelDrawStyle::OVERRIDE_COLOR)
         {
-            int numChildren = node->getNumChildren();
-            for (int i = 0; i < numChildren; i++)
+            if (loadedColor.r != element.color.r
+                    || loadedColor.g != element.color.g
+                    || loadedColor.b != element.color.b
+                    || loadedColor.a != element.color.a)
             {
-                SoSeparator* nodeSep = static_cast<SoSeparator*>(node->getChild(i));
-                // The first entry must be a SoMaterial (see recreateVisualizationNodes)
-                SoMaterial* m = dynamic_cast<SoMaterial*>(nodeSep->getChild(0));
-                if (!m)
+                int numChildren = node->getNumChildren();
+                for (int i = 0; i < numChildren; i++)
                 {
-                    ARMARX_WARNING << "Error at node with index: " << i;
-                    continue;
+                    SoSeparator* nodeSep = static_cast<SoSeparator*>(node->getChild(i));
+                    // The first entry must be a SoMaterial (see recreateVisualizationNodes)
+                    SoMaterial* m = dynamic_cast<SoMaterial*>(nodeSep->getChild(0));
+                    if (!m)
+                    {
+                        ARMARX_WARNING << "Error at node with index: " << i;
+                        continue;
+                    }
+
+                    auto color = element.color;
+                    const float conv = 1.0f / 255.0f;
+                    float a = color.a * conv;
+                    SbColor coinColor(conv * color.r, conv * color.g, conv * color.b);
+                    m->diffuseColor = coinColor;
+                    m->ambientColor = coinColor;
+                    m->transparency = 1.0f - a;
+                    m->setOverride(true);
                 }
-
-                auto color = element.color;
-                const float conv = 1.0f / 255.0f;
-                float a = color.a * conv;
-                SbColor coinColor(conv * color.r, conv * color.g, conv * color.b);
-                m->diffuseColor = coinColor;
-                m->ambientColor = coinColor;
-                m->transparency = 1.0f - a;
-                m->setOverride(true);
+                loadedColor = element.color;
             }
         }
-        IceUtil::Time time_color = IceUtil::Time::now();
+        //IceUtil::Time time_color = IceUtil::Time::now();
 
         // Setting the joint angles takes > 0.5 ms! This is unexpected...
         //        ARMARX_INFO << "Total:   " << (time_color - time_start).toMilliSecondsDouble()
diff --git a/source/RobotAPI/components/ArViz/Coin/VisualizationRobot.h b/source/RobotAPI/components/ArViz/Coin/VisualizationRobot.h
index cb6699735a40b1783bb0e09270891910514278da..63aa3f1f8cabf92029b1d1b763d808f9b2123d77 100644
--- a/source/RobotAPI/components/ArViz/Coin/VisualizationRobot.h
+++ b/source/RobotAPI/components/ArViz/Coin/VisualizationRobot.h
@@ -25,6 +25,7 @@ namespace armarx::viz::coin
 
         LoadedRobot loaded;
         int loadedDrawStyle = data::ModelDrawStyle::ORIGINAL;
+        armarx::viz::data::Color loadedColor{0, 0, 0, 0};
     };
 
     void clearRobotCache();
diff --git a/source/RobotAPI/components/ArViz/Coin/Visualizer.cpp b/source/RobotAPI/components/ArViz/Coin/Visualizer.cpp
index f11c7aa9de6672cafcda2bbcfdb2e5114eb2be69..692800bc7d85488b4af3dc7090c6efabde509911 100644
--- a/source/RobotAPI/components/ArViz/Coin/Visualizer.cpp
+++ b/source/RobotAPI/components/ArViz/Coin/Visualizer.cpp
@@ -143,8 +143,8 @@ namespace armarx::viz
             layerIt = layers.emplace(layerID, CoinLayer(coinNode)).first;
         }
 
-        IceUtil::Time time_start1 = IceUtil::Time::now();
-        IceUtil::Time time_start = IceUtil::Time::now();
+        //IceUtil::Time time_start1 = IceUtil::Time::now();
+        //IceUtil::Time time_start = IceUtil::Time::now();
 
         // Add or update the elements in the update
         CoinLayer& layer = layerIt->second;
@@ -171,10 +171,10 @@ namespace armarx::viz
                 continue;
             }
             coin::ElementVisualizer* visualizer = elementVisualizers[visuIndex].get();
-            IceUtil::Time time_findVisu = IceUtil::Time::now();
+            //IceUtil::Time time_findVisu = IceUtil::Time::now();
 
             auto oldElementIter = layer.elements.find(updatedElement.id);
-            IceUtil::Time time_findElement = IceUtil::Time::now();
+            //IceUtil::Time time_findElement = IceUtil::Time::now();
             if (oldElementIter != layer.elements.end())
             {
                 // Element already exists
@@ -238,7 +238,7 @@ namespace armarx::viz
                 iter = layer.elements.erase(iter);
             }
         }
-        IceUtil::Time time_remove = IceUtil::Time::now();
+        //IceUtil::Time time_remove = IceUtil::Time::now();
 
         //        if (update.name == "Example")
         //        {
@@ -290,7 +290,7 @@ namespace armarx::viz
         {
             case CoinVisualizerUpdateResult::SUCCESS:
             {
-                IceUtil::Time time_start = IceUtil::Time::now();
+                //IceUtil::Time time_start = IceUtil::Time::now();
 
                 // We should restart the pull for updates so it can run in parallel
                 data::LayerUpdates currentUpdates = pulledUpdates;
@@ -299,20 +299,20 @@ namespace armarx::viz
 
                 auto layerIDsBefore = getLayerIDs();
 
-                IceUtil::Time time_afterPull = IceUtil::Time::now();
+                //IceUtil::Time time_afterPull = IceUtil::Time::now();
 
                 for (data::LayerUpdate const& update : currentUpdates.updates)
                 {
                     apply(update);
                 }
-                IceUtil::Time time_afterApply = IceUtil::Time::now();
+                //IceUtil::Time time_afterApply = IceUtil::Time::now();
 
                 auto layerIDsAfter = getLayerIDs();
                 if (layerIDsAfter != layerIDsBefore)
                 {
                     emitLayersChanged(layerIDsAfter);
                 }
-                IceUtil::Time time_afterLayersChanged = IceUtil::Time::now();
+                //IceUtil::Time time_afterLayersChanged = IceUtil::Time::now();
 
                 // Most of the time is spent in apply
                 //                ARMARX_INFO << "Updates:  " << pulledUpdates.updates.size()
diff --git a/source/RobotAPI/components/DSObstacleAvoidance/DSObstacleAvoidance.cpp b/source/RobotAPI/components/DSObstacleAvoidance/DSObstacleAvoidance.cpp
index 4a83bdedaabbabcc2f46bc4e2815a826ee661156..a1be9a1ff18a6d9c86a570b75d5b9079f9ae8b68 100644
--- a/source/RobotAPI/components/DSObstacleAvoidance/DSObstacleAvoidance.cpp
+++ b/source/RobotAPI/components/DSObstacleAvoidance/DSObstacleAvoidance.cpp
@@ -549,17 +549,23 @@ armarx::DSObstacleAvoidance::run_visualization()
     Layer layer_sms = arviz.layer("safety_margins");
     Layer layer_rps = arviz.layer("reference_points");
     Layer layer_bbs = arviz.layer("bounding_boxes");
-    Color color = Color::red(255, 128);
-    Color color_m = Color::red(255, 64);
-
-    if (not m_doa.cfg.only_2d)
-    {
-        color = Color::blue(255, 128);
-        color_m = Color::blue(255, 64);
-    }
 
     for (const obstacledetection::Obstacle& obstacle : getObstacles())
     {
+        Color color = Color::orange(255, 128);
+        Color color_m = Color::orange(255, 64);
+
+        if (obstacle.name == "human")
+        {
+            color = Color::red(255, 128);
+            color_m = Color::red(255, 64);
+        }
+        else if (not m_doa.cfg.only_2d)
+        {
+            color = Color::blue(255, 128);
+            color_m = Color::blue(255, 64);
+        }
+
         const double safetyMarginZ = m_doa.cfg.only_2d ? 1 : obstacle.safetyMarginZ;
         const double posZ = m_doa.cfg.only_2d ? 1 : obstacle.posZ;
         const double refPosZ = m_doa.cfg.only_2d ? 1 : obstacle.refPosZ;
@@ -574,6 +580,7 @@ armarx::DSObstacleAvoidance::run_visualization()
 
         if (m_doa.cfg.only_2d)
         {
+
             layer_obs.add(Cylindroid{obstacle.name}
                           .pose(pose)
                           .axisLengths(dim.head<2>())
diff --git a/source/RobotAPI/components/DynamicObstacleManager/DynamicObstacleManager.cpp b/source/RobotAPI/components/DynamicObstacleManager/DynamicObstacleManager.cpp
index 46515a2c2f9a61acbaf63c186920478dab82cb1c..e712e30ccb2978fdc7caa0210b919773b7dce46b 100644
--- a/source/RobotAPI/components/DynamicObstacleManager/DynamicObstacleManager.cpp
+++ b/source/RobotAPI/components/DynamicObstacleManager/DynamicObstacleManager.cpp
@@ -234,7 +234,9 @@ namespace armarx
 
     void DynamicObstacleManager::wait_unitl_obstacles_are_ready(const Ice::Current&)
     {
-        usleep(m_min_value_for_accepting);
+        ARMARX_INFO << "Waiting for obstacles to get ready";
+        usleep(2.0 * m_min_value_for_accepting);
+        ARMARX_INFO << "Finished waiting for obstacles";
     }
 
 
diff --git a/source/RobotAPI/gui-plugins/CartesianWaypointControlGui/CMakeLists.txt b/source/RobotAPI/gui-plugins/CartesianWaypointControlGui/CMakeLists.txt
index 38578c06d1ad3cc784896d377a3986bbc73c3e6a..1b2caffb7f5f818c18e1ee068b6e9d7e0745eabc 100644
--- a/source/RobotAPI/gui-plugins/CartesianWaypointControlGui/CMakeLists.txt
+++ b/source/RobotAPI/gui-plugins/CartesianWaypointControlGui/CMakeLists.txt
@@ -17,12 +17,8 @@ set(GUI_MOC_HDRS ${HEADERS})
 set(GUI_UIS CartesianWaypointControlGuiWidget.ui)
 
 set(COMPONENT_LIBS
-    VirtualRobot
-
     SimpleConfigDialog
-
-    RobotAPIInterfaces
-    RobotAPICore
+    RobotAPIComponentPlugins
 )
 
 if(ArmarXGui_FOUND)
diff --git a/source/RobotAPI/gui-plugins/CartesianWaypointControlGui/CartesianWaypointControlGuiWidgetController.cpp b/source/RobotAPI/gui-plugins/CartesianWaypointControlGui/CartesianWaypointControlGuiWidgetController.cpp
index 5d2d12234ba03ac626e0579ed633b4699eae868d..5348bcaaa944c72d5b05f85afa0cd5253ca5ce9c 100644
--- a/source/RobotAPI/gui-plugins/CartesianWaypointControlGui/CartesianWaypointControlGuiWidgetController.cpp
+++ b/source/RobotAPI/gui-plugins/CartesianWaypointControlGui/CartesianWaypointControlGuiWidgetController.cpp
@@ -58,35 +58,27 @@ namespace armarx
     void CartesianWaypointControlGuiWidgetController::loadSettings(QSettings* settings)
     {
         std::lock_guard g{_allMutex};
-        _robotStateComponentName = settings->value("rsc", "Armar6StateComponent").toString().toStdString();
-        _robotUnitName = settings->value("ru", "Armar6Unit").toString().toStdString();
+        getRobotStateComponentPlugin().setRobotStateComponentName(settings->value("rsc", "Armar6StateComponent").toString().toStdString());
+        getRobotUnitComponentPlugin().setRobotUnitName(settings->value("ru", "Armar6Unit").toString().toStdString());
     }
 
     void CartesianWaypointControlGuiWidgetController::saveSettings(QSettings* settings)
     {
         std::lock_guard g{_allMutex};
-        settings->setValue("rsc", QString::fromStdString(_robotStateComponentName));
-        settings->setValue("ru", QString::fromStdString(_robotUnitName));
+        settings->setValue("rsc", QString::fromStdString(getRobotStateComponentPlugin().getRobotStateComponentName()));
+        settings->setValue("ru", QString::fromStdString(getRobotUnitComponentPlugin().getRobotUnitName()));
     }
 
     void CartesianWaypointControlGuiWidgetController::onInitComponent()
     {
-        std::lock_guard g{_allMutex};
-        usingProxy(_robotStateComponentName);
-        usingProxy(_robotUnitName);
     }
 
     void CartesianWaypointControlGuiWidgetController::onConnectComponent()
     {
         std::lock_guard g{_allMutex};
-        //proxies
-        {
-            _robotStateComponent = getProxy<RobotStateComponentInterfacePrx>(_robotStateComponentName);
-            _robotUnit = getProxy<RobotUnitInterfacePrx>(_robotUnitName);
-        }
         //robot
         {
-            _robot = RemoteRobot::createLocalCloneFromFile(_robotStateComponent, VirtualRobot::RobotIO::eStructure);
+            _robot = addRobot("state robot", VirtualRobot::RobotIO::eStructure);
         }
         //fill rns combo box
         {
@@ -135,7 +127,7 @@ namespace armarx
         ARMARX_IMPORTANT << "Creating " << njointControllerClassName << " '"
                          << _controllerName << "'";
         _controller = NJointCartesianWaypointControllerInterfacePrx::checkedCast(
-                          _robotUnit->createNJointController(
+                          getRobotUnit()->createNJointController(
                               njointControllerClassName,
                               _controllerName,
                               cfg));
@@ -199,8 +191,8 @@ namespace armarx
     void CartesianWaypointControlGuiWidgetController::configured()
     {
         std::lock_guard g{_allMutex};
-        _robotStateComponentName = _dialog->getProxyName("rsc");
-        _robotUnitName = _dialog->getProxyName("ru");
+        getRobotStateComponentPlugin().setRobotStateComponentName(_dialog->getProxyName("rsc"));
+        getRobotUnitComponentPlugin().setRobotUnitName(_dialog->getProxyName("ru"));
     }
 
     void CartesianWaypointControlGuiWidgetController::triggerParsing()
@@ -283,11 +275,11 @@ namespace armarx
     void CartesianWaypointControlGuiWidgetController::timerEvent(QTimerEvent*)
     {
         std::lock_guard g{_allMutex};
-        if (!_robot || !_robotStateComponent)
+        if (!_robot)
         {
             return;
         }
-        RemoteRobot::synchronizeLocalClone(_robot, _robotStateComponent);
+        synchronizeLocalClone(_robot);
         if (_controller)
         {
             ARMARX_INFO << deactivateSpam() << "setting visu gp to:\n" << _robot->getGlobalPose();
diff --git a/source/RobotAPI/gui-plugins/CartesianWaypointControlGui/CartesianWaypointControlGuiWidgetController.h b/source/RobotAPI/gui-plugins/CartesianWaypointControlGui/CartesianWaypointControlGuiWidgetController.h
index ae6961634e680913480e1441c572af6f397aa15f..fc6b1936d3abe105a02c8fdf2ca72439dcf8d84f 100644
--- a/source/RobotAPI/gui-plugins/CartesianWaypointControlGui/CartesianWaypointControlGuiWidgetController.h
+++ b/source/RobotAPI/gui-plugins/CartesianWaypointControlGui/CartesianWaypointControlGuiWidgetController.h
@@ -34,6 +34,8 @@
 #include <RobotAPI/interface/core/RobotState.h>
 #include <RobotAPI/interface/units/RobotUnit/RobotUnitInterface.h>
 #include <RobotAPI/interface/units/RobotUnit/NJointCartesianWaypointController.h>
+#include <RobotAPI/libraries/RobotAPIComponentPlugins/RobotUnitComponentPlugin.h>
+#include <RobotAPI/libraries/RobotAPIComponentPlugins/RobotStateComponentPlugin.h>
 
 #include <RobotAPI/gui-plugins/CartesianWaypointControlGui/ui_CartesianWaypointControlGuiWidget.h>
 
@@ -59,7 +61,9 @@ namespace armarx
      */
     class ARMARXCOMPONENT_IMPORT_EXPORT
         CartesianWaypointControlGuiWidgetController:
-        public armarx::ArmarXComponentWidgetControllerTemplate < CartesianWaypointControlGuiWidgetController >
+        public armarx::ArmarXComponentWidgetControllerTemplate < CartesianWaypointControlGuiWidgetController >,
+        public virtual RobotUnitComponentPluginUser,
+        public virtual RobotStateComponentPluginUser
     {
         Q_OBJECT
 
@@ -105,10 +109,6 @@ namespace armarx
         void timerEvent(QTimerEvent*) override;
 
     private:
-        std::string                                     _robotStateComponentName;
-        std::string                                     _robotUnitName;
-        RobotStateComponentInterfacePrx                 _robotStateComponent;
-        RobotUnitInterfacePrx                           _robotUnit;
         Ui::CartesianWaypointControlGuiWidget           _ui;
         QPointer<SimpleConfigDialog>                    _dialog;
         NJointCartesianWaypointControllerInterfacePrx   _controller;
diff --git a/source/RobotAPI/gui-plugins/RobotUnitPlugin/RobotUnitPlugin/RobotUnitPluginWidget.ui b/source/RobotAPI/gui-plugins/RobotUnitPlugin/RobotUnitPlugin/RobotUnitPluginWidget.ui
index 8d4e7919a123d4fe736a68de36dc19a10f6daa84..8b4af8524ff6102e7230794f12fdaac64b07a876 100644
--- a/source/RobotAPI/gui-plugins/RobotUnitPlugin/RobotUnitPlugin/RobotUnitPluginWidget.ui
+++ b/source/RobotAPI/gui-plugins/RobotUnitPlugin/RobotUnitPlugin/RobotUnitPluginWidget.ui
@@ -14,12 +14,6 @@
    <string>RobotUnitPluginWidget</string>
   </property>
   <layout class="QVBoxLayout" name="verticalLayout">
-   <property name="topMargin">
-    <number>0</number>
-   </property>
-   <property name="bottomMargin">
-    <number>0</number>
-   </property>
    <item>
     <widget class="QSplitter" name="splitter">
      <property name="orientation">
@@ -101,6 +95,116 @@
        </property>
       </layout>
      </widget>
+     <widget class="QGroupBox" name="groupBoxLogging">
+      <property name="title">
+       <string>Logging</string>
+      </property>
+      <layout class="QGridLayout" name="gridLayout">
+       <item row="0" column="0" colspan="2">
+        <layout class="QHBoxLayout" name="horizontalLayout">
+         <item>
+          <widget class="QLabel" name="label">
+           <property name="text">
+            <string>Filter</string>
+           </property>
+          </widget>
+         </item>
+         <item>
+          <widget class="QLineEdit" name="lineEditLoggingFilter"/>
+         </item>
+        </layout>
+       </item>
+       <item row="1" column="0" colspan="2">
+        <widget class="QTreeWidget" name="treeWidgetLoggingNames">
+         <column>
+          <property name="text">
+           <string/>
+          </property>
+         </column>
+        </widget>
+       </item>
+       <item row="3" column="0" colspan="2">
+        <layout class="QHBoxLayout" name="horizontalLayout_2">
+         <item>
+          <widget class="QLabel" name="label_2">
+           <property name="text">
+            <string>Save path</string>
+           </property>
+          </widget>
+         </item>
+         <item>
+          <widget class="QLineEdit" name="lineEditLoggingPath">
+           <property name="toolTip">
+            <string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Accepts patterns:&lt;/p&gt;&lt;p&gt;{LEFT&lt;span style=&quot; color:#c0c0c0;&quot;/&gt;CURLY}&lt;span style=&quot; color:#c0c0c0;&quot;/&gt;-&amp;gt;&lt;span style=&quot; color:#c0c0c0;&quot;/&gt;{&lt;/p&gt;&lt;p&gt;&lt;span style=&quot; font-family:'monospace';&quot;&gt;{RIGHT&lt;/span&gt;&lt;span style=&quot; font-family:'monospace'; color:#c0c0c0;&quot;/&gt;&lt;span style=&quot; font-family:'monospace';&quot;&gt;CURLY}&lt;/span&gt;&lt;span style=&quot; font-family:'monospace'; color:#c0c0c0;&quot;/&gt;&lt;span style=&quot; font-family:'monospace';&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span style=&quot; font-family:'monospace'; color:#c0c0c0;&quot;/&gt;&lt;span style=&quot; font-family:'monospace';&quot;&gt;}&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style=&quot; font-family:'monospace';&quot;&gt;{year&lt;/span&gt;&lt;span style=&quot; font-family:'monospace'; color:#c0c0c0;&quot;/&gt;&lt;span style=&quot; font-family:'monospace';&quot;&gt;/&lt;/span&gt;&lt;span style=&quot; font-family:'monospace'; color:#c0c0c0;&quot;/&gt;&lt;span style=&quot; font-family:'monospace';&quot;&gt;Year}&lt;/span&gt;&lt;span style=&quot; font-family:'monospace'; color:#c0c0c0;&quot;/&gt;&lt;span style=&quot; font-family:'monospace';&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span style=&quot; font-family:'monospace'; color:#c0c0c0;&quot;/&gt;&lt;span style=&quot; font-family:'monospace';&quot;&gt;year&lt;/span&gt;&lt;span style=&quot; font-family:'monospace'; color:#c0c0c0;&quot;/&gt;&lt;span style=&quot; font-family:'monospace';&quot;&gt;(&lt;/span&gt;&lt;span style=&quot; font-family:'monospace'; color:#000080;&quot;&gt;2&lt;/span&gt;&lt;span style=&quot; font-family:'monospace';&quot;&gt;/&lt;/span&gt;&lt;span style=&quot; font-family:'monospace'; color:#000080;&quot;&gt;4&lt;/span&gt;&lt;span style=&quot; font-family:'monospace'; color:#c0c0c0;&quot;/&gt;&lt;span style=&quot; font-family:'monospace';&quot;&gt;digits)&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style=&quot; font-family:'monospace';&quot;&gt;{month}&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style=&quot; font-family:'monospace';&quot;&gt;{day}&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style=&quot; font-family:'monospace';&quot;&gt;{hour}&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style=&quot; font-family:'monospace';&quot;&gt;{minute}&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style=&quot; font-family:'monospace';&quot;&gt;{second}&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style=&quot; font-family:'monospace';&quot;&gt;{Date}&lt;/span&gt;&lt;span style=&quot; font-family:'monospace'; color:#c0c0c0;&quot;/&gt;&lt;span style=&quot; font-family:'monospace';&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span style=&quot; font-family:'monospace'; color:#c0c0c0;&quot;/&gt;&lt;span style=&quot; font-family:'monospace';&quot;&gt;YYYY-MM-DD&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style=&quot; font-family:'monospace';&quot;&gt;{Time}&lt;/span&gt;&lt;span style=&quot; font-family:'monospace'; color:#c0c0c0;&quot;/&gt;&lt;span style=&quot; font-family:'monospace';&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span style=&quot; font-family:'monospace'; color:#c0c0c0;&quot;/&gt;&lt;span style=&quot; font-family:'monospace';&quot;&gt;HH-MM-SS&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style=&quot; font-family:'monospace';&quot;&gt;{DateTime}&lt;/span&gt;&lt;span style=&quot; font-family:'monospace'; color:#c0c0c0;&quot;/&gt;&lt;span style=&quot; font-family:'monospace';&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span style=&quot; font-family:'monospace'; color:#c0c0c0;&quot;/&gt;&lt;span style=&quot; font-family:'monospace';&quot;&gt;{Date}_{Time}&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style=&quot; font-family:'monospace';&quot;&gt;{time-since-epoch}&lt;/span&gt;&lt;span style=&quot; font-family:'monospace'; color:#c0c0c0;&quot;/&gt;&lt;span style=&quot; font-family:'monospace';&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span style=&quot; font-family:'monospace'; color:#c0c0c0;&quot;/&gt;&lt;span style=&quot; font-family:'monospace';&quot;&gt;nanoseconds&lt;/span&gt;&lt;span style=&quot; font-family:'monospace'; color:#c0c0c0;&quot;/&gt;&lt;span style=&quot; font-family:'monospace';&quot;&gt;since&lt;/span&gt;&lt;span style=&quot; font-family:'monospace'; color:#c0c0c0;&quot;/&gt;&lt;span style=&quot; font-family:'monospace';&quot;&gt;epoch&lt;/span&gt;&lt;span style=&quot; font-family:'monospace'; color:#c0c0c0;&quot;/&gt;&lt;span style=&quot; font-family:'monospace';&quot;&gt;(can&lt;/span&gt;&lt;span style=&quot; font-family:'monospace'; color:#c0c0c0;&quot;/&gt;&lt;span style=&quot; font-family:'monospace';&quot;&gt;be&lt;/span&gt;&lt;span style=&quot; font-family:'monospace'; color:#c0c0c0;&quot;/&gt;&lt;span style=&quot; font-family:'monospace';&quot;&gt;used&lt;/span&gt;&lt;span style=&quot; font-family:'monospace'; color:#c0c0c0;&quot;/&gt;&lt;span style=&quot; font-family:'monospace';&quot;&gt;as&lt;/span&gt;&lt;span style=&quot; font-family:'monospace'; color:#c0c0c0;&quot;/&gt;&lt;span style=&quot; font-family:'monospace';&quot;&gt;uuid)&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style=&quot; font-family:'monospace';&quot;&gt;{PackageDir:...}&lt;/span&gt;&lt;span style=&quot; font-family:'monospace'; color:#c0c0c0;&quot;/&gt;&lt;span style=&quot; font-family:'monospace';&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span style=&quot; font-family:'monospace'; color:#c0c0c0;&quot;/&gt;&lt;span style=&quot; font-family:'monospace';&quot;&gt;Directory&lt;/span&gt;&lt;span style=&quot; font-family:'monospace'; color:#c0c0c0;&quot;/&gt;&lt;span style=&quot; font-family:'monospace';&quot;&gt;of&lt;/span&gt;&lt;span style=&quot; font-family:'monospace'; color:#c0c0c0;&quot;/&gt;&lt;span style=&quot; font-family:'monospace';&quot;&gt;the&lt;/span&gt;&lt;span style=&quot; font-family:'monospace'; color:#c0c0c0;&quot;/&gt;&lt;span style=&quot; font-family:'monospace';&quot;&gt;given&lt;/span&gt;&lt;span style=&quot; font-family:'monospace'; color:#c0c0c0;&quot;/&gt;&lt;span style=&quot; font-family:'monospace';&quot;&gt;package&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style=&quot; font-family:'monospace';&quot;&gt;{ScenarioDir:...}&lt;/span&gt;&lt;span style=&quot; font-family:'monospace'; color:#c0c0c0;&quot;/&gt;&lt;span style=&quot; font-family:'monospace';&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span style=&quot; font-family:'monospace'; color:#c0c0c0;&quot;/&gt;&lt;span style=&quot; font-family:'monospace';&quot;&gt;Scenario&lt;/span&gt;&lt;span style=&quot; font-family:'monospace'; color:#c0c0c0;&quot;/&gt;&lt;span style=&quot; font-family:'monospace';&quot;&gt;Directory&lt;/span&gt;&lt;span style=&quot; font-family:'monospace'; color:#c0c0c0;&quot;/&gt;&lt;span style=&quot; font-family:'monospace';&quot;&gt;of&lt;/span&gt;&lt;span style=&quot; font-family:'monospace'; color:#c0c0c0;&quot;/&gt;&lt;span style=&quot; font-family:'monospace';&quot;&gt;the&lt;/span&gt;&lt;span style=&quot; font-family:'monospace'; color:#c0c0c0;&quot;/&gt;&lt;span style=&quot; font-family:'monospace';&quot;&gt;given&lt;/span&gt;&lt;span style=&quot; font-family:'monospace'; color:#c0c0c0;&quot;/&gt;&lt;span style=&quot; font-family:'monospace';&quot;&gt;package&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style=&quot; font-family:'monospace';&quot;&gt;{DataDir:...}&lt;/span&gt;&lt;span style=&quot; font-family:'monospace'; color:#c0c0c0;&quot;/&gt;&lt;span style=&quot; font-family:'monospace';&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span style=&quot; font-family:'monospace'; color:#c0c0c0;&quot;/&gt;&lt;span style=&quot; font-family:'monospace';&quot;&gt;Data&lt;/span&gt;&lt;span style=&quot; font-family:'monospace'; color:#c0c0c0;&quot;/&gt;&lt;span style=&quot; font-family:'monospace';&quot;&gt;Directory&lt;/span&gt;&lt;span style=&quot; font-family:'monospace'; color:#c0c0c0;&quot;/&gt;&lt;span style=&quot; font-family:'monospace';&quot;&gt;of&lt;/span&gt;&lt;span style=&quot; font-family:'monospace'; color:#c0c0c0;&quot;/&gt;&lt;span style=&quot; font-family:'monospace';&quot;&gt;the&lt;/span&gt;&lt;span style=&quot; font-family:'monospace'; color:#c0c0c0;&quot;/&gt;&lt;span style=&quot; font-family:'monospace';&quot;&gt;given&lt;/span&gt;&lt;span style=&quot; font-family:'monospace'; color:#c0c0c0;&quot;/&gt;&lt;span style=&quot; font-family:'monospace';&quot;&gt;package&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style=&quot; font-family:'monospace';&quot;&gt;{BinaryeDir:...}&lt;/span&gt;&lt;span style=&quot; font-family:'monospace'; color:#c0c0c0;&quot;/&gt;&lt;span style=&quot; font-family:'monospace';&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span style=&quot; font-family:'monospace'; color:#c0c0c0;&quot;/&gt;&lt;span style=&quot; font-family:'monospace';&quot;&gt;Binary&lt;/span&gt;&lt;span style=&quot; font-family:'monospace'; color:#c0c0c0;&quot;/&gt;&lt;span style=&quot; font-family:'monospace';&quot;&gt;Directory&lt;/span&gt;&lt;span style=&quot; font-family:'monospace'; color:#c0c0c0;&quot;/&gt;&lt;span style=&quot; font-family:'monospace';&quot;&gt;of&lt;/span&gt;&lt;span style=&quot; font-family:'monospace'; color:#c0c0c0;&quot;/&gt;&lt;span style=&quot; font-family:'monospace';&quot;&gt;the&lt;/span&gt;&lt;span style=&quot; font-family:'monospace'; color:#c0c0c0;&quot;/&gt;&lt;span style=&quot; font-family:'monospace';&quot;&gt;given&lt;/span&gt;&lt;span style=&quot; font-family:'monospace'; color:#c0c0c0;&quot;/&gt;&lt;span style=&quot; font-family:'monospace';&quot;&gt;package&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style=&quot; font-family:'monospace';&quot;&gt;{CMakeDir:...}&lt;/span&gt;&lt;span style=&quot; font-family:'monospace'; color:#c0c0c0;&quot;/&gt;&lt;span style=&quot; font-family:'monospace';&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span style=&quot; font-family:'monospace'; color:#c0c0c0;&quot;/&gt;&lt;span style=&quot; font-family:'monospace';&quot;&gt;CMake&lt;/span&gt;&lt;span style=&quot; font-family:'monospace'; color:#c0c0c0;&quot;/&gt;&lt;span style=&quot; font-family:'monospace';&quot;&gt;Directory&lt;/span&gt;&lt;span style=&quot; font-family:'monospace'; color:#c0c0c0;&quot;/&gt;&lt;span style=&quot; font-family:'monospace';&quot;&gt;of&lt;/span&gt;&lt;span style=&quot; font-family:'monospace'; color:#c0c0c0;&quot;/&gt;&lt;span style=&quot; font-family:'monospace';&quot;&gt;the&lt;/span&gt;&lt;span style=&quot; font-family:'monospace'; color:#c0c0c0;&quot;/&gt;&lt;span style=&quot; font-family:'monospace';&quot;&gt;given&lt;/span&gt;&lt;span style=&quot; font-family:'monospace'; color:#c0c0c0;&quot;/&gt;&lt;span style=&quot; font-family:'monospace';&quot;&gt;package&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style=&quot; font-family:'monospace';&quot;&gt;{BuildDir:...}&lt;/span&gt;&lt;span style=&quot; font-family:'monospace'; color:#c0c0c0;&quot;/&gt;&lt;span style=&quot; font-family:'monospace';&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span style=&quot; font-family:'monospace'; color:#c0c0c0;&quot;/&gt;&lt;span style=&quot; font-family:'monospace';&quot;&gt;Build&lt;/span&gt;&lt;span style=&quot; font-family:'monospace'; color:#c0c0c0;&quot;/&gt;&lt;span style=&quot; font-family:'monospace';&quot;&gt;Directory&lt;/span&gt;&lt;span style=&quot; font-family:'monospace'; color:#c0c0c0;&quot;/&gt;&lt;span style=&quot; font-family:'monospace';&quot;&gt;of&lt;/span&gt;&lt;span style=&quot; font-family:'monospace'; color:#c0c0c0;&quot;/&gt;&lt;span style=&quot; font-family:'monospace';&quot;&gt;the&lt;/span&gt;&lt;span style=&quot; font-family:'monospace'; color:#c0c0c0;&quot;/&gt;&lt;span style=&quot; font-family:'monospace';&quot;&gt;given&lt;/span&gt;&lt;span style=&quot; font-family:'monospace'; color:#c0c0c0;&quot;/&gt;&lt;span style=&quot; font-family:'monospace';&quot;&gt;package&lt;/span&gt;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
+           </property>
+           <property name="text">
+            <string>/tmp/logging/{DateTime}.csv</string>
+           </property>
+          </widget>
+         </item>
+         <item>
+          <widget class="QPushButton" name="pushButtonLoggingStart">
+           <property name="text">
+            <string>Start</string>
+           </property>
+          </widget>
+         </item>
+         <item>
+          <widget class="QPushButton" name="pushButtonLoggingStop">
+           <property name="enabled">
+            <bool>false</bool>
+           </property>
+           <property name="text">
+            <string>Stop</string>
+           </property>
+          </widget>
+         </item>
+        </layout>
+       </item>
+       <item row="5" column="0" colspan="2">
+        <layout class="QGridLayout" name="gridLayout_2">
+         <item row="0" column="0">
+          <widget class="QLineEdit" name="lineEditLoggingMark1">
+           <property name="text">
+            <string>Start</string>
+           </property>
+          </widget>
+         </item>
+         <item row="1" column="0">
+          <widget class="QLineEdit" name="lineEditLoggingMark2">
+           <property name="text">
+            <string>Stop</string>
+           </property>
+          </widget>
+         </item>
+         <item row="2" column="0">
+          <widget class="QLineEdit" name="lineEditLoggingMark3"/>
+         </item>
+         <item row="1" column="1">
+          <widget class="QPushButton" name="pushButtonLoggingMark2">
+           <property name="text">
+            <string>Set Mark</string>
+           </property>
+          </widget>
+         </item>
+         <item row="0" column="1">
+          <widget class="QPushButton" name="pushButtonLoggingMark1">
+           <property name="text">
+            <string>Set Mark</string>
+           </property>
+          </widget>
+         </item>
+         <item row="2" column="1">
+          <widget class="QPushButton" name="pushButtonLoggingMark3">
+           <property name="text">
+            <string>Set Mark</string>
+           </property>
+          </widget>
+         </item>
+        </layout>
+       </item>
+      </layout>
+     </widget>
     </widget>
    </item>
   </layout>
diff --git a/source/RobotAPI/gui-plugins/RobotUnitPlugin/RobotUnitPlugin/RobotUnitPluginWidgetController.cpp b/source/RobotAPI/gui-plugins/RobotUnitPlugin/RobotUnitPlugin/RobotUnitPluginWidgetController.cpp
index 076dfbbcebef9b02331fe6943fb7ba18943aa6c3..9f6229c5105a523109babbc9f2b7121ace039e42 100644
--- a/source/RobotAPI/gui-plugins/RobotUnitPlugin/RobotUnitPlugin/RobotUnitPluginWidgetController.cpp
+++ b/source/RobotAPI/gui-plugins/RobotUnitPlugin/RobotUnitPlugin/RobotUnitPluginWidgetController.cpp
@@ -24,13 +24,14 @@
 #include "../QWidgets/StyleSheets.h"
 
 #include <string>
-
+#include <regex>
 #include <filesystem>
 
 #include <QDir>
 #include <QSortFilterProxyModel>
 #include <QAction>
 
+#include <ArmarXCore/util/CPPUtility/Iterator.h>
 #include <ArmarXCore/core/system/cmake/CMakePackageFinder.h>
 #include <ArmarXCore/core/exceptions/local/ExpressionException.h>
 
@@ -72,6 +73,21 @@ RobotUnitPluginWidgetController::RobotUnitPluginWidgetController()
         nJointControllerClasses->setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::Expanding);
         nJointControllerClasses->setVisible(false);
     }
+    //update logging
+    {
+        widget.groupBoxLogging->setVisible(false);
+        widget.groupBoxLogging->setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::Expanding);
+
+        connect(widget.pushButtonLoggingStart, SIGNAL(clicked()), this, SLOT(on_pushButtonLoggingStart_clicked()));
+        connect(widget.pushButtonLoggingStop, SIGNAL(clicked()), this, SLOT(on_pushButtonLoggingStop_clicked()));
+        connect(widget.pushButtonLoggingMark1, SIGNAL(clicked()), this, SLOT(on_pushButtonLoggingMark1_clicked()));
+        connect(widget.pushButtonLoggingMark2, SIGNAL(clicked()), this, SLOT(on_pushButtonLoggingMark2_clicked()));
+        connect(widget.pushButtonLoggingMark3, SIGNAL(clicked()), this, SLOT(on_pushButtonLoggingMark3_clicked()));
+        connect(widget.lineEditLoggingFilter, SIGNAL(textChanged(const QString&)),
+                this, SLOT(on_lineEditLoggingFilter_textChanged(const QString&)));
+        connect(widget.treeWidgetLoggingNames, SIGNAL(itemChanged(QTreeWidgetItem*, int)),
+                this, SLOT(on_treeWidgetLoggingNames_itemChanged(QTreeWidgetItem*, int)));
+    }
     updateToolBarActionCheckedState();
 }
 
@@ -195,6 +211,14 @@ QPointer<QWidget> RobotUnitPluginWidgetController::getCustomTitlebarWidget(QWidg
         customToolbar->addAction(showNJointClasses);
         customToolbar->addSeparator();
 
+        customToolbar->addAction(QIcon(":/icons/view-refresh-7.png"), "", this, SLOT(refreshLogging()));
+        showLogging = new QAction {"Logging", customToolbar};
+        showLogging->setCheckable(true);
+        showLogging->setToolTip("Hide/Show the logging pane");
+        connect(showLogging, SIGNAL(toggled(bool)), widget.groupBoxLogging, SLOT(setVisible(bool)));
+        customToolbar->addAction(showLogging);
+        customToolbar->addSeparator();
+
         customToolbar->addAction(QIcon(":/icons/document-save.svg"), "Write log", this, SLOT(writeLogClicked()))
         ->setToolTip("Writes the log to /tmp/");
     }
@@ -285,6 +309,263 @@ void armarx::RobotUnitPluginWidgetController::timerEvent(QTimerEvent*)
         refreshNJointControllerClassesClicked();
         refreshControlDevicesClicked();
         refreshSensorDevicesClicked();
+        refreshLogging();
         killTimer(onConnectTimerId);
     }
 }
+
+void armarx::RobotUnitPluginWidgetController::refreshLogging()
+{
+    on_pushButtonLoggingStop_clicked();
+
+    widget.treeWidgetLoggingNames->clear();
+    loggingData.allItems.clear();
+
+    const auto allLoggingNames = robotUnitPrx->getLoggingNames();
+
+    std::map<std::string, QTreeWidgetItem*> separators;
+    auto add = [&](const std::string & name, const std::string & display, auto parent)
+    {
+        QTreeWidgetItem* i = new QTreeWidgetItem(parent);
+        i->setText(0, QString::fromStdString(display) + "*");
+        i->setData(0, Qt::ToolTipRole, QString::fromStdString(name));
+        separators[name] = i;
+        loggingData.allItems.emplace_back(i);
+        i->setCheckState(0, Qt::Unchecked);
+    };
+    add("", "", widget.treeWidgetLoggingNames);
+    loggingData.top = loggingData.allItems.front();
+
+    for (const auto& name : allLoggingNames)
+    {
+        const auto parts = Split(name, ".", true, true);
+        std::string reassembled;
+        for (const auto& p : parts)
+        {
+            ARMARX_CHECK_EXPRESSION(separators.count(reassembled));
+            auto parent = separators.at(reassembled);
+            reassembled += (reassembled.empty() ? p : "." + p) ;
+            if (!separators.count(reassembled))
+            {
+                add(reassembled, p, parent);
+            }
+        }
+        loggingData.allItems.back()->setText(0, QString::fromStdString(parts.back()));
+    }
+
+}
+
+void armarx::RobotUnitPluginWidgetController::on_pushButtonLoggingStart_clicked()
+{
+    if (!robotUnitPrx || loggingData.handle)
+    {
+        return;
+    }
+    std::vector<std::string> loggingNames;
+    std::function<void(QTreeWidgetItem*)> recurseChildren = [&](auto it)
+    {
+        switch (it->checkState(0))
+        {
+            case Qt::Checked:
+                loggingNames.emplace_back(it->data(0, Qt::ToolTipRole).toString().toStdString());
+                break;
+            case Qt::Unchecked:
+                break;
+            case Qt::PartiallyChecked:
+                for (int  i = 0; i < it->childCount(); ++i)
+                {
+                    recurseChildren(it->child(i));
+                }
+                break;
+        }
+    };
+    recurseChildren(loggingData.top);
+    ARMARX_INFO << "start logging " << loggingNames;
+
+    loggingData.handle = robotUnitPrx->startRtLogging(
+                             widget.lineEditLoggingPath->text().toStdString(),
+                             loggingNames);
+    widget.pushButtonLoggingStart->setEnabled(false);
+    widget.pushButtonLoggingStop->setEnabled(true);
+    widget.pushButtonLoggingMark1->setEnabled(true);
+    widget.pushButtonLoggingMark2->setEnabled(true);
+    widget.pushButtonLoggingMark3->setEnabled(true);
+}
+
+void armarx::RobotUnitPluginWidgetController::on_pushButtonLoggingStop_clicked()
+{
+    widget.pushButtonLoggingStart->setEnabled(true);
+    widget.pushButtonLoggingStop->setEnabled(false);
+    widget.pushButtonLoggingMark1->setEnabled(false);
+    widget.pushButtonLoggingMark2->setEnabled(false);
+    widget.pushButtonLoggingMark3->setEnabled(false);
+    if (!loggingData.handle)
+    {
+        return;
+    }
+    robotUnitPrx->stopRtLogging(loggingData.handle);
+    loggingData.handle = nullptr;
+}
+
+void armarx::RobotUnitPluginWidgetController::on_lineEditLoggingFilter_textChanged(const QString& arg1)
+{
+    std::regex reg;
+    try
+    {
+        reg = std::regex{arg1.toStdString()};
+    }
+    catch (...)
+    {
+        //broken regex
+        widget.lineEditLoggingFilter->setStyleSheet("QLineEdit { background: rgb(255, 150, 150); selection-background-color: rgb(255, 0, 0); }");
+        return;
+    }
+    widget.lineEditLoggingFilter->setStyleSheet("QLineEdit {}");
+
+    std::function<void(QTreeWidgetItem* item)> setVisible = [&](auto it)
+    {
+        it->setHidden(false);
+        auto parent = it->parent();
+        //set parent state depending on its childrens state
+        if (!parent)
+        {
+            return;
+        }
+        setVisible(parent);
+    };
+    for (auto item : loggingData.allItems)
+    {
+        item->setHidden(true);
+    }
+    for (auto item : loggingData.allItems)
+    {
+        const auto str = item->data(0, Qt::ToolTipRole).toString().toStdString();
+        std::smatch match;
+        if (std::regex_search(str, match, reg))
+        {
+            setVisible(item);
+        }
+    }
+    widget.treeWidgetLoggingNames->blockSignals(true);
+    for (auto item : MakeReversedRange(loggingData.allItems))
+    {
+        loggingData.updateCheckStateUpward(item, false);
+    }
+    widget.treeWidgetLoggingNames->blockSignals(false);
+}
+
+void armarx::RobotUnitPluginWidgetController::on_treeWidgetLoggingNames_itemChanged(QTreeWidgetItem* item, int)
+{
+    widget.treeWidgetLoggingNames->blockSignals(true);
+    loggingData.updateCheckStateDownward(item, item->checkState(0), true);
+    loggingData.updateCheckStateUpward(item->parent(), true);
+    widget.treeWidgetLoggingNames->blockSignals(false);
+}
+
+void armarx::RobotUnitPluginWidgetController::on_pushButtonLoggingMark1_clicked()
+{
+    if (!loggingData.handle)
+    {
+        return;
+    }
+    const auto mark = widget.lineEditLoggingMark1->text().toStdString();
+    ARMARX_INFO << "set mark " << mark;
+    robotUnitPrx->addMarkerToRtLog(loggingData.handle, mark);
+}
+
+void armarx::RobotUnitPluginWidgetController::on_pushButtonLoggingMark2_clicked()
+{
+    if (!loggingData.handle)
+    {
+        return;
+    }
+    const auto mark = widget.lineEditLoggingMark2->text().toStdString();
+    ARMARX_INFO << "set mark " << mark;
+    robotUnitPrx->addMarkerToRtLog(loggingData.handle, mark);
+}
+
+void armarx::RobotUnitPluginWidgetController::on_pushButtonLoggingMark3_clicked()
+{
+    if (!loggingData.handle)
+    {
+        return;
+    }
+    const auto mark = widget.lineEditLoggingMark3->text().toStdString();
+    ARMARX_INFO << "set mark " << mark;
+    robotUnitPrx->addMarkerToRtLog(loggingData.handle, mark);
+}
+
+void RobotUnitPluginWidgetController::LoggingData::updateCheckStateUpward(QTreeWidgetItem* item, bool recurseParents)
+{
+    //set item state depending on its childrens state and maybe recurse parent
+    for (; item; item = recurseParents ? item->parent() : nullptr)
+    {
+        if (item->isHidden())
+        {
+            continue;
+        }
+        bool anyChecked = false;
+        bool anyUnchecked = false;
+        bool anyTri = false;
+        for (int  i = 0; i < item->childCount(); ++i)
+        {
+            auto c = item->child(i);
+            if (c->isHidden())
+            {
+                continue;
+            }
+            switch (c->checkState(0))
+            {
+                case Qt::Checked:
+                    anyChecked = true;
+                    break;
+                case Qt::Unchecked:
+                    anyUnchecked = true;
+                    break;
+                case Qt::PartiallyChecked:
+                    anyTri = true;
+                    break;
+            }
+            if (anyChecked + anyUnchecked + anyTri > 1 || anyTri)
+            {
+                item->setCheckState(0, Qt::PartiallyChecked);
+            }
+            else if (anyChecked)
+            {
+                item->setCheckState(0, Qt::Checked);
+            }
+            else if (anyUnchecked)
+            {
+                item->setCheckState(0, Qt::Unchecked);
+            }
+            //case all false -> leaf -> do nothing
+        }
+    }
+}
+
+void RobotUnitPluginWidgetController::LoggingData::updateCheckStateDownward(
+    QTreeWidgetItem* item,
+    Qt::CheckState state,
+    bool recurseChildren)
+{
+    if (item->isHidden())
+    {
+        return;
+    }
+    item->setCheckState(0, state);
+
+    if (!recurseChildren)
+    {
+        return;
+    }
+    for (int  i = 0; i < item->childCount(); ++i)
+    {
+        auto c = item->child(i);
+        if (c->isHidden())
+        {
+            continue;
+        }
+        c->setCheckState(0, state);
+        updateCheckStateDownward(c, state, true);
+    }
+}
diff --git a/source/RobotAPI/gui-plugins/RobotUnitPlugin/RobotUnitPlugin/RobotUnitPluginWidgetController.h b/source/RobotAPI/gui-plugins/RobotUnitPlugin/RobotUnitPlugin/RobotUnitPluginWidgetController.h
index 9b57ef2d510a9c2ce896e86a36dbab461e9e7a12..06270ecbc7e9c7280fac72f6dac959e504db26bd 100644
--- a/source/RobotAPI/gui-plugins/RobotUnitPlugin/RobotUnitPlugin/RobotUnitPluginWidgetController.h
+++ b/source/RobotAPI/gui-plugins/RobotUnitPlugin/RobotUnitPlugin/RobotUnitPluginWidgetController.h
@@ -132,11 +132,21 @@ namespace armarx
         void refreshNJointControllerClassesClicked();
         void refreshControlDevicesClicked();
         void refreshSensorDevicesClicked();
+        void refreshLogging();
 
         void writeLogClicked();
 
         void startOnConnectTimer();
 
+        //logging
+        void on_lineEditLoggingFilter_textChanged(const QString& arg1);
+        void on_pushButtonLoggingStop_clicked();
+        void on_pushButtonLoggingStart_clicked();
+        void on_treeWidgetLoggingNames_itemChanged(QTreeWidgetItem* item, int column);
+        void on_pushButtonLoggingMark1_clicked();
+        void on_pushButtonLoggingMark2_clicked();
+        void on_pushButtonLoggingMark3_clicked();
+
     private:
         void timerEvent(QTimerEvent*) override;
         void updateToolBarActionCheckedState();
@@ -162,6 +172,17 @@ namespace armarx
         QPointer<QAction> showSDevs;
         QPointer<QAction> showNJoint;
         QPointer<QAction> showNJointClasses;
+        QPointer<QAction> showLogging;
+
+        struct LoggingData
+        {
+            QTreeWidgetItem* top;
+            std::vector<QTreeWidgetItem*> allItems;
+            RemoteReferenceCounterBasePtr handle;
+            static void updateCheckStateUpward(QTreeWidgetItem* item, bool recurseParents);
+            static void updateCheckStateDownward(QTreeWidgetItem* item, Qt::CheckState state, bool recurseChildren);
+        };
+        LoggingData loggingData;
 
         int onConnectTimerId;
     };
diff --git a/source/RobotAPI/interface/units/RobotUnit/NJointBimanualObjLevelController.ice b/source/RobotAPI/interface/units/RobotUnit/NJointBimanualObjLevelController.ice
index 2707d344c94ae887ca725a970e1adc67257629b9..a00ef88cca841dec09a24ba64e1a3e7059ceb931 100644
--- a/source/RobotAPI/interface/units/RobotUnit/NJointBimanualObjLevelController.ice
+++ b/source/RobotAPI/interface/units/RobotUnit/NJointBimanualObjLevelController.ice
@@ -110,9 +110,17 @@ module armarx
 //        void setViaPoints(double canVal, Ice::DoubleSeq point);
         void setGoals(Ice::DoubleSeq goals);
         void setViaPoints(double u, Ice::DoubleSeq viapoint);
+        void removeAllViaPoints();
         double getVirtualTime();
 
+        void setKpImpedance(Ice::FloatSeq value);
+        void setKdImpedance(Ice::FloatSeq value);
+        void setKmAdmittance(Ice::FloatSeq value);
+        void setKpAdmittance(Ice::FloatSeq value);
+        void setKdAdmittance(Ice::FloatSeq value);
 
+        Ice::FloatSeq getCurrentObjVel();
+        Ice::FloatSeq getCurrentObjForce();
     };
 
 
diff --git a/source/RobotAPI/libraries/DMPController/TaskSpaceDMPController.cpp b/source/RobotAPI/libraries/DMPController/TaskSpaceDMPController.cpp
index d92ea1cf2a18c40c413699c4fae09f99b000558a..ddf9458379e26add5eb9c58ba1054306f5b5fd2e 100644
--- a/source/RobotAPI/libraries/DMPController/TaskSpaceDMPController.cpp
+++ b/source/RobotAPI/libraries/DMPController/TaskSpaceDMPController.cpp
@@ -321,7 +321,7 @@ void TaskSpaceDMPController::setViaPose(double canVal, const std::vector<double>
 
 void TaskSpaceDMPController::removeAllViaPoints()
 {
-    //    dmpPtr->removeViaPoints();
+    dmpPtr->removeViaPoints();
 }
 
 void TaskSpaceDMPController::prepareExecution(const Eigen::Matrix4f& currentPose, const Eigen::Matrix4f& goalPose)
diff --git a/source/RobotAPI/libraries/RobotAPIComponentPlugins/CMakeLists.txt b/source/RobotAPI/libraries/RobotAPIComponentPlugins/CMakeLists.txt
index 6567872ebd97ab3016b3af816f2048d473040464..eb2a743cc6435d7ab3d44a77dc8283a0e754138d 100644
--- a/source/RobotAPI/libraries/RobotAPIComponentPlugins/CMakeLists.txt
+++ b/source/RobotAPI/libraries/RobotAPIComponentPlugins/CMakeLists.txt
@@ -21,6 +21,8 @@ set(LIB_FILES
     TrajectoryPlayerComponentPlugin.cpp
     CartesianPositionControlComponentPlugin.cpp
     NaturalIKComponentPlugin.cpp
+    HandUnitComponentPlugin.cpp
+    FrameTrackingComponentPlugin.cpp
 )
 set(LIB_HEADERS
     RobotStateComponentPlugin.h
@@ -34,6 +36,8 @@ set(LIB_HEADERS
     TrajectoryPlayerComponentPlugin.h
     CartesianPositionControlComponentPlugin.h
     NaturalIKComponentPlugin.h
+    HandUnitComponentPlugin.h
+    FrameTrackingComponentPlugin.h
 )
 
 armarx_add_library("${LIB_NAME}" "${LIB_FILES}" "${LIB_HEADERS}" "${LIBS}")
diff --git a/source/RobotAPI/libraries/RobotAPIComponentPlugins/FrameTrackingComponentPlugin.cpp b/source/RobotAPI/libraries/RobotAPIComponentPlugins/FrameTrackingComponentPlugin.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..f5ba6417ad1ee3c5a683a33209678c3465c76277
--- /dev/null
+++ b/source/RobotAPI/libraries/RobotAPIComponentPlugins/FrameTrackingComponentPlugin.cpp
@@ -0,0 +1,54 @@
+#include "FrameTrackingComponentPlugin.h"
+
+namespace armarx
+{
+    namespace plugins
+    {
+
+        void FrameTrackingComponentPlugin::preOnInitComponent()
+        {
+            parent<Component>().usingProxyFromProperty(PROPERTY_NAME);
+        }
+
+        void FrameTrackingComponentPlugin::preOnConnectComponent()
+        {
+            parent<Component>().getProxyFromProperty(_frameTracking, PROPERTY_NAME);
+        }
+
+        void FrameTrackingComponentPlugin::postCreatePropertyDefinitions(armarx::PropertyDefinitionsPtr& properties)
+        {
+            if (!properties->hasDefinition(PROPERTY_NAME))
+            {
+                properties->defineOptionalProperty<std::string>(
+                    PROPERTY_NAME,
+                    "FrameTracking",
+                    "Name of the FrameTracking");
+            }
+        }
+
+        FrameTrackingInterfacePrx FrameTrackingComponentPlugin::getFrameTracking()
+        {
+            return _frameTracking;
+        }
+
+
+    }
+}
+
+namespace armarx
+{
+
+    FrameTrackingComponentPluginUser::FrameTrackingComponentPluginUser()
+    {
+        addPlugin(plugin);
+    }
+
+    FrameTrackingInterfacePrx FrameTrackingComponentPluginUser::getFrameTracking()
+    {
+        return plugin->getFrameTracking();
+    }
+
+
+}
+
+
diff --git a/source/RobotAPI/libraries/RobotAPIComponentPlugins/FrameTrackingComponentPlugin.h b/source/RobotAPI/libraries/RobotAPIComponentPlugins/FrameTrackingComponentPlugin.h
new file mode 100644
index 0000000000000000000000000000000000000000..82b1b593d1c457b1b2c636a292ee0ce8aebce477
--- /dev/null
+++ b/source/RobotAPI/libraries/RobotAPIComponentPlugins/FrameTrackingComponentPlugin.h
@@ -0,0 +1,58 @@
+#pragma once
+
+#include <ArmarXCore/core/Component.h>
+#include <RobotAPI/interface/components/FrameTrackingInterface.h>
+
+
+namespace armarx
+{
+    namespace plugins
+    {
+
+        class FrameTrackingComponentPlugin : public ComponentPlugin
+        {
+        public:
+            using ComponentPlugin::ComponentPlugin;
+
+            void preOnInitComponent() override;
+
+            void preOnConnectComponent() override;
+
+            void postCreatePropertyDefinitions(PropertyDefinitionsPtr& properties) override;
+
+            FrameTrackingInterfacePrx getFrameTracking();
+
+        private:
+            static constexpr const char* PROPERTY_NAME = "FrameTrackingName";
+            FrameTrackingInterfacePrx _frameTracking;
+        };
+
+    }
+}
+
+namespace armarx
+{
+    /**
+     * @brief Provides a ready-to-use FrameTracking.
+     */
+    class FrameTrackingComponentPluginUser : virtual public ManagedIceObject
+    {
+    public:
+        FrameTrackingComponentPluginUser();
+        FrameTrackingInterfacePrx getFrameTracking();
+
+    private:
+        armarx::plugins::FrameTrackingComponentPlugin* plugin = nullptr;
+    };
+
+}
+
+
+namespace armarx
+{
+    namespace plugins
+    {
+        // Legacy typedef.
+        using FrameTrackingComponentPluginUser = armarx::FrameTrackingComponentPluginUser;
+    }
+}
diff --git a/source/RobotAPI/libraries/RobotAPIComponentPlugins/HandUnitComponentPlugin.cpp b/source/RobotAPI/libraries/RobotAPIComponentPlugins/HandUnitComponentPlugin.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..c99b6a9c2dafb560e00e86c28eee0108b650c888
--- /dev/null
+++ b/source/RobotAPI/libraries/RobotAPIComponentPlugins/HandUnitComponentPlugin.cpp
@@ -0,0 +1,54 @@
+#include "HandUnitComponentPlugin.h"
+
+namespace armarx
+{
+    namespace plugins
+    {
+
+        void HandUnitComponentPlugin::preOnInitComponent()
+        {
+            parent<Component>().usingProxyFromProperty(PROPERTY_NAME);
+        }
+
+        void HandUnitComponentPlugin::preOnConnectComponent()
+        {
+            parent<Component>().getProxyFromProperty(_handUnit, PROPERTY_NAME);
+        }
+
+        void HandUnitComponentPlugin::postCreatePropertyDefinitions(armarx::PropertyDefinitionsPtr& properties)
+        {
+            if (!properties->hasDefinition(PROPERTY_NAME))
+            {
+                properties->defineOptionalProperty<std::string>(
+                    PROPERTY_NAME,
+                    "HandUnit",
+                    "Name of the HandUnit");
+            }
+        }
+
+        HandUnitInterfacePrx HandUnitComponentPlugin::getHandUnit()
+        {
+            return _handUnit;
+        }
+
+
+    }
+}
+
+namespace armarx
+{
+
+    HandUnitComponentPluginUser::HandUnitComponentPluginUser()
+    {
+        addPlugin(plugin);
+    }
+
+    HandUnitInterfacePrx HandUnitComponentPluginUser::getHandUnit()
+    {
+        return plugin->getHandUnit();
+    }
+
+
+}
+
+
diff --git a/source/RobotAPI/libraries/RobotAPIComponentPlugins/HandUnitComponentPlugin.h b/source/RobotAPI/libraries/RobotAPIComponentPlugins/HandUnitComponentPlugin.h
new file mode 100644
index 0000000000000000000000000000000000000000..4cd3593cb95abd83e023e8aa5642b68e23bea3fb
--- /dev/null
+++ b/source/RobotAPI/libraries/RobotAPIComponentPlugins/HandUnitComponentPlugin.h
@@ -0,0 +1,58 @@
+#pragma once
+
+#include <ArmarXCore/core/Component.h>
+#include <RobotAPI/interface/units/HandUnitInterface.h>
+
+
+namespace armarx
+{
+    namespace plugins
+    {
+
+        class HandUnitComponentPlugin : public ComponentPlugin
+        {
+        public:
+            using ComponentPlugin::ComponentPlugin;
+
+            void preOnInitComponent() override;
+
+            void preOnConnectComponent() override;
+
+            void postCreatePropertyDefinitions(PropertyDefinitionsPtr& properties) override;
+
+            HandUnitInterfacePrx getHandUnit();
+
+        private:
+            static constexpr const char* PROPERTY_NAME = "HandUnitName";
+            HandUnitInterfacePrx _handUnit;
+        };
+
+    }
+}
+
+namespace armarx
+{
+    /**
+     * @brief Provides a ready-to-use HandUnit.
+     */
+    class HandUnitComponentPluginUser : virtual public ManagedIceObject
+    {
+    public:
+        HandUnitComponentPluginUser();
+        HandUnitInterfacePrx getHandUnit();
+
+    private:
+        armarx::plugins::HandUnitComponentPlugin* plugin = nullptr;
+    };
+
+}
+
+
+namespace armarx
+{
+    namespace plugins
+    {
+        // Legacy typedef.
+        using HandUnitComponentPluginUser = armarx::HandUnitComponentPluginUser;
+    }
+}
diff --git a/source/RobotAPI/libraries/RobotAPIComponentPlugins/RobotStateComponentPlugin.cpp b/source/RobotAPI/libraries/RobotAPIComponentPlugins/RobotStateComponentPlugin.cpp
index c5445458598bfcfe4ea427a4f519f6d5baacddaf..3f28f11c839e988564882fe679eaec47b74cb649 100644
--- a/source/RobotAPI/libraries/RobotAPIComponentPlugins/RobotStateComponentPlugin.cpp
+++ b/source/RobotAPI/libraries/RobotAPIComponentPlugins/RobotStateComponentPlugin.cpp
@@ -199,9 +199,14 @@ namespace armarx::plugins
 
     void RobotStateComponentPlugin::preOnInitComponent()
     {
+        if (!_robotStateComponent && _robotStateComponentName.empty())
+        {
+            parent<Component>().getProperty(_robotStateComponentName, makePropertyName(_propertyName));
+        }
+
         if (!_robotStateComponent)
         {
-            parent<Component>().usingProxyFromProperty(makePropertyName(_propertyName));
+            parent<Component>().usingProxy(_robotStateComponentName);
         }
     }
 
@@ -209,7 +214,7 @@ namespace armarx::plugins
     {
         if (!_robotStateComponent)
         {
-            parent<Component>().getProxyFromProperty(_robotStateComponent, makePropertyName(_propertyName));
+            parent<Component>().getProxy(_robotStateComponent, _robotStateComponentName);
         }
     }
 
@@ -242,6 +247,18 @@ namespace armarx::plugins
         ARMARX_CHECK_NOT_NULL(node) << "No tcp configured for the robot ";
         return SimpleDiffIK::CalculateReachability(targets, initialJV, rns, node, params);
     }
+
+    void RobotStateComponentPlugin::setRobotStateComponentName(const std::string& name)
+    {
+        ARMARX_CHECK_NOT_EMPTY(name);
+        ARMARX_CHECK_EMPTY(_robotStateComponentName);
+        _robotStateComponentName = name;
+    }
+
+    const std::string& RobotStateComponentPlugin::getRobotStateComponentName() const
+    {
+        return _robotStateComponentName;
+    }
 }
 
 namespace armarx
diff --git a/source/RobotAPI/libraries/RobotAPIComponentPlugins/RobotStateComponentPlugin.h b/source/RobotAPI/libraries/RobotAPIComponentPlugins/RobotStateComponentPlugin.h
index a338957d196d166494ad031ed3280abeef47b899..25ca57fffc2155f8fc88114de62c0836b206c02e 100644
--- a/source/RobotAPI/libraries/RobotAPIComponentPlugins/RobotStateComponentPlugin.h
+++ b/source/RobotAPI/libraries/RobotAPIComponentPlugins/RobotStateComponentPlugin.h
@@ -53,6 +53,8 @@ namespace armarx::plugins
         struct RobotData;
         using ComponentPlugin::ComponentPlugin;
 
+        void setRobotStateComponentName(const std::string& name);
+        const std::string& getRobotStateComponentName() const;
         //get / add
     public:
         bool hasRobot(const std::string& id) const;
@@ -137,6 +139,7 @@ namespace armarx::plugins
         //data
     public:
         static constexpr auto            _propertyName = "RemoteStateComponentName";
+        std::string                      _robotStateComponentName;
         RobotStateComponentInterfacePrx  _robotStateComponent;
         mutable std::recursive_mutex     _robotsMutex;
         std::map<std::string, RobotData> _robots;
diff --git a/source/RobotAPI/libraries/RobotAPIComponentPlugins/RobotUnitComponentPlugin.cpp b/source/RobotAPI/libraries/RobotAPIComponentPlugins/RobotUnitComponentPlugin.cpp
index 383de616a6001cd7358a2fd5604c44f7e669ecc6..1e94a395814376eb08b20e45f5d043f21fa6dbb4 100644
--- a/source/RobotAPI/libraries/RobotAPIComponentPlugins/RobotUnitComponentPlugin.cpp
+++ b/source/RobotAPI/libraries/RobotAPIComponentPlugins/RobotUnitComponentPlugin.cpp
@@ -1,53 +1,64 @@
 #include "RobotUnitComponentPlugin.h"
 
-namespace armarx
+namespace armarx::plugins
 {
-    namespace plugins
+    void RobotUnitComponentPlugin::preOnInitComponent()
     {
-
-        void RobotUnitComponentPlugin::preOnInitComponent()
-        {
-            parent<Component>().usingProxyFromProperty(PROPERTY_NAME);
-        }
-
-        void RobotUnitComponentPlugin::preOnConnectComponent()
+        if (_robotUnitName.empty())
         {
-            parent<Component>().getProxyFromProperty(_robotUnit, PROPERTY_NAME);
+            parent<Component>().getProperty(_robotUnitName, PROPERTY_NAME);
         }
+        parent<Component>().usingProxy(_robotUnitName);
+    }
 
-        void RobotUnitComponentPlugin::postCreatePropertyDefinitions(armarx::PropertyDefinitionsPtr& properties)
-        {
-            if (!properties->hasDefinition(PROPERTY_NAME))
-            {
-                properties->defineRequiredProperty<std::string>(
-                    PROPERTY_NAME,
-                    "Name of the RobotUnit");
-            }
-        }
+    void RobotUnitComponentPlugin::preOnConnectComponent()
+    {
+        parent<Component>().getProxy(_robotUnit, _robotUnitName);
+    }
 
-        RobotUnitInterfacePrx RobotUnitComponentPlugin::getRobotUnit()
+    void RobotUnitComponentPlugin::postCreatePropertyDefinitions(armarx::PropertyDefinitionsPtr& properties)
+    {
+        if (!properties->hasDefinition(PROPERTY_NAME))
         {
-            return _robotUnit;
+            properties->defineRequiredProperty<std::string>(
+                PROPERTY_NAME,
+                "Name of the RobotUnit");
         }
+    }
 
+    RobotUnitInterfacePrx RobotUnitComponentPlugin::getRobotUnit() const
+    {
+        return _robotUnit;
+    }
 
+    void RobotUnitComponentPlugin::setRobotUnitName(const std::string& name)
+    {
+        ARMARX_CHECK_NOT_EMPTY(name);
+        ARMARX_CHECK_EMPTY(_robotUnitName);
+        _robotUnitName = name;
+    }
+    const std::string& RobotUnitComponentPlugin::getRobotUnitName() const
+    {
+        return _robotUnitName;
     }
 }
 
 namespace armarx
 {
-
     RobotUnitComponentPluginUser::RobotUnitComponentPluginUser()
     {
         addPlugin(plugin);
     }
 
-    RobotUnitInterfacePrx RobotUnitComponentPluginUser::getRobotUnit()
+    RobotUnitInterfacePrx RobotUnitComponentPluginUser::getRobotUnit() const
     {
         return plugin->getRobotUnit();
     }
 
-
+    plugins::RobotUnitComponentPlugin& RobotUnitComponentPluginUser::getRobotUnitComponentPlugin()
+    {
+        return *plugin;
+    }
 }
 
 
diff --git a/source/RobotAPI/libraries/RobotAPIComponentPlugins/RobotUnitComponentPlugin.h b/source/RobotAPI/libraries/RobotAPIComponentPlugins/RobotUnitComponentPlugin.h
index 4dc53dcb9fff70332663f1dd4a0211f3fdfd916d..b3cbf9a3b1e43d262370fc3b6082d07612a9c7cc 100644
--- a/source/RobotAPI/libraries/RobotAPIComponentPlugins/RobotUnitComponentPlugin.h
+++ b/source/RobotAPI/libraries/RobotAPIComponentPlugins/RobotUnitComponentPlugin.h
@@ -20,11 +20,14 @@ namespace armarx
 
             void postCreatePropertyDefinitions(PropertyDefinitionsPtr& properties) override;
 
-            RobotUnitInterfacePrx getRobotUnit();
+            RobotUnitInterfacePrx getRobotUnit() const;
 
+            void setRobotUnitName(const std::string& name);
+            const std::string& getRobotUnitName() const;
         private:
             static constexpr const char* PROPERTY_NAME = "RobotUnitName";
             RobotUnitInterfacePrx _robotUnit;
+            std::string           _robotUnitName;
         };
 
     }
@@ -39,8 +42,8 @@ namespace armarx
     {
     public:
         RobotUnitComponentPluginUser();
-        RobotUnitInterfacePrx getRobotUnit();
-
+        RobotUnitInterfacePrx getRobotUnit() const;
+        plugins::RobotUnitComponentPlugin& getRobotUnitComponentPlugin();
     private:
         armarx::plugins::RobotUnitComponentPlugin* plugin = nullptr;
     };
diff --git a/source/RobotAPI/libraries/RobotAPINJointControllers/BimanualForceControllers/NJointBimanualObjLevelController.cpp b/source/RobotAPI/libraries/RobotAPINJointControllers/BimanualForceControllers/NJointBimanualObjLevelController.cpp
index 7f5f67758fe368038d697df0beda4f96b22af98a..37cf71bfc6ab71a1eef4c148be3d16dbc60cffdb 100644
--- a/source/RobotAPI/libraries/RobotAPINJointControllers/BimanualForceControllers/NJointBimanualObjLevelController.cpp
+++ b/source/RobotAPI/libraries/RobotAPINJointControllers/BimanualForceControllers/NJointBimanualObjLevelController.cpp
@@ -105,6 +105,7 @@ namespace armarx
         tcpLeft = leftRNS->getTCP();
         tcpRight = rightRNS->getTCP();
 
+        //initialize control parameters
         KpImpedance.setZero(cfg->KpImpedance.size());
         ARMARX_CHECK_EQUAL(cfg->KpImpedance.size(), 12);
 
@@ -145,6 +146,15 @@ namespace armarx
             KmAdmittance(i) = cfg->KmAdmittance.at(i);
         }
 
+
+        Inferface2rtData initInt2rtData;
+        initInt2rtData.KpImpedance = KpImpedance;
+        initInt2rtData.KdImpedance = KdImpedance;
+        initInt2rtData.KmAdmittance = KmAdmittance;
+        initInt2rtData.KpAdmittance = KpAdmittance;
+        initInt2rtData.KdAdmittance = KdAdmittance;
+        interface2rtBuffer.reinitAllBuffers(initInt2rtData);
+
         leftDesiredJointValues.resize(leftTargets.size());
         ARMARX_CHECK_EQUAL(cfg->leftDesiredJointValues.size(), leftTargets.size());
 
@@ -192,6 +202,9 @@ namespace armarx
         ControlInterfaceData initInterfaceData;
         initInterfaceData.currentLeftPose = tcpLeft->getPoseInRootFrame();
         initInterfaceData.currentRightPose = tcpRight->getPoseInRootFrame();
+        initInterfaceData.currentObjPose = boxInitialPose;
+        initInterfaceData.currentObjForce.setZero();
+        initInterfaceData.currentObjVel.setZero();
         controlInterfaceBuffer.reinitAllBuffers(initInterfaceData);
 
 
@@ -255,6 +268,10 @@ namespace armarx
         {
             targetWrench(i) = cfg->targetWrench[i];
         }
+
+
+
+
     }
 
 
@@ -315,7 +332,6 @@ namespace armarx
 
         controlInterfaceBuffer.getWriteBuffer().currentLeftPose = currentLeftPose;
         controlInterfaceBuffer.getWriteBuffer().currentRightPose = currentRightPose;
-        controlInterfaceBuffer.commitWrite();
         double deltaT = timeSinceLastIteration.toSecondsDouble();
 
         ftcalibrationTimer += deltaT;
@@ -343,6 +359,13 @@ namespace armarx
             ARMARX_INFO << "modified right pose:\n " << rightPose;
         }
 
+        // --------------------------------------------- get control parameters ---------------------------------------
+        KpImpedance = interface2rtBuffer.getUpToDateReadBuffer().KpImpedance;
+        KdImpedance = interface2rtBuffer.getUpToDateReadBuffer().KdImpedance;
+        KmAdmittance = interface2rtBuffer.getUpToDateReadBuffer().KmAdmittance;
+        KpAdmittance = interface2rtBuffer.getUpToDateReadBuffer().KpAdmittance;
+        KdAdmittance = interface2rtBuffer.getUpToDateReadBuffer().KdAdmittance;
+
         if (ftcalibrationTimer < cfg->ftCalibrationTime)
         {
             ftOffset.block<3, 1>(0, 0) = 0.5 * ftOffset.block<3, 1>(0, 0) + 0.5 * leftForceTorque->force;
@@ -454,6 +477,8 @@ namespace armarx
         rt2ControlBuffer.getWriteBuffer().currentTime += deltaT;
         rt2ControlBuffer.commitWrite();
 
+
+
         // --------------------------------------------- get ft sensor ---------------------------------------------
         // static compensation
         Eigen::Vector3f gravity;
@@ -504,11 +529,20 @@ namespace armarx
             }
         }
 
+        // pass sensor value to statechart
+        controlInterfaceBuffer.getWriteBuffer().currentObjPose = boxCurrentPose;
+        controlInterfaceBuffer.getWriteBuffer().currentObjVel = boxCurrentTwist.head(3);
+        controlInterfaceBuffer.getWriteBuffer().currentObjForce = objFTValue.head(3);
+        controlInterfaceBuffer.commitWrite();
+
 
         // --------------------------------------------- get MP target ---------------------------------------------
         Eigen::Matrix4f boxPose = rtGetControlStruct().boxPose;
         Eigen::VectorXf boxTwist = rtGetControlStruct().boxTwist;
 
+
+
+
         // --------------------------------------------- obj admittance control ---------------------------------------------
         // admittance
         Eigen::VectorXf objPoseError(6);
@@ -744,9 +778,109 @@ namespace armarx
         //        LockGuardType guard(controllerMutex);
         ARMARX_INFO << "setting via points ";
         objectDMP->setViaPose(u, viapoint);
+    }
+
+    void NJointBimanualObjLevelController::removeAllViaPoints(const Ice::Current&)
+    {
+        objectDMP->removeAllViaPoints();
+    }
+
+    void NJointBimanualObjLevelController::setKpImpedance(const Ice::FloatSeq& value, const Ice::Current&)
+    {
+        Eigen::VectorXf setpoint;
+        setpoint.setZero(value.size());
+        ARMARX_CHECK_EQUAL(value.size(), 12);
+
+        for (size_t i = 0; i < value.size(); ++i)
+        {
+            setpoint(i) = value.at(i);
+        }
+
+        LockGuardType guard {interfaceDataMutex};
+        interface2rtBuffer.getWriteBuffer().KpImpedance = setpoint;
+        interface2rtBuffer.commitWrite();
+
+    }
+
+    void NJointBimanualObjLevelController::setKdImpedance(const Ice::FloatSeq& value, const Ice::Current&)
+    {
+        Eigen::VectorXf setpoint;
+        setpoint.setZero(value.size());
+        ARMARX_CHECK_EQUAL(value.size(), 12);
+
+        for (size_t i = 0; i < value.size(); ++i)
+        {
+            setpoint(i) = value.at(i);
+        }
+
+        LockGuardType guard {interfaceDataMutex};
+        interface2rtBuffer.getWriteBuffer().KdImpedance = setpoint;
+        interface2rtBuffer.commitWrite();
+    }
+
+    void NJointBimanualObjLevelController::setKpAdmittance(const Ice::FloatSeq& value, const Ice::Current&)
+    {
+        Eigen::VectorXf setpoint;
+        setpoint.setZero(value.size());
+        ARMARX_CHECK_EQUAL(value.size(), 6);
+
+        for (size_t i = 0; i < value.size(); ++i)
+        {
+            setpoint(i) = value.at(i);
+        }
 
+        LockGuardType guard {interfaceDataMutex};
+        interface2rtBuffer.getWriteBuffer().KpAdmittance = setpoint;
+        interface2rtBuffer.commitWrite();
     }
 
+    void NJointBimanualObjLevelController::setKdAdmittance(const Ice::FloatSeq& value, const Ice::Current&)
+    {
+        Eigen::VectorXf setpoint;
+        setpoint.setZero(value.size());
+        ARMARX_CHECK_EQUAL(value.size(), 6);
+
+        for (size_t i = 0; i < value.size(); ++i)
+        {
+            setpoint(i) = value.at(i);
+        }
+
+        LockGuardType guard {interfaceDataMutex};
+        interface2rtBuffer.getWriteBuffer().KdAdmittance = setpoint;
+        interface2rtBuffer.commitWrite();
+    }
+
+    std::vector<float> NJointBimanualObjLevelController::getCurrentObjVel(const Ice::Current&)
+    {
+        Eigen::Vector3f tvel = controlInterfaceBuffer.getUpToDateReadBuffer().currentObjVel;
+        std::vector<float> tvelvec = {tvel(0), tvel(1), tvel(2)};
+        return tvelvec;
+    }
+
+    std::vector<float> NJointBimanualObjLevelController::getCurrentObjForce(const Ice::Current&)
+    {
+        Eigen::Vector3f fvel = controlInterfaceBuffer.getUpToDateReadBuffer().currentObjForce;
+        std::vector<float> fvelvec = {fvel(0), fvel(1), fvel(2)};
+        return fvelvec;
+    }
+
+    void NJointBimanualObjLevelController::setKmAdmittance(const Ice::FloatSeq& value, const Ice::Current&)
+    {
+        Eigen::VectorXf setpoint;
+        setpoint.setZero(value.size());
+        ARMARX_CHECK_EQUAL(value.size(), 6);
+
+        for (size_t i = 0; i < value.size(); ++i)
+        {
+            setpoint(i) = value.at(i);
+        }
+
+        LockGuardType guard {interfaceDataMutex};
+        interface2rtBuffer.getWriteBuffer().KmAdmittance = setpoint;
+        interface2rtBuffer.commitWrite();
+    }
+
+
     void NJointBimanualObjLevelController::onPublish(const SensorAndControl&, const DebugDrawerInterfacePrx&, const DebugObserverInterfacePrx& debugObs)
     {
 
@@ -891,6 +1025,8 @@ namespace armarx
 
     void NJointBimanualObjLevelController::onInitNJointController()
     {
+
+
         ARMARX_INFO << "init ...";
         runTask("NJointBimanualObjLevelController", [&]
         {
diff --git a/source/RobotAPI/libraries/RobotAPINJointControllers/BimanualForceControllers/NJointBimanualObjLevelController.h b/source/RobotAPI/libraries/RobotAPINJointControllers/BimanualForceControllers/NJointBimanualObjLevelController.h
index 7f1c10d711309e81271887feaade945462c23aab..341de9689094e1eee9c9a497c638f79fd2bbfa1d 100644
--- a/source/RobotAPI/libraries/RobotAPINJointControllers/BimanualForceControllers/NJointBimanualObjLevelController.h
+++ b/source/RobotAPI/libraries/RobotAPINJointControllers/BimanualForceControllers/NJointBimanualObjLevelController.h
@@ -70,11 +70,22 @@ namespace armarx
 
         void setGoals(const Ice::DoubleSeq& goals, const Ice::Current&);
         void setViaPoints(Ice::Double u, const Ice::DoubleSeq& viapoint, const Ice::Current&);
+        void removeAllViaPoints(const Ice::Current&);
+
         double getVirtualTime(const Ice::Current&)
         {
             return virtualtimer;
         }
 
+        void setKpImpedance(const Ice::FloatSeq& value, const Ice::Current&);
+        void setKdImpedance(const Ice::FloatSeq& value, const Ice::Current&);
+        void setKmAdmittance(const Ice::FloatSeq& value, const Ice::Current&);
+        void setKpAdmittance(const Ice::FloatSeq& value, const Ice::Current&);
+        void setKdAdmittance(const Ice::FloatSeq& value, const Ice::Current&);
+
+        std::vector<float> getCurrentObjVel(const Ice::Current&);
+        std::vector<float> getCurrentObjForce(const Ice::Current&);
+
     protected:
         virtual void onPublish(const SensorAndControl&, const DebugDrawerInterfacePrx&, const DebugObserverInterfacePrx&);
 
@@ -175,10 +186,25 @@ namespace armarx
         {
             Eigen::Matrix4f currentLeftPose;
             Eigen::Matrix4f currentRightPose;
+            Eigen::Matrix4f currentObjPose;
+            Eigen::Vector3f currentObjVel;
+            Eigen::Vector3f currentObjForce;
         };
 
         TripleBuffer<ControlInterfaceData> controlInterfaceBuffer;
 
+        struct Inferface2rtData
+        {
+            Eigen::VectorXf KpImpedance;
+            Eigen::VectorXf KdImpedance;
+            Eigen::VectorXf KmAdmittance;
+            Eigen::VectorXf KpAdmittance;
+            Eigen::VectorXf KdAdmittance;
+        };
+        TripleBuffer<Inferface2rtData> interface2rtBuffer;
+
+
+
         std::vector<ControlTarget1DoFActuatorTorque*> leftTargets;
         std::vector<const SensorValue1DoFActuatorAcceleration*> leftAccelerationSensors;
         std::vector<const SensorValue1DoFActuatorVelocity*> leftVelocitySensors;
@@ -203,6 +229,7 @@ namespace armarx
         double virtualtimer;
 
         mutable MutexType controllerMutex;
+        mutable MutexType interfaceDataMutex;
         Eigen::VectorXf leftDesiredJointValues;
         Eigen::VectorXf rightDesiredJointValues;