diff --git a/data/RobotAPI/robotStateMemoryConfig.txt b/data/RobotAPI/robotStateMemoryConfig.txt
index bc928c16990df50ca55c96550f320efac999c332..e6e6498e4ce03f08c6b930cb3b73c678a578f34c 100644
--- a/data/RobotAPI/robotStateMemoryConfig.txt
+++ b/data/RobotAPI/robotStateMemoryConfig.txt
@@ -1,5 +1,7 @@
 // Configuration set for the Humanoid Robot ARMAR-6
-// Left Hand unit
+
+// Reft Hand
+
 sens.Index L 1 Joint.acceleration => HandL
 sens.Index L 1 Joint.gravityTorque  => HandL
 sens.Index L 1 Joint.inertiaTorque  => HandL
@@ -103,7 +105,9 @@ sens.Thumb L 2 Joint.position => HandL
 sens.Thumb L 2 Joint.torque => HandL
 sens.Thumb L 2 Joint.velocity => HandL
 
-// Right Hand unit
+
+// Right Hand
+
 sens.Index R 1 Joint.acceleration  => HandR
 sens.Index R 1 Joint.gravityTorque  => HandR
 sens.Index R 1 Joint.inertiaTorque  => HandR
@@ -185,7 +189,165 @@ sens.Thumb R 2 Joint.position => HandR
 sens.Thumb R 2 Joint.torque => HandR
 sens.Thumb R 2 Joint.velocity => HandR
 
+sens.Pinky R 1 Joint.acceleration => HandR
+sens.Pinky R 1 Joint.gravityTorque => HandR
+sens.Pinky R 1 Joint.inertiaTorque => HandR
+sens.Pinky R 1 Joint.inverseDynamicsTorque => HandR
+sens.Pinky R 1 Joint.position => HandR
+sens.Pinky R 1 Joint.torque => HandR
+sens.Pinky R 1 Joint.velocity => HandR
+sens.Pinky R 2 Joint.acceleration => HandR
+sens.Pinky R 2 Joint.gravityTorque => HandR
+sens.Pinky R 2 Joint.inertiaTorque => HandR
+sens.Pinky R 2 Joint.inverseDynamicsTorque => HandR
+sens.Pinky R 2 Joint.position => HandR
+sens.Pinky R 2 Joint.torque => HandR
+sens.Pinky R 2 Joint.velocity => HandR
+sens.Pinky R 3 Joint.acceleration => HandR
+sens.Pinky R 3 Joint.gravityTorque => HandR
+sens.Pinky R 3 Joint.inertiaTorque => HandR
+sens.Pinky R 3 Joint.inverseDynamicsTorque => HandR
+sens.Pinky R 3 Joint.position => HandR
+sens.Pinky R 3 Joint.torque => HandR
+sens.Pinky R 3 Joint.velocity => HandR
+
+
+// Arm L
+
+sens.ArmL1_Cla1.acceleration => ArmL
+sens.ArmL1_Cla1.gravityTorque  => ArmL
+sens.ArmL1_Cla1.inertiaTorque  => ArmL
+sens.ArmL1_Cla1.inverseDynamicsTorque  => ArmL
+sens.ArmL1_Cla1.position  => ArmL
+sens.ArmL1_Cla1.torque  => ArmL
+sens.ArmL1_Cla1.velocity  => ArmL
+
+sens.ArmL2_Sho1.acceleration => ArmL
+sens.ArmL2_Sho1.gravityTorque  => ArmL
+sens.ArmL2_Sho1.inertiaTorque  => ArmL
+sens.ArmL2_Sho1.inverseDynamicsTorque  => ArmL
+sens.ArmL2_Sho1.position  => ArmL
+sens.ArmL2_Sho1.torque  => ArmL
+sens.ArmL2_Sho1.velocity  => ArmL
+
+sens.ArmL3_Sho2.acceleration => ArmL
+sens.ArmL3_Sho2.gravityTorque  => ArmL
+sens.ArmL3_Sho2.inertiaTorque  => ArmL
+sens.ArmL3_Sho2.inverseDynamicsTorque  => ArmL
+sens.ArmL3_Sho2.position  => ArmL
+sens.ArmL3_Sho2.torque  => ArmL
+sens.ArmL3_Sho2.velocity  => ArmL
+
+sens.ArmL4_Sho3.acceleration => ArmL
+sens.ArmL4_Sho3.gravityTorque  => ArmL
+sens.ArmL4_Sho3.inertiaTorque  => ArmL
+sens.ArmL4_Sho3.inverseDynamicsTorque  => ArmL
+sens.ArmL4_Sho3.position  => ArmL
+sens.ArmL4_Sho3.torque  => ArmL
+sens.ArmL4_Sho3.velocity  => ArmL
+
+sens.ArmL5_Elb1.acceleration => ArmL
+sens.ArmL5_Elb1.gravityTorque  => ArmL
+sens.ArmL5_Elb1.inertiaTorque  => ArmL
+sens.ArmL5_Elb1.inverseDynamicsTorque  => ArmL
+sens.ArmL5_Elb1.position  => ArmL
+sens.ArmL5_Elb1.torque  => ArmL
+sens.ArmL5_Elb1.velocity  => ArmL
+
+sens.ArmL6_Elb2.acceleration => ArmL
+sens.ArmL6_Elb2.gravityTorque  => ArmL
+sens.ArmL6_Elb2.inertiaTorque  => ArmL
+sens.ArmL6_Elb2.inverseDynamicsTorque  => ArmL
+sens.ArmL6_Elb2.position  => ArmL
+sens.ArmL6_Elb2.torque  => ArmL
+sens.ArmL6_Elb2.velocity  => ArmL
+
+sens.ArmL7_Wri1.acceleration => ArmL
+sens.ArmL7_Wri1.gravityTorque  => ArmL
+sens.ArmL7_Wri1.inertiaTorque  => ArmL
+sens.ArmL7_Wri1.inverseDynamicsTorque  => ArmL
+sens.ArmL7_Wri1.position  => ArmL
+sens.ArmL7_Wri1.torque  => ArmL
+sens.ArmL7_Wri1.velocity  => ArmL
+
+sens.ArmL8_Wri2.acceleration => ArmL
+sens.ArmL8_Wri2.gravityTorque  => ArmL
+sens.ArmL8_Wri2.inertiaTorque  => ArmL
+sens.ArmL8_Wri2.inverseDynamicsTorque  => ArmL
+sens.ArmL8_Wri2.position  => ArmL
+sens.ArmL8_Wri2.torque  => ArmL
+sens.ArmL8_Wri2.velocity  => ArmL
+
+
+// Arm R
+
+sens.ArmR1_Cla1.acceleration => ArmR
+sens.ArmR1_Cla1.gravityTorque  => ArmR
+sens.ArmR1_Cla1.inertiaTorque  => ArmR
+sens.ArmR1_Cla1.inverseDynamicsTorque  => ArmR
+sens.ArmR1_Cla1.position  => ArmR
+sens.ArmR1_Cla1.torque  => ArmR
+sens.ArmR1_Cla1.velocity  => ArmR
+
+sens.ArmR2_Sho1.acceleration => ArmR
+sens.ArmR2_Sho1.gravityTorque  => ArmR
+sens.ArmR2_Sho1.inertiaTorque  => ArmR
+sens.ArmR2_Sho1.inverseDynamicsTorque  => ArmR
+sens.ArmR2_Sho1.position  => ArmR
+sens.ArmR2_Sho1.torque  => ArmR
+sens.ArmR2_Sho1.velocity  => ArmR
+
+sens.ArmR3_Sho2.acceleration => ArmR
+sens.ArmR3_Sho2.gravityTorque  => ArmR
+sens.ArmR3_Sho2.inertiaTorque  => ArmR
+sens.ArmR3_Sho2.inverseDynamicsTorque  => ArmR
+sens.ArmR3_Sho2.position  => ArmR
+sens.ArmR3_Sho2.torque  => ArmR
+sens.ArmR3_Sho2.velocity  => ArmR
+
+sens.ArmR4_Sho3.acceleration => ArmR
+sens.ArmR4_Sho3.gravityTorque  => ArmR
+sens.ArmR4_Sho3.inertiaTorque  => ArmR
+sens.ArmR4_Sho3.inverseDynamicsTorque  => ArmR
+sens.ArmR4_Sho3.position  => ArmR
+sens.ArmR4_Sho3.torque  => ArmR
+sens.ArmR4_Sho3.velocity  => ArmR
+
+sens.ArmR5_Elb1.acceleration => ArmR
+sens.ArmR5_Elb1.gravityTorque  => ArmR
+sens.ArmR5_Elb1.inertiaTorque  => ArmR
+sens.ArmR5_Elb1.inverseDynamicsTorque  => ArmR
+sens.ArmR5_Elb1.position  => ArmR
+sens.ArmR5_Elb1.torque  => ArmR
+sens.ArmR5_Elb1.velocity  => ArmR
+
+sens.ArmR6_Elb2.acceleration => ArmR
+sens.ArmR6_Elb2.gravityTorque  => ArmR
+sens.ArmR6_Elb2.inertiaTorque  => ArmR
+sens.ArmR6_Elb2.inverseDynamicsTorque  => ArmR
+sens.ArmR6_Elb2.position  => ArmR
+sens.ArmR6_Elb2.torque  => ArmR
+sens.ArmR6_Elb2.velocity  => ArmR
+
+sens.ArmR7_Wri1.acceleration => ArmR
+sens.ArmR7_Wri1.gravityTorque  => ArmR
+sens.ArmR7_Wri1.inertiaTorque  => ArmR
+sens.ArmR7_Wri1.inverseDynamicsTorque  => ArmR
+sens.ArmR7_Wri1.position  => ArmR
+sens.ArmR7_Wri1.torque  => ArmR
+sens.ArmR7_Wri1.velocity  => ArmR
+
+sens.ArmR8_Wri2.acceleration => ArmR
+sens.ArmR8_Wri2.gravityTorque  => ArmR
+sens.ArmR8_Wri2.inertiaTorque  => ArmR
+sens.ArmR8_Wri2.inverseDynamicsTorque  => ArmR
+sens.ArmR8_Wri2.position  => ArmR
+sens.ArmR8_Wri2.torque  => ArmR
+sens.ArmR8_Wri2.velocity  => ArmR
+
+
 // Neck
+
 sens.Neck_1_Yaw.acceleration => Neck
 sens.Neck_1_Yaw.gravityTorque => Neck
 sens.Neck_1_Yaw.inertiaTorque => Neck
@@ -193,10 +355,70 @@ sens.Neck_1_Yaw.inverseDynamicsTorque => Neck
 sens.Neck_1_Yaw.position => Neck
 sens.Neck_1_Yaw.torque => Neck
 sens.Neck_1_Yaw.velocity => Neck
+
 sens.Neck_2_Pitch.acceleration => Neck
 sens.Neck_2_Pitch.gravityTorque => Neck
 sens.Neck_2_Pitch.inertiaTorque => Neck
-sens.Neck_2_Pitch.inverseDynamicsTorque 
+sens.Neck_2_Pitch.inverseDynamicsTorque => Neck
 sens.Neck_2_Pitch.position => Neck
 sens.Neck_2_Pitch.torque => Neck
 sens.Neck_2_Pitch.velocity => Neck
+
+
+// Torso
+
+sens.TorsoJoint.acceleration => Torso
+sens.TorsoJoint.gravityTorque  => Torso
+sens.TorsoJoint.inertiaTorque  => Torso
+sens.TorsoJoint.inverseDynamicsTorque  => Torso
+sens.TorsoJoint.position  => Torso
+sens.TorsoJoint.torque  => Torso
+sens.TorsoJoint.velocity  => Torso
+
+
+// Platform
+
+sens.Platform.accelerationX => Platform
+sens.Platform.accelerationY => Platform
+sens.Platform.accelerationRotation => Platform
+sens.Platform.absolutePositionX => Platform
+sens.Platform.absolutePositionY => Platform
+sens.Platform.absolutePositionRotation => Platform
+sens.Platform.relativePositionX => Platform
+sens.Platform.relativePositionY => Platform
+sens.Platform.relativePositionRotation => Platform
+sens.Platform.velocityX  => Platform
+sens.Platform.velocityY  => Platform
+sens.Platform.velocityRotation  => Platform
+
+
+// FT L
+
+sens.FT L.fx => FT L
+sens.FT L.fy => FT L
+sens.FT L.fz => FT L
+sens.FT L.gravCompFx => FT L
+sens.FT L.gravCompFy => FT L
+sens.FT L.gravCompFz => FT L
+sens.FT L.gravCompTx => FT L
+sens.FT L.gravCompTy => FT L
+sens.FT L.gravCompTz => FT L
+sens.FT L.tx => FT L
+sens.FT L.ty => FT L
+sens.FT L.tz => FT L
+
+
+// FT R
+
+sens.FT R.fx => FT R
+sens.FT R.fy => FT R
+sens.FT R.fz => FT R
+sens.FT R.gravCompFx => FT R
+sens.FT R.gravCompFy => FT R
+sens.FT R.gravCompFz => FT R
+sens.FT R.gravCompTx => FT R
+sens.FT R.gravCompTy => FT R
+sens.FT R.gravCompTz => FT R
+sens.FT R.tx => FT R
+sens.FT R.ty => FT R
+sens.FT R.tz => FT R
diff --git a/source/RobotAPI/components/armem/server/ExampleMemory/ExampleMemory.cpp b/source/RobotAPI/components/armem/server/ExampleMemory/ExampleMemory.cpp
index 3ed4b4612c5dd3f6e0afbd71630dba7a4753f460..e007e8f5e3ad47c57f9bb71c75e517d57af1addf 100644
--- a/source/RobotAPI/components/armem/server/ExampleMemory/ExampleMemory.cpp
+++ b/source/RobotAPI/components/armem/server/ExampleMemory/ExampleMemory.cpp
@@ -122,7 +122,7 @@ namespace armarx
         using namespace armarx::RemoteGui::Client;
 
         {
-            std::scoped_lock lock(workingMemoryMutex);
+            // Core segments are locked by MemoryRemoteGui.
             tab.memoryGroup = armem::server::MemoryRemoteGui().makeGroupBox(workingMemory);
         }
 
diff --git a/source/RobotAPI/components/armem/server/ObjectMemory/ObjectMemory.cpp b/source/RobotAPI/components/armem/server/ObjectMemory/ObjectMemory.cpp
index 91ea5b23400f568891326f6dd6c79b5e603d229c..c624379b89ae336aa561e364706f3780b7fbf0e9 100644
--- a/source/RobotAPI/components/armem/server/ObjectMemory/ObjectMemory.cpp
+++ b/source/RobotAPI/components/armem/server/ObjectMemory/ObjectMemory.cpp
@@ -59,22 +59,27 @@ namespace armarx::armem::server::obj
         return defs;
     }
 
+
     ObjectMemory::ObjectMemory() :
         server::ComponentPluginUser(),
-        instance::SegmentAdapter(server::ComponentPluginUser::iceMemory,
-                                 server::ComponentPluginUser::workingMemoryMutex),
-        classSegment(server::ComponentPluginUser::iceMemory,
-                     server::ComponentPluginUser::workingMemoryMutex),
-        attachmentSegment(server::ComponentPluginUser::iceMemory,
-                          server::ComponentPluginUser::workingMemoryMutex)
+        instance::SegmentAdapter(server::ComponentPluginUser::iceMemory),
+        classSegment(server::ComponentPluginUser::iceMemory),
+        attachmentSegment(server::ComponentPluginUser::iceMemory)
+    {
+    }
+
+
+    ObjectMemory::~ObjectMemory()
     {
     }
 
+
     std::string ObjectMemory::getDefaultName() const
     {
         return "ObjectMemory";
     }
 
+
     void ObjectMemory::onInitComponent()
     {
         workingMemory.name() = defaultMemoryName;
@@ -114,6 +119,7 @@ namespace armarx::armem::server::obj
         });
     }
 
+
     void ObjectMemory::onConnectComponent()
     {
         // onConnect can be called multiple times, but addRobot will fail if called more than once with the same ID
@@ -141,17 +147,17 @@ namespace armarx::armem::server::obj
             ArVizComponentPluginUser::getArvizClient()
         );
 
-        attachmentSegment.connect(
-            ArVizComponentPluginUser::getArvizClient()
-        );
+        attachmentSegment.connect();
 
         RemoteGui_startRunningTask();
     }
 
+
     void ObjectMemory::onDisconnectComponent()
     {
     }
 
+
     void ObjectMemory::onExitComponent()
     {
     }
diff --git a/source/RobotAPI/components/armem/server/ObjectMemory/ObjectMemory.h b/source/RobotAPI/components/armem/server/ObjectMemory/ObjectMemory.h
index f29b2cef93efb2aa35a7983f4dce87d3db854b80..b90406be31ac76a40172d67076f931ebb1a6ba1a 100644
--- a/source/RobotAPI/components/armem/server/ObjectMemory/ObjectMemory.h
+++ b/source/RobotAPI/components/armem/server/ObjectMemory/ObjectMemory.h
@@ -38,8 +38,6 @@
 
 #include <RobotAPI/libraries/armem_objects/server/class/Segment.h>
 #include <RobotAPI/libraries/armem_objects/server/instance/SegmentAdapter.h>
-#include <RobotAPI/libraries/armem_objects/server/articulated_object_instance/Segment.h>
-#include <RobotAPI/libraries/armem_objects/server/articulated_object_class/Segment.h>
 #include <RobotAPI/libraries/armem_objects/server/attachments/Segment.h>
 
 
@@ -81,6 +79,7 @@ namespace armarx::armem::server::obj
     public:
 
         ObjectMemory();
+        virtual ~ObjectMemory();
 
 
         /// @see armarx::ManagedIceObject::getDefaultName()
diff --git a/source/RobotAPI/components/armem/server/RobotStateMemory/CMakeLists.txt b/source/RobotAPI/components/armem/server/RobotStateMemory/CMakeLists.txt
index 137453970c1a97f0f3bd9653c067e959db21b4a5..a25161ff2cdf35173921720f68ad5bcec16cba30 100644
--- a/source/RobotAPI/components/armem/server/RobotStateMemory/CMakeLists.txt
+++ b/source/RobotAPI/components/armem/server/RobotStateMemory/CMakeLists.txt
@@ -2,20 +2,31 @@ armarx_component_set_name("RobotStateMemory")
 
 
 set(COMPONENT_LIBS
+    # ArmarXCore
     ArmarXCore ArmarXCoreInterfaces  # for DebugObserverInterface
+    ArmarXCoreComponentPlugins
+    # ArmarXGUI
     ArmarXGuiComponentPlugins
-    RobotAPICore
-    RobotAPIInterfaces 
-    RobotAPIComponentPlugins 
+    # RobotAPI
+    RobotAPICore RobotAPIInterfaces
+    RobotAPIComponentPlugins
     armem
     armem_robot_state
 )
 
 set(SOURCES
+    aron_conversions.cpp
     RobotStateMemory.cpp
+    RobotStateWriter.cpp
+    RobotUnitData.cpp
+    RobotUnitReader.cpp
 )
 set(HEADERS
+    aron_conversions.h
     RobotStateMemory.h
+    RobotStateWriter.h
+    RobotUnitData.h
+    RobotUnitReader.h
 )
 
 armarx_add_component("${SOURCES}" "${HEADERS}")
diff --git a/source/RobotAPI/components/armem/server/RobotStateMemory/RobotStateMemory.cpp b/source/RobotAPI/components/armem/server/RobotStateMemory/RobotStateMemory.cpp
index 111cced66ba9f678ba852d1005a10ded834d0946..c108b6e78ae6932f129ab4473f235d5f9740ea3b 100644
--- a/source/RobotAPI/components/armem/server/RobotStateMemory/RobotStateMemory.cpp
+++ b/source/RobotAPI/components/armem/server/RobotStateMemory/RobotStateMemory.cpp
@@ -23,46 +23,40 @@
 #include "RobotStateMemory.h"
 
 // STD
-#include <algorithm>
-#include <iostream>
-#include <fstream>
 #include <memory>
 
-// Eigen
-#include <Eigen/Core>
-#include <Eigen/Geometry>
-
 // Simox
 #include <SimoxUtility/algorithm/string.h>
-#include <SimoxUtility/math/convert/rpy_to_mat3f.h>
 
 // ArmarX
-#include <ArmarXCore/core/logging/Logging.h>
 #include <ArmarXCore/core/exceptions/local/ExpressionException.h>
+#include <ArmarXCore/core/logging/Logging.h>
 #include <ArmarXCore/core/system/ArmarXDataPath.h>
+#include <ArmarXCore/libraries/ArmarXCoreComponentPlugins/DebugObserverComponentPlugin.h>
 
 #include <RobotAPI/libraries/armem/core/error.h>
-#include <RobotAPI/libraries/armem/server/MemoryRemoteGui.h>
-#include <RobotAPI/libraries/aron/core/navigator/data/AllNavigators.h>
-#include <RobotAPI/libraries/aron/core/navigator/type/AllNavigators.h>
 #include <RobotAPI/libraries/armem_robot_state/server/common/Visu.h>
-#include <RobotAPI/libraries/armem_robot_state/aron/Transform.aron.generated.h>
-#include <RobotAPI/libraries/core/FramedPose.h>
-#include <RobotAPI/libraries/armem/core/Time.h>
-#include <RobotAPI/libraries/core/Pose.h>
+#include <RobotAPI/libraries/RobotAPIComponentPlugins/RobotUnitComponentPlugin.h>
+
+#include "aron_conversions.h"
+
 
 namespace armarx::armem::server::robot_state
 {
+
     RobotStateMemory::RobotStateMemory()
-        : descriptionSegment(server::ComponentPluginUser::iceMemory,
-                             server::ComponentPluginUser::workingMemoryMutex),
-          proprioceptionSegment(server::ComponentPluginUser::iceMemory,
-                                server::ComponentPluginUser::workingMemoryMutex),
-          localizationSegment(server::ComponentPluginUser::iceMemory,
-                              server::ComponentPluginUser::workingMemoryMutex),
+        : descriptionSegment(server::ComponentPluginUser::iceMemory),
+          proprioceptionSegment(server::ComponentPluginUser::iceMemory),
+          localizationSegment(server::ComponentPluginUser::iceMemory),
           commonVisu(descriptionSegment, proprioceptionSegment, localizationSegment)
     {
+        addPlugin(debugObserver);
+        ARMARX_CHECK_NOT_NULL(debugObserver);
+        addPlugin(robotUnit.plugin);
+        ARMARX_CHECK_NOT_NULL(robotUnit.plugin);
 
+        robotUnit.reader.setTag(getName());
+        robotUnit.writer.setTag(getName());
     }
 
     RobotStateMemory::~RobotStateMemory() = default;
@@ -79,17 +73,22 @@ namespace armarx::armem::server::robot_state
 
         const std::string robotUnitPrefix{sensorValuePrefix};
 
-        defs->optional(robotUnitSensorPrefix, robotUnitPrefix + "SensorValuePrefix", "Prefix of all sensor values");
-        defs->optional(robotUnitMemoryBatchSize, robotUnitPrefix + "MemoryBatchSize", "The size of the entity snapshot to send to the memory. Min is 1");
-        defs->optional(robotUnitPollFrequency, robotUnitPrefix + "UpdateFrequency", "The frequency in Hz to store values. All other values get discarded. Min is 1, max is " + std::to_string(ROBOT_UNIT_MAXIMUM_FREQUENCY));
-        defs->optional(robotUnitConfigPath, robotUnitPrefix + "ConfigPath", "Specify a configuration file to group the sensor values specifically.");
-
-        descriptionSegment.defineProperties(defs);
-        proprioceptionSegment.defineProperties(defs);
-        localizationSegment.defineProperties(defs);
-        commonVisu.defineProperties(defs);
-
-        setRobotUnitAsOptionalDependency();
+        defs->optional(robotUnit.reader.properties.sensorPrefix, robotUnitPrefix + "SensorValuePrefix",
+                       "Prefix of all sensor values.");
+        defs->optional(robotUnit.writer.properties.memoryBatchSize, robotUnitPrefix + "MemoryBatchSize",
+                       "The size of the entity snapshot to send to the memory. Minimum is 1.")
+        .setMin(1);
+        defs->optional(robotUnit.pollFrequency, robotUnitPrefix + "UpdateFrequency",
+                       "The frequency to store values in Hz. All other values get discarded. "
+                       "Minimum is 1, max is " + std::to_string(ROBOT_UNIT_MAXIMUM_FREQUENCY) + ".")
+        .setMin(1).setMax(ROBOT_UNIT_MAXIMUM_FREQUENCY);
+        defs->optional(robotUnit.configPath, robotUnitPrefix + "ConfigPath",
+                       "Specify a configuration file to group the sensor values specifically.");
+
+        descriptionSegment.defineProperties(defs, prefix + "desc.");
+        proprioceptionSegment.defineProperties(defs, prefix + "prop.");
+        localizationSegment.defineProperties(defs, prefix + "loc.");
+        commonVisu.defineProperties(defs, prefix + "visu.");
 
         return defs;
     }
@@ -103,17 +102,16 @@ namespace armarx::armem::server::robot_state
 
     void RobotStateMemory::onInitComponent()
     {
-
         descriptionSegment.init();
         proprioceptionSegment.init();
         localizationSegment.init();
         commonVisu.init();
 
-        robotUnitMemoryBatchSize = std::max((unsigned int) 1, robotUnitMemoryBatchSize);
-        robotUnitPollFrequency = std::clamp(robotUnitPollFrequency, 1, ROBOT_UNIT_MAXIMUM_FREQUENCY);
+        robotUnit.pollFrequency = std::clamp(robotUnit.pollFrequency, 1, ROBOT_UNIT_MAXIMUM_FREQUENCY);
+        robotUnit.writer.properties.memoryBatchSize = std::max(static_cast<unsigned int>(1), robotUnit.writer.properties.memoryBatchSize);
 
-        Ice::StringSeq includePaths;
-        auto packages = armarx::Application::GetProjectDependencies();
+        std::vector<std::string> includePaths;
+        std::vector<std::string> packages = armarx::Application::GetProjectDependencies();
         packages.push_back(Application::GetProjectName());
 
         for (const std::string& projectName : packages)
@@ -124,44 +122,50 @@ namespace armarx::armem::server::robot_state
             }
 
             CMakePackageFinder project(projectName);
-            auto pathsString = project.getIncludePaths();
-            Ice::StringSeq projectIncludePaths = simox::alg::split(pathsString, ";,");
+            std::string pathsString = project.getIncludePaths();
+            std::vector<std::string> projectIncludePaths = simox::alg::split(pathsString, ";,");
             includePaths.insert(includePaths.end(), projectIncludePaths.begin(), projectIncludePaths.end());
         }
 
-        ArmarXDataPath::getAbsolutePath(robotUnitConfigPath, robotUnitConfigPath, includePaths);
-
-        // workingMemory.name() = workingMemoryName;
+        ArmarXDataPath::getAbsolutePath(robotUnit.configPath, robotUnit.configPath, includePaths);
     }
 
 
     void RobotStateMemory::onConnectComponent()
     {
+        ARMARX_CHECK_NOT_NULL(debugObserver->getDebugObserver());
 
-        if (getRobotUnit())
+        if (robotUnit.plugin->getRobotUnit())
         {
-            waitUntilRobotUnitIsRunning();
+            robotUnit.plugin->waitUntilRobotUnitIsRunning();
         }
+        RobotUnitInterfacePrx robotUnitPrx = robotUnit.plugin->getRobotUnit();
 
-        ARMARX_CHECK_NOT_NULL(getRobotUnit()->getKinematicUnit());
-
-        descriptionSegment.connect(getArvizClient(), getRobotUnit());
+        descriptionSegment.connect(robotUnitPrx);
 
-        proprioceptionSegment.connect(getArvizClient(), getRobotUnit());
-        toIce(robotUnitProviderID, proprioceptionSegment.getRobotUnitProviderID());
+        proprioceptionSegment.connect(robotUnitPrx);
 
-        localizationSegment.connect(getArvizClient());
+        localizationSegment.connect();
 
-        commonVisu.connect(
-            getArvizClient()
-        );
+        commonVisu.connect(getArvizClient(), debugObserver->getDebugObserver());
 
-        cfg.loggingNames.emplace_back(robotUnitSensorPrefix);
-        handler = make_shared<RobotUnitDataStreamingReceiver>(this, getRobotUnit(), cfg);
-        keys = handler->getDataDescription();
+        robotUnit.reader.connect(*robotUnit.plugin, *debugObserver);
+        robotUnit.writer.connect(*debugObserver);
+        robotUnit.writer.properties.robotUnitProviderID = proprioceptionSegment.getRobotUnitProviderID();
 
-        robotUnitConversionTask = new PeriodicTask<RobotStateMemory>(this, &RobotStateMemory::convertRobotUnitStreamingDataToAron, (1000 / robotUnitPollFrequency));
-        robotUnitStoringTask = new PeriodicTask<RobotStateMemory>(this, &RobotStateMemory::storeConvertedRobotUnitDataInMemory, (1000 / robotUnitPollFrequency));
+        robotUnit.reader.task = new SimpleRunningTask<>([this]()
+        {
+            robotUnit.reader.run(
+                robotUnit.pollFrequency, robotUnit.dataQueue, robotUnit.dataMutex
+            );
+        }, "Robot Unit Reader");
+        robotUnit.writer.task = new SimpleRunningTask<>([this]()
+        {
+            robotUnit.writer.run(
+                robotUnit.pollFrequency, robotUnit.dataQueue, robotUnit.dataMutex,
+                iceMemory, localizationSegment
+            );
+        }, "Robot State Writer");
 
         startRobotUnitStream();
     }
@@ -178,340 +182,57 @@ namespace armarx::armem::server::robot_state
         stopRobotUnitStream();
     }
 
+
     /*************************************************************/
     // RobotUnit Streaming functions
     /*************************************************************/
-    void RobotStateMemory::convertRobotUnitStreamingDataToAron()
-    {
-        auto& data = handler->getDataBuffer();
-        if (data.size() == 0)
-        {
-            return;
-        }
-        auto& currentTimestep = data.back();
-
-        ARMARX_DEBUG << "RobotUnitData: Generating new aron map for current timestep";
-        auto start = std::chrono::high_resolution_clock::now();
-
-        RobotUnitData convertedAndGroupedData;
-        for (const auto& [nameEntry, dataEntry] : keys.entries)
-        {
-            std::string name = nameEntry;
-            std::string jointOrWhateverName;
-
-            std::string groupName = "";
-            if (configSensorMapping.find(name) != configSensorMapping.end())
-            {
-                groupName = configSensorMapping.at(name);
-            }
-            else
-            {
-                const size_t first_dot_pos = name.find(".");
-                const size_t second_dot_pos = name.find(".", first_dot_pos + 1); // find second occurence of "."
-                if (second_dot_pos == std::string::npos)
-                {
-                    ARMARX_WARNING << "Could not find a groupname for the sensor with name " << name << ". All sensors must be called sens.X.Y where X is the name of the group and Y is the actual sensor. Ignoring this sensor.";
-                    continue;
-                }
-                groupName = name.substr(0, second_dot_pos);
-
-                jointOrWhateverName = name.substr(first_dot_pos + 1, second_dot_pos - first_dot_pos - 1);
-
-                name = name.substr(second_dot_pos + 1); // remove the groupName, TODO check if +1 is valid
-            }
-
-            RobotUnitData::RobotUnitDataGroup e;
-            if (auto it = convertedAndGroupedData.groups.find(groupName); it == convertedAndGroupedData.groups.end())
-            {
-                // generate new dict for the group
-                auto dict = std::make_shared<aron::datanavigator::DictNavigator>();
-                auto encGroupName = std::make_shared<aron::datanavigator::StringNavigator>(groupName);
-                dict->addElement("EncoderGroupName", encGroupName);
-
-                auto iterId = std::make_shared<aron::datanavigator::LongNavigator>(currentTimestep.iterationId);
-                dict->addElement("IterationId", iterId);
-
-                const auto nameId = std::make_shared<aron::datanavigator::StringNavigator>(jointOrWhateverName);
-                dict->addElement("name", nameId);
-
-                e.timestamp = currentTimestep.timestampUSec;
-                e.name = groupName;
-                e.data = dict;
-            }
-            else
-            {
-                // reuse existing entry
-                e = it->second;
-            }
-
-            switch (dataEntry.type)
-            {
-                case RobotUnitDataStreaming::NodeTypeFloat:
-                {
-                    float value = RobotUnitDataStreamingReceiver::GetAs<Ice::Float>(currentTimestep, dataEntry);
-                    auto aron = std::make_shared<aron::datanavigator::FloatNavigator>(value);
-                    e.data->addElement(name, aron);
-                    break;
-                }
-                case RobotUnitDataStreaming::NodeTypeBool:
-                {
-                    bool value = RobotUnitDataStreamingReceiver::GetAs<bool>(currentTimestep, dataEntry);
-                    auto aron = std::make_shared<aron::datanavigator::BoolNavigator>(value);
-                    e.data->addElement(name, aron);
-                    break;
-                }
-                case RobotUnitDataStreaming::NodeTypeByte:
-                {
-                    int value = RobotUnitDataStreamingReceiver::GetAs<Ice::Byte>(currentTimestep, dataEntry);
-                    auto aron = std::make_shared<aron::datanavigator::IntNavigator>(value);
-                    e.data->addElement(name, aron);
-                    break;
-                }
-                case RobotUnitDataStreaming::NodeTypeShort:
-                {
-                    int value = RobotUnitDataStreamingReceiver::GetAs<Ice::Short>(currentTimestep, dataEntry);
-                    auto aron = std::make_shared<aron::datanavigator::IntNavigator>(value);
-                    e.data->addElement(name, aron);
-                    break;
-                }
-                case RobotUnitDataStreaming::NodeTypeInt:
-                {
-                    int value = RobotUnitDataStreamingReceiver::GetAs<Ice::Int>(currentTimestep, dataEntry);
-                    auto aron = std::make_shared<aron::datanavigator::IntNavigator>(value);
-                    e.data->addElement(name, aron);
-                    break;
-                }
-                case RobotUnitDataStreaming::NodeTypeLong:
-                {
-                    long value = RobotUnitDataStreamingReceiver::GetAs<Ice::Long>(currentTimestep, dataEntry);
-                    auto aron = std::make_shared<aron::datanavigator::LongNavigator>(value);
-                    e.data->addElement(name, aron);
-                    break;
-                }
-                case RobotUnitDataStreaming::NodeTypeDouble:
-                {
-                    double value = RobotUnitDataStreamingReceiver::GetAs<Ice::Double>(currentTimestep, dataEntry);
-                    auto aron = std::make_shared<aron::datanavigator::DoubleNavigator>(value);
-                    e.data->addElement(name, aron);
-                    break;
-                }
-                default:
-                    throw LocalException("The enum type should not exist! Perhaps someone changed the RobotUnitDataStreaming::NodeType enum definition?");
-            }
-
-            convertedAndGroupedData.groups.insert({groupName, e});
-        }
-        {
-            std::lock_guard g{robotUnitDataMutex};
-            robotUnitDataQueue.push(convertedAndGroupedData);
-        }
-
-        auto stop = std::chrono::high_resolution_clock::now();
-        ARMARX_DEBUG << "RobotUnitData: The total time needed to convert the data to aron is: " << std::chrono::duration_cast<std::chrono::microseconds>(stop - start);
-    }
-
-    void RobotStateMemory::storeConvertedRobotUnitDataInMemory()
-    {
-        unsigned int size = 0;
-        {
-            std::lock_guard g{robotUnitDataMutex};
-            size = robotUnitDataQueue.size(); // the size can only grow
-        }
-        if (size >= robotUnitMemoryBatchSize)
-        {
-            ARMARX_DEBUG << "RobotUnitData: Sending batch of " << robotUnitMemoryBatchSize << " timesteps to memory... The size of the queue is: " << size;
-            auto start = std::chrono::high_resolution_clock::now();
-
-            // send batch to memory
-            armem::data::Commit proprioceptionCommit;
-            armem::data::Commit odometryCommit;
-
-            for (unsigned int i = 0; i < robotUnitMemoryBatchSize; ++i)
-            {
-                std::lock_guard g{robotUnitDataMutex};
-                const auto& convertedAndGroupedData = robotUnitDataQueue.front();
-                for (const auto& [encName, encTimestep] : convertedAndGroupedData.groups)
-                {
-                    ARMARX_CHECK_EQUAL(encName, encTimestep.name);
-
-                    auto entityID = robotUnitProviderID;
-                    entityID.entityName = encName;
-
-                    const auto& timeUSec = encTimestep.timestamp;
-                    const auto& aron = encTimestep.data;
-
-                    armem::data::EntityUpdate& update = proprioceptionCommit.updates.emplace_back();
-                    update.entityID = entityID;
-                    update.timeCreatedMicroSeconds = timeUSec;
-                    update.instancesData = {aron->toAronDictPtr()};
-                }
-
-                // odometry pose -> localization segment
-                auto it = convertedAndGroupedData.groups.find("sens.Platform");
-                if (it != convertedAndGroupedData.groups.end())
-                {
-                    ARMARX_DEBUG << "Found odometry data.";
-
-                    const RobotUnitData::RobotUnitDataGroup& timestep = it->second;
-                    const float relPosX = aron::datanavigator::FloatNavigator::DynamicCast(timestep.data->getElement("relativePositionX"))->getValue();
-                    const float relPosY = aron::datanavigator::FloatNavigator::DynamicCast(timestep.data->getElement("relativePositionY"))->getValue();
-                    const float relOrientation = aron::datanavigator::FloatNavigator::DynamicCast(timestep.data->getElement("relativePositionRotation"))->getValue();
-
-                    Eigen::Affine3f odometryPose = Eigen::Affine3f::Identity();
-                    odometryPose.translation() << relPosX, relPosY, 0; // TODO set height
-                    odometryPose.linear() = simox::math::rpy_to_mat3f(0.F, 0.F, relOrientation);
-
-                    // const auto timestamp = armem::Time::microSeconds(it->second.timestamp);
-                    const auto timestamp = armem::Time::now();
-
-                    const ::armarx::armem::robot_state::Transform transform
-                    {
-                        .header =
-                        {
-                            .parentFrame = OdometryFrame,
-                            .frame = "root", // TODO: robot root node
-                            .agent = robotUnitProviderID.providerSegmentName,
-                            .timestamp = timestamp
-                        },
-                        .transform = odometryPose
-                    };
-
-                    localizationSegment.storeTransform(transform);
-
-                }
-                else
-                {
-                    ARMARX_INFO << deactivateSpam(1000) << "No odometry data! If you are using a mobile platform this should not have happened";
-                }
-
-
-                robotUnitDataQueue.pop();
-            }
 
-            auto results = commit(proprioceptionCommit);
-            auto stop = std::chrono::high_resolution_clock::now();
-            ARMARX_DEBUG << "RobotUnitData: The total runtime of sending a batch to the memory is: " << std::chrono::duration_cast<std::chrono::microseconds>(stop - start);
-
-            for (const auto& result : results.results)
-            {
-                if (!result.success)
-                {
-                    ARMARX_WARNING << "Could not add data to memory. Error message: " << result.errorMessage;
-                }
-            }
-        }
-    }
-
-    void RobotStateMemory::stopRobotUnitStream()
-    {
-        std::lock_guard g{startStopMutex};
-        robotUnitConversionTask->stop();
-        robotUnitStoringTask->stop();
-    }
 
     void RobotStateMemory::startRobotUnitStream()
     {
-        std::lock_guard g{startStopMutex};
-        if (robotUnitConversionTask->isRunning() || robotUnitStoringTask->isRunning())
+        std::lock_guard lock{startStopMutex};
+        if (robotUnit.reader.task->isRunning() || robotUnit.writer.task->isRunning())
         {
-            if (robotUnitConversionTask->isRunning() && robotUnitStoringTask->isRunning())
+            if (robotUnit.reader.task->isRunning() && robotUnit.writer.task->isRunning())
             {
                 return;
             }
             ARMARX_WARNING << "Found inconsistency in running tasks. Restarting all!";
             stopRobotUnitStream();
         }
-
-        std::stringstream ss;
-        ss << "Getting sensor values for:" << std::endl;
-        for (const auto& [name, dataEntry] : keys.entries)
         {
-            std::string type = "";
-            switch (dataEntry.type)
+            std::stringstream ss;
+            ss << "Getting sensor values for:" << std::endl;
+            for (const auto& [name, dataEntry] : robotUnit.reader.description.entries)
             {
-                case RobotUnitDataStreaming::NodeTypeBool:
-                {
-                    type = "Bool";
-                    break;
-                }
-                case RobotUnitDataStreaming::NodeTypeByte:
-                {
-                    type = "Byte";
-                    break;
-                }
-                case RobotUnitDataStreaming::NodeTypeShort:
-                {
-                    type = "Short";
-                    break;
-                }
-                case RobotUnitDataStreaming::NodeTypeInt:
-                {
-                    type = "Int";
-                    break;
-                }
-                case RobotUnitDataStreaming::NodeTypeLong:
-                {
-                    type = "Long";
-                    break;
-                }
-                case RobotUnitDataStreaming::NodeTypeFloat:
-                {
-                    type = "Float";
-                    break;
-                }
-                case RobotUnitDataStreaming::NodeTypeDouble:
-                {
-                    type = "Double";
-                    break;
-                }
+                const std::string type = RobotUnitDataStreaming::DataEntryNames.to_name(dataEntry.type);
+                ss << "\t" << name << " (type: '" << type << "')" << std::endl;
             }
-            ss << "\t" << name << " (type: '" << type << "')" << std::endl;
+            ARMARX_INFO << ss.str();
         }
-        ARMARX_INFO << ss.str();
 
         // parse config
-        std::filesystem::path configPath(robotUnitConfigPath);
-        configSensorMapping.clear();
-        if (std::filesystem::is_regular_file(configPath))
+        if (std::filesystem::is_regular_file(robotUnit.configPath))
         {
-            ARMARX_INFO << "Found a configuration file at: " << robotUnitConfigPath;
-            // a simple self-made parser for the config file. Extend it if you need to
-            std::ifstream in(configPath);
-            std::string line;
-            while (std::getline(in, line))
-            {
-                if (line.size() > 0)
-                {
-                    if (simox::alg::starts_with(line, "//"))
-                    {
-                        continue;
-                    }
-
-                    std::vector<std::string> mappings = simox::alg::split(line, ",");
-                    for (const auto& mapping : mappings)
-                    {
-                        std::vector<std::string> split = simox::alg::split(mapping, "=>");
-                        if (split.size() < 2)
-                        {
-                            ARMARX_WARNING << "A mapping in the RobotUnitConfig file is not valid. Ignoring it: " << mapping;
-                            continue;
-                        }
-                        for (unsigned int i = 0; i < split.size() - 1; ++i)
-                        {
-                            ARMARX_DEBUG << "Setting sensor value '" << split[i] << "' to group '" << split[split.size() - 1] << "'.";
-                            configSensorMapping.insert({split[i], split[split.size() - 1]});
-                        }
-                    }
-                }
-            }
+            ARMARX_INFO << "Found a configuration file at: " << robotUnit.configPath;
+            // A simple self-made parser for the config file. Extend it if you need to.
+            robotUnit.reader.configSensorMapping = RobotUnitReader::readConfig(robotUnit.configPath);
         }
         else
         {
-            ARMARX_INFO << "The config path '" << robotUnitConfigPath << "' is not valid.";
+            ARMARX_INFO << "The config path '" << robotUnit.configPath << "' is not valid.";
         }
 
-        robotUnitConversionTask->start();
-        robotUnitStoringTask->start();
+        robotUnit.reader.task->start();
+        robotUnit.writer.task->start();
+    }
+
+
+    void RobotStateMemory::stopRobotUnitStream()
+    {
+        std::lock_guard lock{startStopMutex};
+        robotUnit.reader.task->stop();
+        robotUnit.writer.task->stop();
     }
 
 }
diff --git a/source/RobotAPI/components/armem/server/RobotStateMemory/RobotStateMemory.h b/source/RobotAPI/components/armem/server/RobotStateMemory/RobotStateMemory.h
index e8174416e9b547f70af5e5c6b578242a0234743d..39048334904470b929e0ebe045083a63d4f59125 100644
--- a/source/RobotAPI/components/armem/server/RobotStateMemory/RobotStateMemory.h
+++ b/source/RobotAPI/components/armem/server/RobotStateMemory/RobotStateMemory.h
@@ -24,20 +24,13 @@
 
 // STD
 #include <atomic>
-#include <thread>
+#include <optional>
 #include <queue>
 
-// Simox
-#include <SimoxUtility/meta/enum/adapt_enum.h>
-
 // ArmarX
 #include <ArmarXCore/core/Component.h>
-#include <ArmarXCore/core/services/tasks/PeriodicTask.h>
-
-// BaseClass
-#include <RobotAPI/libraries/RobotAPIComponentPlugins/RobotUnitComponentPlugin.h>
-#include "RobotAPI/libraries/RobotAPIComponentPlugins/ArVizComponentPlugin.h"
 
+#include <RobotAPI/libraries/RobotAPIComponentPlugins/ArVizComponentPlugin.h>
 #include <RobotAPI/libraries/RobotUnitDataStreamingReceiver/RobotUnitDataStreamingReceiver.h>
 #include <RobotAPI/libraries/armem/server/ComponentPlugin.h>
 
@@ -46,6 +39,16 @@
 #include <RobotAPI/libraries/armem_robot_state/server/localization/Segment.h>
 #include <RobotAPI/libraries/armem_robot_state/server/common/Visu.h>
 
+#include "RobotUnitData.h"
+#include "RobotUnitReader.h"
+#include "RobotStateWriter.h"
+
+
+namespace armarx::plugins
+{
+    class DebugObserverComponentPlugin;
+    class RobotUnitComponentPlugin;
+}
 namespace armarx::armem::server::robot_state
 {
 
@@ -63,44 +66,41 @@ namespace armarx::armem::server::robot_state
     class RobotStateMemory :
         virtual public armarx::Component,
         virtual public armem::server::ComponentPluginUser,
-        virtual public RobotUnitComponentPluginUser,
         virtual public armarx::ArVizComponentPluginUser
     {
     public:
+
         RobotStateMemory();
+        virtual ~RobotStateMemory() override;
 
-        virtual ~RobotStateMemory();
 
-        /// @see armarx::ManagedIceObject::getDefaultName()
         std::string getDefaultName() const override;
 
+
     protected:
-        /// @see armarx::ManagedIceObject::onInitComponent()
-        void onInitComponent() override;
 
-        /// @see armarx::ManagedIceObject::onConnectComponent()
-        void onConnectComponent() override;
+        armarx::PropertyDefinitionsPtr createPropertyDefinitions() override;
 
-        /// @see armarx::ManagedIceObject::onDisconnectComponent()
+        void onInitComponent() override;
+        void onConnectComponent() override;
         void onDisconnectComponent() override;
-
-        /// @see armarx::ManagedIceObject::onExitComponent()
         void onExitComponent() override;
 
-        /// @see PropertyUser::createPropertyDefinitions()
-        armarx::PropertyDefinitionsPtr createPropertyDefinitions() override;
 
     private:
-        // RobotUnit Streaming
-        void convertRobotUnitStreamingDataToAron();
-        void storeConvertedRobotUnitDataInMemory();
+
+        /// Reads from `robotUnitDataQueue` and commits into memory.
+        void convertRobotUnitStreamingDataToAronTask();
+        /// Reads from `robotUnitDataQueue` and commits into memory.
+        void storeConvertedRobotUnitDataInMemoryTask();
 
         void startRobotUnitStream();
         void stopRobotUnitStream();
 
+
     private:
-        std::string workingMemoryName = "RobotStateMemory";
-        bool addCoreSegmentOnUsage = false;
+
+        armarx::plugins::DebugObserverComponentPlugin* debugObserver = nullptr;
 
         mutable std::recursive_mutex startStopMutex;
 
@@ -118,41 +118,28 @@ namespace armarx::armem::server::robot_state
         // Joint visu for all segments => robot pose and configuration
         Visu commonVisu;
 
-        // RobotUnit stuff
-        RobotUnitDataStreaming::DataStreamingDescription keys;
-        std::vector<RobotUnitDataStreaming::DataEntry> keysList;
-        RobotUnitDataStreaming::Config cfg;
-        RobotUnitDataStreamingReceiverPtr handler;
-        std::map<std::string, std::string> configSensorMapping;
 
-        struct RobotUnitData
+        struct RobotUnit
         {
-            struct RobotUnitDataGroup
-            {
-                long timestamp;
-                std::string name;
-                aron::datanavigator::DictNavigatorPtr data;
-            };
-
-            std::map<std::string, RobotUnitDataGroup> groups;
+            int pollFrequency = 50;
+            std::string configPath = "NO CONFIG SET";
+
+            armarx::plugins::RobotUnitComponentPlugin* plugin = nullptr;
+            RobotUnitReader reader;
+            RobotStateWriter writer;
+
+            // queue
+            std::queue<RobotUnitData> dataQueue;
+            mutable std::mutex dataMutex;
         };
+        RobotUnit robotUnit;
+
 
         // params
         static constexpr int ROBOT_UNIT_MAXIMUM_FREQUENCY = 100;
         static constexpr const char* sensorValuePrefix = "RobotUnit.";
 
-        int robotUnitPollFrequency = 50;
-        std::string robotUnitSensorPrefix = "sens.*";
-        unsigned int robotUnitMemoryBatchSize = 50;
-        std::string robotUnitConfigPath = "NO CONFIG SET";
-
-        // queue
-        std::queue<RobotUnitData> robotUnitDataQueue;
-        mutable std::mutex robotUnitDataMutex;
 
-        // running tasks
-        armarx::PeriodicTask<RobotStateMemory>::pointer_type robotUnitConversionTask;
-        armarx::PeriodicTask<RobotStateMemory>::pointer_type robotUnitStoringTask;
     };
 
 }  // namespace armarx::armem::server::robot_state
diff --git a/source/RobotAPI/components/armem/server/RobotStateMemory/RobotStateWriter.cpp b/source/RobotAPI/components/armem/server/RobotStateMemory/RobotStateWriter.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..39439e2e77bbd8c3ebea44782ae44d62286c6ed9
--- /dev/null
+++ b/source/RobotAPI/components/armem/server/RobotStateMemory/RobotStateWriter.cpp
@@ -0,0 +1,198 @@
+/*
+ * 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::RobotSensorMemory
+ * @author     Rainer Kartmann ( rainer dot kartmann at kit dot edu )
+ * @date       2020
+ * @copyright  http://www.gnu.org/licenses/gpl-2.0.txt
+ *             GNU General Public License
+ */
+
+#include "RobotStateWriter.h"
+
+// STL
+#include <chrono>
+
+// Simox
+#include <SimoxUtility/math/convert/rpy_to_mat3f.h>
+
+// ArmarX
+#include <ArmarXCore/core/exceptions/local/ExpressionException.h>
+#include <ArmarXCore/core/time/CycleUtil.h>
+#include <ArmarXCore/libraries/ArmarXCoreComponentPlugins/DebugObserverComponentPlugin.h>
+
+#include <RobotAPI/libraries/core/FramedPose.h>
+#include <RobotAPI/libraries/aron/core/navigator/data/AllNavigators.h>
+#include <RobotAPI/libraries/armem/core/Time.h>
+#include <RobotAPI/libraries/armem/core/ice_conversions.h>
+#include <RobotAPI/libraries/armem/server/MemoryToIceAdapter.h>
+#include <RobotAPI/libraries/armem_robot_state/aron/Transform.aron.generated.h>
+#include <RobotAPI/libraries/armem_robot_state/server/localization/Segment.h>
+
+
+namespace armarx::armem::server::robot_state
+{
+
+    void RobotStateWriter::connect(armarx::plugins::DebugObserverComponentPlugin& debugObserver)
+    {
+        {
+            // Thread-local copy of debug observer helper.
+            this->debugObserver = DebugObserverHelper(
+                                      Logging::tag.tagName, debugObserver.getDebugObserver(), true
+                                  );
+        }
+    }
+
+
+    static float toDurationMs(
+        std::chrono::high_resolution_clock::time_point start,
+        std::chrono::high_resolution_clock::time_point end)
+    {
+        auto duration = std::chrono::duration_cast<std::chrono::microseconds>(end - start);
+        return duration.count() / 1000.f;
+    }
+
+
+    void RobotStateWriter::run(float pollFrequency,
+                               std::queue<RobotUnitData>& dataQueue, std::mutex& dataMutex,
+                               MemoryToIceAdapter& memory, localization::Segment& localizationSegment)
+    {
+        CycleUtil cycle(static_cast<int>(1000.f / pollFrequency));
+        while (task and not task->isStopped())
+        {
+            size_t queueSize = 0;
+            std::queue<RobotUnitData> batch;
+            {
+                std::lock_guard lock{dataMutex};
+                queueSize = dataQueue.size();
+                if (dataQueue.size() >= properties.memoryBatchSize)
+                {
+                    std::swap(batch, dataQueue);
+                }
+            }
+            if (debugObserver)
+            {
+                debugObserver->setDebugObserverDatafield("RobotStateWriter | Queue Size", queueSize);
+            }
+            if (batch.size() > 0)
+            {
+                Update update = buildUpdate(batch);
+
+                auto start = std::chrono::high_resolution_clock::now();
+                auto endProprioception = start, endLocalization = start;
+
+                armem::CommitResult result;
+                {
+                    // Commits lock the core segments.
+
+                    result = memory.commitLocking(update.proprioception);
+                    endProprioception = std::chrono::high_resolution_clock::now();
+
+                    localizationSegment.commitTransformLocking(update.localization);
+                    endLocalization = std::chrono::high_resolution_clock::now();
+                }
+                if (not result.allSuccess())
+                {
+                    ARMARX_WARNING << "Could not add data to memory. Error message: " << result.allErrorMessages();
+                }
+                if (debugObserver)
+                {
+                    auto end = std::chrono::high_resolution_clock::now();
+
+                    debugObserver->setDebugObserverDatafield("RobotStateWriter | t Commit [ms]", toDurationMs(start, end));
+                    debugObserver->setDebugObserverDatafield("RobotStateWriter | t Commit Proprioception [ms]", toDurationMs(start, endProprioception));
+                    debugObserver->setDebugObserverDatafield("RobotStateWriter | t Commit Localization [ms]", toDurationMs(endProprioception, endLocalization));
+                }
+            }
+
+            if (debugObserver)
+            {
+                debugObserver->sendDebugObserverBatch();
+            }
+            cycle.waitForCycleDuration();
+        }
+    }
+
+
+    RobotStateWriter::Update RobotStateWriter::buildUpdate(std::queue<RobotUnitData> dataQueue)
+    {
+        ARMARX_CHECK_GREATER(dataQueue.size(), 0);
+
+        ARMARX_DEBUG << "RobotStateWriter: Commit batch of " << dataQueue.size() << " timesteps to memory...";
+        auto start = std::chrono::high_resolution_clock::now();
+
+        // Send batch to memory
+        Update update;
+
+        while (dataQueue.size() > 0)
+        {
+            const RobotUnitData& convertedAndGroupedData = dataQueue.front();
+
+            for (const auto& [encName, encTimestep] : convertedAndGroupedData.groups)
+            {
+                ARMARX_CHECK_EQUAL(encName, encTimestep.name);
+
+                armem::EntityUpdate& up = update.proprioception.add();
+                up.entityID = properties.robotUnitProviderID.withEntityName(encName);
+                up.timeCreated = encTimestep.timestamp;
+                up.instancesData = { encTimestep.data };
+            }
+
+            // odometry pose -> localization segment
+            auto it = convertedAndGroupedData.groups.find(properties.platformGroupName);
+            if (it != convertedAndGroupedData.groups.end())
+            {
+                ARMARX_DEBUG << "Found odometry data.";
+
+                const RobotUnitData::RobotUnitDataGroup& timestep = it->second;
+                const float relPosX = aron::datanavigator::FloatNavigator::DynamicCast(timestep.data->getElement("relativePositionX"))->getValue();
+                const float relPosY = aron::datanavigator::FloatNavigator::DynamicCast(timestep.data->getElement("relativePositionY"))->getValue();
+                const float relOrientation = aron::datanavigator::FloatNavigator::DynamicCast(timestep.data->getElement("relativePositionRotation"))->getValue();
+
+                Eigen::Affine3f odometryPose = Eigen::Affine3f::Identity();
+                odometryPose.translation() << relPosX, relPosY, 0; // TODO set height
+                odometryPose.linear() = simox::math::rpy_to_mat3f(0.F, 0.F, relOrientation);
+
+                // const auto timestamp = armem::Time::microSeconds(it->second.timestamp);
+
+                armem::robot_state::Transform& transform = update.localization;
+                transform.header.parentFrame = armarx::OdometryFrame;
+                transform.header.frame = "root"; // TODO: robot root node
+                transform.header.agent = properties.robotUnitProviderID.providerSegmentName;
+                transform.header.timestamp = it->second.timestamp;
+                transform.transform = odometryPose;
+            }
+            else if (!noOdometryDataLogged)
+            {
+                ARMARX_INFO << "No odometry data! (No group with name '" << properties.platformGroupName << "'.). \n"
+                            << "If you are using a mobile platform this should not have happened.";
+                noOdometryDataLogged = true;
+            }
+
+            dataQueue.pop();
+        }
+
+        auto stop = std::chrono::high_resolution_clock::now();
+        auto duration = std::chrono::duration_cast<std::chrono::microseconds>(stop - start);
+        ARMARX_DEBUG << "RobotUnitData: The total runtime of sending a batch to the memory is: " << duration;
+        if (debugObserver)
+        {
+            debugObserver->setDebugObserverDatafield("RobotStateWriter | t Build Update [ms]", duration.count() / 1000.f);
+        }
+
+        return update;
+    }
+
+}
diff --git a/source/RobotAPI/components/armem/server/RobotStateMemory/RobotStateWriter.h b/source/RobotAPI/components/armem/server/RobotStateMemory/RobotStateWriter.h
new file mode 100644
index 0000000000000000000000000000000000000000..93ba74d2d9d622f4d72d1d5a4d08acd97f3eb64b
--- /dev/null
+++ b/source/RobotAPI/components/armem/server/RobotStateMemory/RobotStateWriter.h
@@ -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::RobotSensorMemory
+ * @author     Rainer Kartmann ( rainer dot kartmann at kit dot edu )
+ * @date       2020
+ * @copyright  http://www.gnu.org/licenses/gpl-2.0.txt
+ *             GNU General Public License
+ */
+
+
+#pragma once
+
+#include <optional>
+
+#include <ArmarXCore/core/logging/Logging.h>
+#include <ArmarXCore/core/services/tasks/TaskUtil.h>
+#include <ArmarXCore/libraries/DebugObserverHelper/DebugObserverHelper.h>
+
+#include <RobotAPI/libraries/armem/core/Commit.h>
+#include <RobotAPI/libraries/armem/core/MemoryID.h>
+#include <RobotAPI/libraries/armem_robot_state/types.h>
+
+#include "RobotUnitData.h"
+
+
+namespace armarx::plugins
+{
+    class DebugObserverComponentPlugin;
+}
+namespace armarx::armem::server
+{
+    class MemoryToIceAdapter;
+}
+namespace armarx::armem::server::robot_state::localization
+{
+    class Segment;
+}
+namespace armarx::armem::server::robot_state
+{
+
+    class RobotStateWriter : public armarx::Logging
+    {
+    public:
+
+        void connect(armarx::plugins::DebugObserverComponentPlugin& debugObserver);
+
+        /// Reads data from `dataQueue` and commits to the memory.
+        void run(float pollFrequency,
+                 std::queue<RobotUnitData>& dataQueue, std::mutex& dataMutex,
+                 MemoryToIceAdapter& memory,
+                 localization::Segment& localizationSegment
+                );
+
+
+        struct Update
+        {
+            armem::Commit proprioception;
+            armem::robot_state::Transform localization;
+        };
+        Update buildUpdate(std::queue<RobotUnitData> dataQueue);
+
+
+    public:
+
+        struct Properties
+        {
+            unsigned int memoryBatchSize = 50;
+            armem::MemoryID robotUnitProviderID;
+            std::string platformGroupName = "sens.Platform";
+        };
+        Properties properties;
+
+        std::optional<DebugObserverHelper> debugObserver;
+
+
+        armarx::SimpleRunningTask<>::pointer_type task = nullptr;
+
+
+    private:
+
+        bool noOdometryDataLogged = false;
+
+    };
+
+}
diff --git a/source/RobotAPI/components/armem/server/RobotStateMemory/RobotUnitData.cpp b/source/RobotAPI/components/armem/server/RobotStateMemory/RobotUnitData.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..9a9b72e2a74203cb9f44dd54796b397770257ecd
--- /dev/null
+++ b/source/RobotAPI/components/armem/server/RobotStateMemory/RobotUnitData.cpp
@@ -0,0 +1,9 @@
+#include "RobotUnitData.h"
+
+#include <RobotAPI/libraries/aron/core/navigator/data/container/Dict.h>
+
+
+namespace armarx::armem::server::robot_state
+{
+
+}
diff --git a/source/RobotAPI/components/armem/server/RobotStateMemory/RobotUnitData.h b/source/RobotAPI/components/armem/server/RobotStateMemory/RobotUnitData.h
new file mode 100644
index 0000000000000000000000000000000000000000..dc43dcddca3eb693fe5200dcc0a256a15be23cac
--- /dev/null
+++ b/source/RobotAPI/components/armem/server/RobotStateMemory/RobotUnitData.h
@@ -0,0 +1,31 @@
+#pragma once
+
+#include <map>
+#include <memory>
+#include <string>
+
+#include <RobotAPI/libraries/armem/core/Time.h>
+
+
+namespace armarx::aron::datanavigator
+{
+    using DictNavigatorPtr = std::shared_ptr<class DictNavigator>;
+}
+
+namespace armarx::armem::server::robot_state
+{
+
+    struct RobotUnitData
+    {
+        struct RobotUnitDataGroup
+        {
+            armem::Time timestamp;
+            std::string name;
+            aron::datanavigator::DictNavigatorPtr data;
+        };
+
+        std::map<std::string, RobotUnitDataGroup> groups;
+    };
+
+}
+
diff --git a/source/RobotAPI/components/armem/server/RobotStateMemory/RobotUnitReader.cpp b/source/RobotAPI/components/armem/server/RobotStateMemory/RobotUnitReader.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..58b688557eb86e8efb28afd0329d8f3b50e8508c
--- /dev/null
+++ b/source/RobotAPI/components/armem/server/RobotStateMemory/RobotUnitReader.cpp
@@ -0,0 +1,201 @@
+#include "RobotUnitReader.h"
+
+#include "aron_conversions.h"
+
+#include <RobotAPI/libraries/aron/core/navigator/data/container/Dict.h>
+#include <RobotAPI/libraries/aron/core/navigator/data/primitive/Long.h>
+#include <RobotAPI/libraries/aron/core/navigator/data/primitive/String.h>
+
+#include <RobotAPI/libraries/RobotUnitDataStreamingReceiver/RobotUnitDataStreamingReceiver.h>
+
+#include <ArmarXCore/core/time/CycleUtil.h>
+#include <ArmarXCore/libraries/ArmarXCoreComponentPlugins/DebugObserverComponentPlugin.h>
+
+#include <SimoxUtility/algorithm/string/string_tools.h>
+
+#include <istream>
+#include <filesystem>
+#include <fstream>
+
+
+namespace armarx::armem::server::robot_state
+{
+
+    std::map<std::string, std::string> RobotUnitReader::readConfig(const std::string& configPath)
+    {
+        ARMARX_CHECK(std::filesystem::is_regular_file(configPath));
+
+        std::map<std::string, std::string> config;
+
+        std::ifstream in(configPath);
+        std::string line;
+        while (std::getline(in, line))
+        {
+            if (line.size() > 0)
+            {
+                if (simox::alg::starts_with(line, "//"))
+                {
+                    continue;
+                }
+
+                std::vector<std::string> mappings = simox::alg::split(line, ",");
+                for (const auto& mapping : mappings)
+                {
+                    std::vector<std::string> split = simox::alg::split(mapping, "=>");
+                    if (split.size() < 2)
+                    {
+                        ARMARX_WARNING_S << "A mapping in the RobotUnitConfig file is not valid. Ignoring it: " << mapping;
+                        continue;
+                    }
+                    for (unsigned int i = 0; i < split.size() - 1; ++i)
+                    {
+                        ARMARX_DEBUG_S << "Setting sensor value '" << split[i] << "' to group '" << split[split.size() - 1] << "'.";
+                        config.emplace(split[i], split[split.size() - 1]);
+                    }
+                }
+            }
+        }
+
+        return config;
+    }
+
+
+    void RobotUnitReader::connect(
+        armarx::plugins::RobotUnitComponentPlugin& robotUnitPlugin,
+        armarx::plugins::DebugObserverComponentPlugin& debugObserverPlugin)
+    {
+        {
+            config.loggingNames.push_back(properties.sensorPrefix);
+            receiver = robotUnitPlugin.startDataSatreming(config);
+            description = receiver->getDataDescription();
+        }
+        {
+            // Thread-local copy of debug observer helper.
+            debugObserver = DebugObserverHelper(
+                                Logging::tag.tagName, debugObserverPlugin.getDebugObserver(), true
+                            );
+        }
+    }
+
+
+    void RobotUnitReader::run(
+        float pollFrequency,
+        std::queue<RobotUnitData>& dataQueue,
+        std::mutex& dataMutex)
+    {
+        CycleUtil cycle(static_cast<int>(1000.f / pollFrequency));
+        while (task and not task->isStopped())
+        {
+            if (std::optional<RobotUnitData> data = fetchAndGroupLatestRobotUnitData())
+            {
+                std::lock_guard g{dataMutex};
+                dataQueue.push(data.value());
+            }
+
+            if (debugObserver)
+            {
+                debugObserver->sendDebugObserverBatch();
+            }
+            cycle.waitForCycleDuration();
+        }
+    }
+
+
+    std::optional<RobotUnitData> RobotUnitReader::fetchAndGroupLatestRobotUnitData()
+    {
+        const std::optional<RobotUnitDataStreaming::TimeStep> data = fetchLatestData();
+        if (not data.has_value())
+        {
+            return std::nullopt;
+        }
+
+        ARMARX_DEBUG << "RobotUnitData: Generating new aron map for current timestep";
+        auto start = std::chrono::high_resolution_clock::now();
+
+        RobotUnitData convertedAndGroupedData;
+        for (const auto& [nameEntry, dataEntry] : description.entries)
+        {
+            std::string name = nameEntry;
+            std::string jointOrWhateverName;
+
+            std::string groupName = "";
+            if (auto it = configSensorMapping.find(name); it != configSensorMapping.end())
+            {
+                groupName = it->second;
+            }
+            else
+            {
+                const size_t first_dot_pos = name.find(".");
+                const size_t second_dot_pos = name.find(".", first_dot_pos + 1); // find second occurence of "."
+                if (second_dot_pos == std::string::npos)
+                {
+                    ARMARX_WARNING << "Could not find a groupname for the sensor with name " << name << ". "
+                                   << "All sensors must be called sens.X.Y where X is the name of the group "
+                                   << "and Y is the actual sensor. Ignoring this sensor.";
+                    continue;
+                }
+                groupName = name.substr(0, second_dot_pos);
+
+                jointOrWhateverName = name.substr(first_dot_pos + 1, second_dot_pos - first_dot_pos - 1);
+
+                name = name.substr(second_dot_pos + 1); // remove the groupName, TODO check if +1 is valid
+            }
+
+            auto it = convertedAndGroupedData.groups.find(groupName);
+            if (it == convertedAndGroupedData.groups.end())
+            {
+                namespace adn = aron::datanavigator;
+
+                // Generate new dict for the group
+                RobotUnitData::RobotUnitDataGroup group;
+                group.timestamp = armem::Time::microSeconds(data->timestampUSec);
+                group.name = groupName;
+                group.data = std::make_shared<adn::DictNavigator>();
+
+                group.data->addElement("EncoderGroupName", std::make_shared<adn::StringNavigator>(groupName));
+                group.data->addElement("IterationId", std::make_shared<adn::LongNavigator>(data->iterationId));
+                group.data->addElement("name", std::make_shared<adn::StringNavigator>(jointOrWhateverName));
+
+                auto r = convertedAndGroupedData.groups.emplace(groupName, group);
+                it = r.first;
+            }
+
+            RobotUnitData::RobotUnitDataGroup& group = it->second;
+            group.data->addElement(name, RobotUnitDataStreaming::toAron(data.value(), dataEntry));
+        }
+
+        auto stop = std::chrono::high_resolution_clock::now();
+        auto duration = std::chrono::duration_cast<std::chrono::microseconds>(stop - start);
+        ARMARX_DEBUG << "RobotUnitData: The total time needed to convert the data to aron is: " << duration;
+
+        if (debugObserver)
+        {
+            debugObserver->setDebugObserverDatafield("RobotUnitReader | t Read+Group [ms]", duration.count() / 1000.f);
+        }
+
+        return convertedAndGroupedData;
+    }
+
+
+    std::optional<RobotUnitDataStreaming::TimeStep> RobotUnitReader::fetchLatestData()
+    {
+        std::deque<RobotUnitDataStreaming::TimeStep>& data = receiver->getDataBuffer();
+        if (debugObserver)
+        {
+            debugObserver->setDebugObserverDatafield("RobotUnitReader | Buffer Size", data.size());
+        }
+        if (data.empty())
+        {
+            return std::nullopt;
+        }
+        else
+        {
+            RobotUnitDataStreaming::TimeStep currentTimestep = data.back();
+            data.clear();
+            return currentTimestep;
+        }
+    }
+
+
+}
+
diff --git a/source/RobotAPI/components/armem/server/RobotStateMemory/RobotUnitReader.h b/source/RobotAPI/components/armem/server/RobotStateMemory/RobotUnitReader.h
new file mode 100644
index 0000000000000000000000000000000000000000..a44c9c0f19a586f48b3f899ae314ca70cc223abe
--- /dev/null
+++ b/source/RobotAPI/components/armem/server/RobotStateMemory/RobotUnitReader.h
@@ -0,0 +1,84 @@
+#pragma once
+
+#include <queue>
+#include <map>
+#include <memory>
+#include <optional>
+#include <string>
+
+#include <ArmarXCore/core/logging/Logging.h>
+#include <ArmarXCore/core/services/tasks/TaskUtil.h>
+#include <ArmarXCore/libraries/DebugObserverHelper/DebugObserverHelper.h>
+
+
+#include <RobotAPI/interface/units/RobotUnit/RobotUnitInterface.h>
+#include <RobotAPI/libraries/RobotAPIComponentPlugins/RobotUnitComponentPlugin.h>
+
+#include "RobotUnitData.h"
+
+
+namespace armarx::plugins
+{
+    class RobotUnitComponentPlugin;
+    class DebugObserverComponentPlugin;
+}
+namespace armarx
+{
+    using RobotUnitDataStreamingReceiverPtr = std::shared_ptr<class RobotUnitDataStreamingReceiver>;
+}
+
+namespace armarx::armem::server::robot_state
+{
+
+    class RobotUnitReader : public armarx::Logging
+    {
+    public:
+
+        static std::map<std::string, std::string> readConfig(const std::string& configPath);
+
+
+    public:
+
+        void connect(armarx::plugins::RobotUnitComponentPlugin& robotUnitPlugin,
+                     armarx::plugins::DebugObserverComponentPlugin& debugObserverPlugin);
+
+
+
+        /// Reads data from `handler` and fills `robotUnitDataQueue`.
+        void run(float pollFrequency,
+                 std::queue<RobotUnitData>& dataQueue,
+                 std::mutex& dataMutex);
+
+        std::optional<RobotUnitData> fetchAndGroupLatestRobotUnitData();
+
+
+    private:
+
+        /// Fetch the latest timestep and clear the robot unit buffer.
+        std::optional<RobotUnitDataStreaming::TimeStep> fetchLatestData();
+
+
+    public:
+
+        struct Properties
+        {
+            std::string sensorPrefix = "sens.*";
+        };
+        Properties properties;
+
+        std::optional<DebugObserverHelper> debugObserver;
+
+
+        RobotUnitDataStreaming::Config config;
+        RobotUnitDataStreamingReceiverPtr receiver;
+        RobotUnitDataStreaming::DataStreamingDescription description;
+
+        /// RobotUnit name -> group name.
+        std::map<std::string, std::string> configSensorMapping;
+
+        armarx::SimpleRunningTask<>::pointer_type task = nullptr;
+
+    };
+
+}
+
diff --git a/source/RobotAPI/components/armem/server/RobotStateMemory/aron_conversions.cpp b/source/RobotAPI/components/armem/server/RobotStateMemory/aron_conversions.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..8caf73057ac54df453f6e3c2d67295dc7e69ab89
--- /dev/null
+++ b/source/RobotAPI/components/armem/server/RobotStateMemory/aron_conversions.cpp
@@ -0,0 +1,69 @@
+#include "aron_conversions.h"
+
+#include <RobotAPI/libraries/aron/core/navigator/data/AllNavigators.h>
+#include <RobotAPI/libraries/RobotUnitDataStreamingReceiver/RobotUnitDataStreamingReceiver.h>
+
+#include <ArmarXCore/core/exceptions/local/UnexpectedEnumValueException.h>
+
+
+namespace armarx
+{
+    aron::datanavigator::NavigatorPtr RobotUnitDataStreaming::toAron(
+        const TimeStep& timestep,
+        const DataEntry& dataEntry)
+    {
+        switch (dataEntry.type)
+        {
+            case RobotUnitDataStreaming::NodeTypeFloat:
+            {
+                float value = RobotUnitDataStreamingReceiver::GetAs<Ice::Float>(timestep, dataEntry);
+                return std::make_shared<aron::datanavigator::FloatNavigator>(value);
+            }
+            case RobotUnitDataStreaming::NodeTypeBool:
+            {
+                bool value = RobotUnitDataStreamingReceiver::GetAs<bool>(timestep, dataEntry);
+                return std::make_shared<aron::datanavigator::BoolNavigator>(value);
+            }
+            case RobotUnitDataStreaming::NodeTypeByte:
+            {
+                int value = RobotUnitDataStreamingReceiver::GetAs<Ice::Byte>(timestep, dataEntry);
+                return std::make_shared<aron::datanavigator::IntNavigator>(value);
+            }
+            case RobotUnitDataStreaming::NodeTypeShort:
+            {
+                int value = RobotUnitDataStreamingReceiver::GetAs<Ice::Short>(timestep, dataEntry);
+                return std::make_shared<aron::datanavigator::IntNavigator>(value);
+            }
+            case RobotUnitDataStreaming::NodeTypeInt:
+            {
+                int value = RobotUnitDataStreamingReceiver::GetAs<Ice::Int>(timestep, dataEntry);
+                return std::make_shared<aron::datanavigator::IntNavigator>(value);
+            }
+            case RobotUnitDataStreaming::NodeTypeLong:
+            {
+                long value = RobotUnitDataStreamingReceiver::GetAs<Ice::Long>(timestep, dataEntry);
+                return std::make_shared<aron::datanavigator::LongNavigator>(value);
+            }
+            case RobotUnitDataStreaming::NodeTypeDouble:
+            {
+                double value = RobotUnitDataStreamingReceiver::GetAs<Ice::Double>(timestep, dataEntry);
+                return std::make_shared<aron::datanavigator::DoubleNavigator>(value);
+            }
+            default:
+                ARMARX_UNEXPECTED_ENUM_VALUE(RobotUnitDataStreaming::NodeType, dataEntry.type);
+        }
+    }
+
+
+    const simox::meta::EnumNames<RobotUnitDataStreaming::DataEntryType> RobotUnitDataStreaming::DataEntryNames =
+    {
+        { NodeTypeBool, "Bool" },
+        { NodeTypeByte, "Byte" },
+        { NodeTypeShort, "Short" },
+        { NodeTypeInt, "Int" },
+        { NodeTypeLong, "Long" },
+        { NodeTypeFloat, "Float" },
+        { NodeTypeDouble, "Double" },
+    };
+
+}
diff --git a/source/RobotAPI/components/armem/server/RobotStateMemory/aron_conversions.h b/source/RobotAPI/components/armem/server/RobotStateMemory/aron_conversions.h
new file mode 100644
index 0000000000000000000000000000000000000000..dd2177c9e2f167af3946119f381dcd7ec43d170c
--- /dev/null
+++ b/source/RobotAPI/components/armem/server/RobotStateMemory/aron_conversions.h
@@ -0,0 +1,23 @@
+#pragma once
+
+#include <memory>
+
+#include <SimoxUtility/meta/enum/EnumNames.hpp>
+
+#include <RobotAPI/interface/units/RobotUnit/RobotUnitInterface.h>
+
+
+namespace armarx::aron::datanavigator
+{
+    using NavigatorPtr = std::shared_ptr<class Navigator>;
+}
+
+namespace armarx::RobotUnitDataStreaming
+{
+    aron::datanavigator::NavigatorPtr toAron(
+        const TimeStep& timestep,
+        const DataEntry& dataEntry);
+
+    extern const simox::meta::EnumNames<DataEntryType> DataEntryNames;
+
+}
diff --git a/source/RobotAPI/libraries/RobotAPIComponentPlugins/RobotUnitComponentPlugin.cpp b/source/RobotAPI/libraries/RobotAPIComponentPlugins/RobotUnitComponentPlugin.cpp
index 4e6e7966cc4c71e819da47cd9a7ee06ccd536775..6647cf38585cb868a3df29e9c328bbfe8ac3a677 100644
--- a/source/RobotAPI/libraries/RobotAPIComponentPlugins/RobotUnitComponentPlugin.cpp
+++ b/source/RobotAPI/libraries/RobotAPIComponentPlugins/RobotUnitComponentPlugin.cpp
@@ -116,6 +116,19 @@ namespace armarx::plugins
     }
 
 
+    void RobotUnitComponentPlugin::waitUntilRobotUnitIsRunning(const std::function<bool ()>& termCond) const
+    {
+        ARMARX_INFO << "Waiting until robot unit is running ...";
+
+        while (not(termCond() or not isNullptr(getRobotUnit()) or getRobotUnit()->isRunning()))
+        {
+            std::this_thread::sleep_for(std::chrono::milliseconds(100));
+        }
+
+        ARMARX_INFO << "Robot unit is up and running.";
+    }
+
+
 
 
 }  // namespace armarx::plugins
diff --git a/source/RobotAPI/libraries/RobotAPIComponentPlugins/RobotUnitComponentPlugin.h b/source/RobotAPI/libraries/RobotAPIComponentPlugins/RobotUnitComponentPlugin.h
index 80357a96e9a3bb6c889d7b73435baef90a385b54..4371934b97182947afbaad3d60fd5295a717615a 100644
--- a/source/RobotAPI/libraries/RobotAPIComponentPlugins/RobotUnitComponentPlugin.h
+++ b/source/RobotAPI/libraries/RobotAPIComponentPlugins/RobotUnitComponentPlugin.h
@@ -34,6 +34,19 @@ namespace armarx
 
             }
 
+            /**
+             * @brief Waits until the robot unit is running.
+             *
+             * Although the robot unit proxy might be initialized (\see getRobotUnit()), the robot unit might
+             * not be fully initialized.
+             *
+             * @param termCond Termination condition.
+             *      If it evaluates to true, waitUntilRobotUnitIsRunning returns without waiting
+             *      for the robot unit to become available.
+             */
+            void waitUntilRobotUnitIsRunning(const std::function<bool()>& termCond = [] {return false;}) const;
+
+
 
             //controllers
         public:
diff --git a/source/RobotAPI/libraries/armem/CMakeLists.txt b/source/RobotAPI/libraries/armem/CMakeLists.txt
index eb53706cb8836fc40891372811738240b3522aa0..c606ae195f054e3d5afab9e075ffa3b04d884dff 100644
--- a/source/RobotAPI/libraries/armem/CMakeLists.txt
+++ b/source/RobotAPI/libraries/armem/CMakeLists.txt
@@ -99,6 +99,8 @@ set(LIB_FILES
     server/RemoteGuiAronDataVisitor.cpp
     server/Segment.cpp
 
+    server/segment/SpecializedSegment.cpp
+
     server/query_proc/base/BaseQueryProcessorBase.cpp
     server/query_proc/base/EntityQueryProcessorBase.cpp
     server/query_proc/base/ProviderSegmentQueryProcessorBase.cpp
@@ -140,6 +142,7 @@ set(LIB_HEADERS
     core/aron_conversions.h
     core/json_conversions.h
     core/ice_conversions.h
+    core/ice_conversions_boost_templates.h
     core/ice_conversions_templates.h
 
     core/error.h
@@ -220,6 +223,8 @@ set(LIB_HEADERS
     server/RemoteGuiAronDataVisitor.h
     server/Segment.h
 
+    server/segment/SpecializedSegment.h
+
     server/query_proc.h
     server/query_proc/base/BaseQueryProcessorBase.h
     server/query_proc/base/EntityQueryProcessorBase.h
diff --git a/source/RobotAPI/libraries/armem/client/ComponentPlugin.cpp b/source/RobotAPI/libraries/armem/client/ComponentPlugin.cpp
index a68e742cd24489694da91ef73ff557a6e8be1294..a88f374d6bddede5fd0b05eb28481d524f5f6b0a 100644
--- a/source/RobotAPI/libraries/armem/client/ComponentPlugin.cpp
+++ b/source/RobotAPI/libraries/armem/client/ComponentPlugin.cpp
@@ -31,7 +31,8 @@ armarx::armem::client::ComponentPluginUser::setMemoryServer(server::MemoryInterf
 armarx::armem::data::WaitForMemoryResult
 armarx::armem::client::ComponentPluginUser::useMemoryServer(const std::string& memoryName)
 {
-    armem::data::WaitForMemoryResult result = MemoryNameSystemComponentPluginUser::useMemoryServer(memoryName);
+    armem::data::WaitForMemoryResult result;
+    result.proxy = memoryNameSystem.useServer(MemoryID().withMemoryName(memoryName));
     if (result.proxy)
     {
         setMemoryServer(result.proxy);
diff --git a/source/RobotAPI/libraries/armem/client/ComponentPlugin.h b/source/RobotAPI/libraries/armem/client/ComponentPlugin.h
index 3bdbde93bd046bcceb361d94183be5fd1c09db23..ae3f26b26557c11046d84cde8a07483e4ba9ad49 100644
--- a/source/RobotAPI/libraries/armem/client/ComponentPlugin.h
+++ b/source/RobotAPI/libraries/armem/client/ComponentPlugin.h
@@ -2,7 +2,7 @@
 
 
 // ArmarX
-#include <ArmarXCore/core/Component.h>
+#include <ArmarXCore/core/ComponentPlugin.h>
 
 // RobotAPI
 #include <RobotAPI/interface/armem/server/MemoryInterface.h>
diff --git a/source/RobotAPI/libraries/armem/client/ReaderComponentPlugin.cpp b/source/RobotAPI/libraries/armem/client/ReaderComponentPlugin.cpp
index 3204c83cc094f3895e4ace10a4b91c9cdfeb1070..3ac9f7438408460c157f7484d313ef0d6a3808a6 100644
--- a/source/RobotAPI/libraries/armem/client/ReaderComponentPlugin.cpp
+++ b/source/RobotAPI/libraries/armem/client/ReaderComponentPlugin.cpp
@@ -2,6 +2,7 @@
 
 
 // ArmarX
+#include <ArmarXCore/core/Component.h>
 #include <ArmarXCore/core/exceptions/local/ExpressionException.h>
 
 // RobotAPI
@@ -47,11 +48,13 @@ namespace armarx::armem::client
 
     armem::data::WaitForMemoryResult ReaderComponentPluginUser::useMemoryServer(const std::string& memoryName)
     {
-        armem::data::WaitForMemoryResult result = MemoryNameSystemComponentPluginUser::useMemoryServer(memoryName);
+        armem::data::WaitForMemoryResult result;
+        result.proxy = memoryNameSystem.useServer(memoryName);
         if (result.proxy)
         {
             setReadingMemoryServer(result.proxy);
         }
         return result;
     }
+
 }
diff --git a/source/RobotAPI/libraries/armem/client/ReaderComponentPlugin.h b/source/RobotAPI/libraries/armem/client/ReaderComponentPlugin.h
index 0a2e37ba953e024858090cc64d6510dfebfd8a77..c0139e609e830e2c07517837f6cc3d48aff434db 100644
--- a/source/RobotAPI/libraries/armem/client/ReaderComponentPlugin.h
+++ b/source/RobotAPI/libraries/armem/client/ReaderComponentPlugin.h
@@ -5,7 +5,7 @@
 #include <vector>
 
 // ArmarX
-#include <ArmarXCore/core/Component.h>
+#include <ArmarXCore/core/ComponentPlugin.h>
 
 // RobotAPI
 #include <RobotAPI/libraries/aron/core/navigator/data/AllNavigators.h>
diff --git a/source/RobotAPI/libraries/armem/client/WriterComponentPlugin.cpp b/source/RobotAPI/libraries/armem/client/WriterComponentPlugin.cpp
index 093f29e6fa2178f19ae13983e21772f17400856d..d4b95ca3565e8552322e7e7cdfac131335ca06f3 100644
--- a/source/RobotAPI/libraries/armem/client/WriterComponentPlugin.cpp
+++ b/source/RobotAPI/libraries/armem/client/WriterComponentPlugin.cpp
@@ -2,6 +2,7 @@
 
 
 // ArmarX
+#include <ArmarXCore/core/Component.h>
 #include <ArmarXCore/core/exceptions/local/ExpressionException.h>
 
 // RobotAPI
@@ -43,9 +44,11 @@ namespace armarx::armem::client
         memoryWriter.setWritingMemory(memory);
     }
 
+
     armem::data::WaitForMemoryResult WriterComponentPluginUser::useMemoryServer(const std::string& memoryName)
     {
-        armem::data::WaitForMemoryResult result = MemoryNameSystemComponentPluginUser::useMemoryServer(memoryName);
+        armem::data::WaitForMemoryResult result;
+        result.proxy = memoryNameSystem.useServer(MemoryID().withMemoryName(memoryName));
         if (result.proxy)
         {
             setWritingMemoryServer(result.proxy);
diff --git a/source/RobotAPI/libraries/armem/client/WriterComponentPlugin.h b/source/RobotAPI/libraries/armem/client/WriterComponentPlugin.h
index 435881b48b27b9053dd5da5e87b794d3561f3b3c..3ae9a66bfab912237934d4bea6580a2e32a2c7fb 100644
--- a/source/RobotAPI/libraries/armem/client/WriterComponentPlugin.h
+++ b/source/RobotAPI/libraries/armem/client/WriterComponentPlugin.h
@@ -2,7 +2,7 @@
 
 
 // ArmarX
-#include <ArmarXCore/core/Component.h>
+#include <ArmarXCore/core/ComponentPlugin.h>
 
 // RobotAPI
 #include <RobotAPI/libraries/aron/core/navigator/data/AllNavigators.h>
diff --git a/source/RobotAPI/libraries/armem/core/base/EntityBase.h b/source/RobotAPI/libraries/armem/core/base/EntityBase.h
index ab227c33ee321475f129d8f864b5cbf31e3f4845..0775a71f977fde16966550f0506e9fd0f591e9a5 100644
--- a/source/RobotAPI/libraries/armem/core/base/EntityBase.h
+++ b/source/RobotAPI/libraries/armem/core/base/EntityBase.h
@@ -114,13 +114,13 @@ namespace armarx::armem::base
         }
 
 
-        inline const std::map<Time, EntitySnapshotT>& history() const
+        inline const ContainerT& history() const
         {
             return this->_container;
         }
-        inline std::map<Time, EntitySnapshotT>& history()
+        inline ContainerT& history()
         {
-            return const_cast<std::map<Time, EntitySnapshotT>&>(const_cast<const EntityBase*>(this)->history());
+            return const_cast<ContainerT&>(const_cast<const EntityBase*>(this)->history());
         }
 
 
@@ -226,7 +226,7 @@ namespace armarx::armem::base
         virtual const EntitySnapshotT& getLatestSnapshotBeforeOrAt(const Time& time) const
         {
             // first element equal or greater
-            typename std::map<Time, EntitySnapshotT>::const_iterator refIt = this->_container.upper_bound(time);
+            typename ContainerT::const_iterator refIt = this->_container.upper_bound(time);
 
             if (refIt == this->_container.begin())
             {
@@ -238,7 +238,7 @@ namespace armarx::armem::base
             }
 
             // last element less than
-            typename std::map<Time, EntitySnapshotT>::const_iterator refItPrev = std::prev(refIt);
+            typename ContainerT::const_iterator refItPrev = std::prev(refIt);
 
             // ... or we return the element before if possible
             if (refItPrev != this->_container.begin())
@@ -259,7 +259,7 @@ namespace armarx::armem::base
         virtual const EntitySnapshotT& getLatestSnapshotBefore(const Time& time) const
         {
             // first element equal or greater
-            typename std::map<Time, EntitySnapshotT>::const_iterator refIt = this->_container.upper_bound(time);
+            typename ContainerT::const_iterator refIt = this->_container.upper_bound(time);
 
             if (refIt == this->_container.begin())
             {
@@ -267,7 +267,7 @@ namespace armarx::armem::base
             }
 
             // last element less than
-            typename std::map<Time, EntitySnapshotT>::const_iterator refItPrev = std::prev(refIt);
+            typename ContainerT::const_iterator refItPrev = std::prev(refIt);
 
             // we return the element before if possible
             if (refItPrev != this->_container.begin())
@@ -311,7 +311,7 @@ namespace armarx::armem::base
         virtual const EntitySnapshotT& getFirstSnapshotAfterOrAt(const Time& time) const
         {
             // first element equal or greater
-            typename std::map<Time, EntitySnapshotT>::const_iterator refIt = this->_container.upper_bound(time);
+            typename ContainerT::const_iterator refIt = this->_container.upper_bound(time);
 
             if (refIt == this->_container.end())
             {
@@ -330,7 +330,7 @@ namespace armarx::armem::base
         virtual const EntitySnapshotT& getFirstSnapshotAfter(const Time& time) const
         {
             // first element equal or greater
-            typename std::map<Time, EntitySnapshotT>::const_iterator refIt = this->_container.upper_bound(time);
+            typename ContainerT::const_iterator refIt = this->_container.upper_bound(time);
 
             if (refIt == this->_container.end())
             {
@@ -343,7 +343,7 @@ namespace armarx::armem::base
             }
 
             // first element greater than
-            typename std::map<Time, EntitySnapshotT>::const_iterator refItNext = std::next(refIt);
+            typename ContainerT::const_iterator refItNext = std::next(refIt);
 
             if (refItNext != this->_container.end())
             {
@@ -418,7 +418,7 @@ namespace armarx::armem::base
 
         EntitySnapshotT& addSnapshot(EntitySnapshotT&& snapshot)
         {
-            auto it = this->_container.emplace(snapshot.time(), std::move(snapshot)).first;
+            auto it = this->_container.emplace_hint(this->_container.end(), snapshot.time(), std::move(snapshot));
             it->second.id().setEntityID(this->id());
             return it->second;
         }
@@ -473,7 +473,9 @@ namespace armarx::armem::base
          * @return The latest snapshot.
          * @throw `armem::error::EntityHistoryEmpty` If the history is empty.
          */
-        virtual const typename std::map<Time, EntitySnapshotT>::value_type& getLatestItem() const
+        virtual
+        const typename ContainerT::value_type&
+        getLatestItem() const
         {
             if (this->_container.empty())
             {
diff --git a/source/RobotAPI/libraries/armem/core/base/MemoryBase.h b/source/RobotAPI/libraries/armem/core/base/MemoryBase.h
index d7c8b8cd203fc8b140cbed0b959110f0868a4b83..73e70478fb9713536c266b01e9004ceb838be2a4 100644
--- a/source/RobotAPI/libraries/armem/core/base/MemoryBase.h
+++ b/source/RobotAPI/libraries/armem/core/base/MemoryBase.h
@@ -223,7 +223,7 @@ namespace armarx::armem::base
          * @param commit The commit.
          * @return The resulting memory IDs.
          */
-        std::vector<UpdateResult> update(const Commit& commit)
+        virtual std::vector<UpdateResult> update(const Commit& commit)
         {
             std::vector<UpdateResult> results;
             for (const auto& update : commit.updates)
@@ -238,7 +238,7 @@ namespace armarx::armem::base
          * @param update The update.
          * @return The resulting entity snapshot's ID.
          */
-        UpdateResult update(const EntityUpdate& update)
+        virtual UpdateResult update(const EntityUpdate& update)
         {
             this->_checkContainerName(update.entityID.memoryName, this->name());
 
diff --git a/source/RobotAPI/libraries/armem/core/diskmemory/CoreSegment.cpp b/source/RobotAPI/libraries/armem/core/diskmemory/CoreSegment.cpp
index 0f1bd0be881f477908464bcda5a4a858afb54488..b166468d81929da12c8204a6e2df9ab90b994528 100644
--- a/source/RobotAPI/libraries/armem/core/diskmemory/CoreSegment.cpp
+++ b/source/RobotAPI/libraries/armem/core/diskmemory/CoreSegment.cpp
@@ -96,7 +96,7 @@ namespace armarx::armem::d_ltm
                     return;
                 }
 
-                auto wms = _container.emplace(std::make_pair(k, id().withProviderSegmentName(k)));
+                auto wms = _container.emplace(k, id().withProviderSegmentName(k));
                 wms.first->second.path = path;
                 wms.first->second.append(s);
             }
diff --git a/source/RobotAPI/libraries/armem/core/ice_conversions_boost_templates.h b/source/RobotAPI/libraries/armem/core/ice_conversions_boost_templates.h
new file mode 100644
index 0000000000000000000000000000000000000000..7b6681236bc3d0517d6fd61656a1dc598a8d6a36
--- /dev/null
+++ b/source/RobotAPI/libraries/armem/core/ice_conversions_boost_templates.h
@@ -0,0 +1,34 @@
+#pragma once
+
+#include <map>
+
+#include <boost/container/flat_map.hpp>
+
+
+namespace armarx::armem
+{
+    // std::map <-> boost::container::flat_map
+
+    template <class IceKeyT, class IceValueT, class CppKeyT, class CppValueT>
+    void toIce(std::map<IceKeyT, IceValueT>& iceMap,
+               const boost::container::flat_map<CppKeyT, CppValueT>& cppMap)
+    {
+        iceMap.clear();
+        for (const auto& [key, value] : cppMap)
+        {
+            iceMap.emplace(toIce<IceKeyT>(key), toIce<IceValueT>(value));
+        }
+    }
+
+    template <class IceKeyT, class IceValueT, class CppKeyT, class CppValueT>
+    void fromIce(const std::map<IceKeyT, IceValueT>& iceMap,
+                 boost::container::flat_map<CppKeyT, CppValueT>& cppMap)
+    {
+        cppMap.clear();
+        for (const auto& [key, value] : iceMap)
+        {
+            cppMap.emplace(fromIce<CppKeyT>(key), fromIce<CppValueT>(value));
+        }
+    }
+
+}
diff --git a/source/RobotAPI/libraries/armem/core/longtermmemory/Entity.cpp b/source/RobotAPI/libraries/armem/core/longtermmemory/Entity.cpp
index 153852eaf50f4d71573c1bafdc44b052c0e1317c..aeb2be76e6ae6951188af4174b9b11dc51d736fc 100644
--- a/source/RobotAPI/libraries/armem/core/longtermmemory/Entity.cpp
+++ b/source/RobotAPI/libraries/armem/core/longtermmemory/Entity.cpp
@@ -1,5 +1,6 @@
 #include "Entity.h"
 
+
 namespace armarx::armem::ltm
 {
 
@@ -106,7 +107,7 @@ namespace armarx::armem::ltm
             snapshot.addInstance(instance);
         }
 
-        _container.insert({time, snapshot});
+        _container.emplace(time, snapshot);
         //truncateHistoryToSize();
         return true;
     }
@@ -142,7 +143,7 @@ namespace armarx::armem::ltm
         return Base::getSnapshot(time);
     }
 
-    const std::map<Time, EntitySnapshot>::value_type& Entity::getLatestItem() const
+    auto Entity::getLatestItem() const -> const ContainerT::value_type&
     {
         // Directly query mongodb (cache cant know whether it is the latest or not)
         // TODO
diff --git a/source/RobotAPI/libraries/armem/core/longtermmemory/Entity.h b/source/RobotAPI/libraries/armem/core/longtermmemory/Entity.h
index a5bca08c7ee0b7aff2a79d2c45aa37fc4baec1c4..20377befd61f741a642e139aafe1de3c2cc7f24b 100644
--- a/source/RobotAPI/libraries/armem/core/longtermmemory/Entity.h
+++ b/source/RobotAPI/libraries/armem/core/longtermmemory/Entity.h
@@ -71,7 +71,7 @@ namespace armarx::armem::ltm
 
     protected:
         // virtual overrides for LTM storage
-        virtual const std::map<Time, EntitySnapshot>::value_type& getLatestItem() const override;
+        virtual const ContainerT::value_type& getLatestItem() const override;
 
     public:
         MongoDBConnectionManager::MongoDBSettings dbsettings;
diff --git a/source/RobotAPI/libraries/armem/core/workingmemory/CoreSegment.cpp b/source/RobotAPI/libraries/armem/core/workingmemory/CoreSegment.cpp
index 285235b76e397952301c23d8218abb11f1f7aeaf..601f079350de8536aff130943d539eafee4e43b3 100644
--- a/source/RobotAPI/libraries/armem/core/workingmemory/CoreSegment.cpp
+++ b/source/RobotAPI/libraries/armem/core/workingmemory/CoreSegment.cpp
@@ -8,6 +8,36 @@
 namespace armarx::armem::wm
 {
 
+    CoreSegment::CoreSegment(const CoreSegment& other) :
+        CoreSegment::Base(other),
+        _mutex()
+    {
+        // Do not copy _mutex.
+    }
+
+
+    CoreSegment::CoreSegment(CoreSegment&& other) : CoreSegment::Base(other)
+    {
+        // Do not move _mutex.
+    }
+
+
+    CoreSegment& CoreSegment::operator=(const CoreSegment& other)
+    {
+        Base::operator=(other);
+        // Don't copy _mutex.
+        return *this;
+    }
+
+
+    CoreSegment& CoreSegment::operator=(CoreSegment&& other)
+    {
+        Base::operator=(other);
+        // Don't move _mutex.
+        return *this;
+    }
+
+
     Commit CoreSegment::toCommit() const
     {
         Commit c;
@@ -18,6 +48,7 @@ namespace armarx::armem::wm
         return c;
     }
 
+
     void CoreSegment::_copySelfWithoutData(CoreSegment& other) const
     {
         other.id() = _id;
@@ -27,4 +58,79 @@ namespace armarx::armem::wm
             other.addProviderSegment(s.copyWithoutData());
         }
     }
+
+
+    std::mutex& CoreSegment::mutex() const
+    {
+        return _mutex;
+    }
+
+
+    std::optional<wm::EntitySnapshot> CoreSegment::getLatestEntitySnapshot(const MemoryID& entityID) const
+    {
+        const wm::Entity& entity = this->getEntity(entityID);
+        if (entity.empty())
+        {
+            return std::nullopt;
+        }
+        else
+        {
+            return entity.getLatestSnapshot();
+        }
+    }
+
+
+    std::optional<wm::EntityInstance> CoreSegment::getLatestEntityInstance(
+        const MemoryID& entityID, int instanceIndex) const
+    {
+        auto snapshot = getLatestEntitySnapshot(entityID);
+        if (snapshot.has_value()
+            and instanceIndex >= 0
+            and static_cast<size_t>(instanceIndex) < snapshot->size())
+        {
+            return snapshot->getInstance(instanceIndex);
+        }
+        else
+        {
+            return std::nullopt;
+        }
+    }
+
+
+    armarx::aron::datanavigator::DictNavigatorPtr
+    CoreSegment::getLatestEntityInstanceData(const MemoryID& entityID, int instanceIndex) const
+    {
+        auto instance = getLatestEntityInstance(entityID, instanceIndex);
+        if (instance.has_value())
+        {
+            return instance->data();
+        }
+        else
+        {
+            return nullptr;
+        }
+    }
+
+
+    std::optional<wm::EntitySnapshot>
+    CoreSegment::getLatestEntitySnapshotLocking(const MemoryID& entityID) const
+    {
+        std::scoped_lock lock(_mutex);
+        return getLatestEntitySnapshot(entityID);
+    }
+
+    std::optional<wm::EntityInstance>
+    CoreSegment::getLatestEntityInstanceLocking(const MemoryID& entityID, int instanceIndex) const
+    {
+        std::scoped_lock lock(_mutex);
+        return getLatestEntityInstance(entityID, instanceIndex);
+    }
+
+    armarx::aron::datanavigator::DictNavigatorPtr
+    CoreSegment::getLatestEntityInstanceDataLocking(const MemoryID& entityID, int instanceIndex) const
+    {
+        std::scoped_lock lock(_mutex);
+        return getLatestEntityInstanceData(entityID, instanceIndex);
+    }
+
 }
diff --git a/source/RobotAPI/libraries/armem/core/workingmemory/CoreSegment.h b/source/RobotAPI/libraries/armem/core/workingmemory/CoreSegment.h
index 7847bbb71cc6a1a269556aeec07738c396e42a68..86b9b439e72d4d686b2c52fe5fd39f0a9b6aaf1c 100644
--- a/source/RobotAPI/libraries/armem/core/workingmemory/CoreSegment.h
+++ b/source/RobotAPI/libraries/armem/core/workingmemory/CoreSegment.h
@@ -1,5 +1,8 @@
 #pragma once
 
+#include <mutex>
+#include <optional>
+
 #include "../base/CoreSegmentBase.h"
 
 #include "ProviderSegment.h"
@@ -22,10 +25,10 @@ namespace armarx::armem::wm
 
         using Base::CoreSegmentBase;
 
-        CoreSegment(const CoreSegment& other) = default;
-        CoreSegment(CoreSegment&& other) = default;
-        CoreSegment& operator=(const CoreSegment& other) = default;
-        CoreSegment& operator=(CoreSegment&& other) = default;
+        CoreSegment(const CoreSegment& other);
+        CoreSegment(CoreSegment&& other);
+        CoreSegment& operator=(const CoreSegment& other);
+        CoreSegment& operator=(CoreSegment&& other);
 
         /**
          * @brief Convert the content of this segmnet into a commit
@@ -33,10 +36,76 @@ namespace armarx::armem::wm
          */
         Commit toCommit() const;
 
+        std::mutex& mutex() const;
+
+
+        // Non-locking interface
+
+        std::optional<wm::EntitySnapshot> getLatestEntitySnapshot(
+            const MemoryID& entityID) const;
+        std::optional<wm::EntityInstance> getLatestEntityInstance(
+            const MemoryID& entityID, int instanceIndex = 0) const;
+        armarx::aron::datanavigator::DictNavigatorPtr getLatestEntityInstanceData(
+            const MemoryID& entityID, int instanceIndex = 0) const;
+
+
+        template <class AronDtoT>
+        std::optional<AronDtoT> getLatestEntityInstanceDataAs(
+            const MemoryID& entityID, int instanceIndex = 0) const
+        {
+            wm::EntityInstanceDataPtr data = getLatestEntityInstanceData(entityID, instanceIndex);
+            if (data)
+            {
+                AronDtoT aron;
+                aron.fromAron(data);
+                return aron;
+            }
+            else
+            {
+                return std::nullopt;
+            }
+        }
+
+
+        // Locking interface
+
+        std::optional<wm::EntitySnapshot> getLatestEntitySnapshotLocking(
+            const MemoryID& entityID) const;
+        std::optional<wm::EntityInstance> getLatestEntityInstanceLocking(
+            const MemoryID& entityID, int instanceIndex = 0) const;
+        armarx::aron::datanavigator::DictNavigatorPtr getLatestEntityInstanceDataLocking(
+            const MemoryID& entityID, int instanceIndex = 0) const;
+
+
+        template <class AronDtoT>
+        std::optional<AronDtoT> getLatestEntityInstanceDataLockingAs(
+            const MemoryID& entityID, int instanceIndex = 0) const
+        {
+            // Keep lock to a minimum.
+            wm::EntityInstanceDataPtr data = nullptr;
+            {
+                std::scoped_lock lock(_mutex);
+                data = getLatestEntityInstanceData(entityID, instanceIndex);
+            }
+            if (data)
+            {
+                AronDtoT aron;
+                aron.fromAron(data);
+                return aron;
+            }
+            else
+            {
+                return std::nullopt;
+            }
+        }
+
+
     protected:
 
         virtual void _copySelfWithoutData(CoreSegment& other) const override;
 
+        mutable std::mutex _mutex;
+
     };
 
 }
diff --git a/source/RobotAPI/libraries/armem/core/workingmemory/EntityInstance.h b/source/RobotAPI/libraries/armem/core/workingmemory/EntityInstance.h
index 8e6eb1afe7e673baeab933397ebd16aa1781c18d..d3dc888d0304276bc6aaf1c677e8b33f4a1cae1a 100644
--- a/source/RobotAPI/libraries/armem/core/workingmemory/EntityInstance.h
+++ b/source/RobotAPI/libraries/armem/core/workingmemory/EntityInstance.h
@@ -8,6 +8,10 @@
 namespace armarx::armem::wm
 {
 
+    using EntityInstanceData = armarx::aron::datanavigator::DictNavigator;
+    using EntityInstanceDataPtr = armarx::aron::datanavigator::DictNavigatorPtr;
+
+
     /**
      * @brief Metadata of an entity instance.
      */
@@ -62,7 +66,7 @@ namespace armarx::armem::wm
             return _metadata;
         }
 
-        inline armarx::aron::datanavigator::DictNavigatorPtr data() const
+        inline EntityInstanceDataPtr data() const
         {
             return _data;
         }
@@ -97,7 +101,7 @@ namespace armarx::armem::wm
         EntityInstanceMetadata _metadata;
 
         /// The data. May be nullptr.
-        armarx::aron::datanavigator::DictNavigatorPtr _data;
+        EntityInstanceDataPtr _data;
 
     };
 }
diff --git a/source/RobotAPI/libraries/armem/core/workingmemory/Memory.cpp b/source/RobotAPI/libraries/armem/core/workingmemory/Memory.cpp
index 3d2efd2249f969308b126608d01533500f3bfa73..cd6c9cc58887cd5bd8833ffd06c92e30a0606ecb 100644
--- a/source/RobotAPI/libraries/armem/core/workingmemory/Memory.cpp
+++ b/source/RobotAPI/libraries/armem/core/workingmemory/Memory.cpp
@@ -1,8 +1,99 @@
 #include "Memory.h"
 
+#include <map>
+#include <vector>
+
 
 namespace armarx::armem::wm
 {
+
+    std::vector<Memory::Base::UpdateResult>
+    Memory::update(const Commit& commit)
+    {
+        std::vector<Memory::Base::UpdateResult> result;
+        for (const EntityUpdate& update : commit.updates)
+        {
+            result.push_back(this->update(update));
+        }
+        return result;
+    }
+
+
+    std::vector<Memory::Base::UpdateResult>
+    Memory::updateLocking(const Commit& commit)
+    {
+        // Group updates by core segment, then update each core segment in a batch to only lock it once.
+        std::map<std::string, std::vector<const EntityUpdate*>> updatesPerCoreSegment;
+        for (const EntityUpdate& update : commit.updates)
+        {
+            updatesPerCoreSegment[update.entityID.coreSegmentName].push_back(&update);
+        }
+
+        std::vector<Memory::Base::UpdateResult> result;
+        // To throw an exception after the commit if a core segment is missing.
+        std::vector<std::string> missingCoreSegmentNames;
+        for (const auto& [coreSegmentName, updates] : updatesPerCoreSegment)
+        {
+            auto it = this->_container.find(coreSegmentName);
+            if (it != this->_container.end())
+            {
+                CoreSegment& coreSegment = it->second;
+
+                // Lock the core segment for the whole batch.
+                std::scoped_lock lock(coreSegment.mutex());
+
+                for (const EntityUpdate* update : updates)
+                {
+                    auto r = coreSegment.update(*update);
+                    Base::UpdateResult ret { r };
+                    ret.memoryUpdateType = UpdateType::UpdatedExisting;
+                    result.push_back(ret);
+                }
+            }
+            else
+            {
+                // Perform the other updates first, then throw afterwards.
+                missingCoreSegmentNames.push_back(coreSegmentName);
+            }
+        }
+        // Throw an exception if something went wrong.
+        if (not missingCoreSegmentNames.empty())
+        {
+            // Just throw an exception for the first entry. We can extend this exception in the future.
+            throw armem::error::MissingEntry::create<CoreSegment>(missingCoreSegmentNames.front(), *this);
+        }
+        return result;
+    }
+
+
+    Memory::Base::UpdateResult
+    Memory::update(const EntityUpdate& update)
+    {
+        this->_checkContainerName(update.entityID.memoryName, this->name());
+
+        CoreSegment& segment = getCoreSegment(update.entityID.coreSegmentName);
+        Base::UpdateResult result = segment.update(update);
+        result.memoryUpdateType = UpdateType::UpdatedExisting;
+        return result;
+    }
+
+
+    Memory::Base::UpdateResult
+    Memory::updateLocking(const EntityUpdate& update)
+    {
+        this->_checkContainerName(update.entityID.memoryName, this->name());
+
+        CoreSegment& segment = getCoreSegment(update.entityID.coreSegmentName);
+        Base::UpdateResult result;
+        {
+            std::scoped_lock lock(segment.mutex());
+            result = segment.update(update);
+        }
+        result.memoryUpdateType = UpdateType::UpdatedExisting;
+        return result;
+    }
+
+
     Commit Memory::toCommit() const
     {
         Commit c;
@@ -13,6 +104,7 @@ namespace armarx::armem::wm
         return c;
     }
 
+
     void Memory::_copySelfWithoutData(Memory& other) const
     {
         other.id() = _id;
@@ -21,4 +113,5 @@ namespace armarx::armem::wm
             other.addCoreSegment(s.copyWithoutData());
         }
     }
+
 }
diff --git a/source/RobotAPI/libraries/armem/core/workingmemory/Memory.h b/source/RobotAPI/libraries/armem/core/workingmemory/Memory.h
index 3c64c0841b46a5c95f7f7365af26a1b20226f4dc..99a14dbdd291b0619733347cf2aec2ba365871f9 100644
--- a/source/RobotAPI/libraries/armem/core/workingmemory/Memory.h
+++ b/source/RobotAPI/libraries/armem/core/workingmemory/Memory.h
@@ -1,6 +1,6 @@
 #pragma once
 
-#include "../base/MemoryBase.h"
+#include <RobotAPI/libraries/armem/core/base/MemoryBase.h>
 
 #include "CoreSegment.h"
 #include "detail/CopyWithoutData.h"
@@ -27,12 +27,30 @@ namespace armarx::armem::wm
         Memory& operator=(const Memory& other) = default;
         Memory& operator=(Memory&& other) = default;
 
+
+        virtual std::vector<Base::UpdateResult> update(const Commit& commit) override;
+        /**
+         * @brief Perform the commit, locking the core segments.
+         *
+         * Groups the commits by core segment, and updates each core segment
+         * in a batch, locking the core segment.
+         */
+        std::vector<Base::UpdateResult> updateLocking(const Commit& commit);
+
+        virtual Base::UpdateResult update(const EntityUpdate& update) override;
+        /**
+         * @brief Update the memory, locking the updated core segment.
+         */
+        Base::UpdateResult updateLocking(const EntityUpdate& update);
+
+
         /**
          * @brief Convert the content of this memory into a commit
          * @return The resulting commit
          */
         Commit toCommit() const;
 
+
     protected:
 
         virtual void _copySelfWithoutData(Memory& other) const override;
diff --git a/source/RobotAPI/libraries/armem/core/workingmemory/visitor/FunctionalVisitor.h b/source/RobotAPI/libraries/armem/core/workingmemory/visitor/FunctionalVisitor.h
index 1c1b46e138c7eb2d713ba15b76ba77a2588ea0ce..34390a1823a6f3f1651bbe59ec815a0c1ab48bd6 100644
--- a/source/RobotAPI/libraries/armem/core/workingmemory/visitor/FunctionalVisitor.h
+++ b/source/RobotAPI/libraries/armem/core/workingmemory/visitor/FunctionalVisitor.h
@@ -53,28 +53,28 @@ namespace armarx::armem::wm
 
         bool visitEnter(const Memory& memory) override
         {
-            return memoryFn ? memoryConstFn(memory) : Visitor::visitEnter(memory);
+            return memoryConstFn ? memoryConstFn(memory) : Visitor::visitEnter(memory);
         }
         bool visitEnter(const CoreSegment& coreSegment) override
         {
-            return coreSegmentFn ? coreSegmentConstFn(coreSegment) : Visitor::visitEnter(coreSegment);
+            return coreSegmentConstFn ? coreSegmentConstFn(coreSegment) : Visitor::visitEnter(coreSegment);
         }
         bool visitEnter(const ProviderSegment& providerSegment) override
         {
-            return providerSegmentFn ? providerSegmentConstFn(providerSegment) : Visitor::visitEnter(providerSegment);
+            return providerSegmentConstFn ? providerSegmentConstFn(providerSegment) : Visitor::visitEnter(providerSegment);
         }
         bool visitEnter(const Entity& entity) override
         {
-            return entityFn ? entityConstFn(entity) : Visitor::visitEnter(entity);
+            return entityConstFn ? entityConstFn(entity) : Visitor::visitEnter(entity);
         }
         bool visitEnter(const EntitySnapshot& snapshot) override
         {
-            return memoryFn ? snapshotConstFn(snapshot) : Visitor::visitEnter(snapshot);
+            return snapshotConstFn ? snapshotConstFn(snapshot) : Visitor::visitEnter(snapshot);
         }
 
         bool visit(const EntityInstance& instance) override
         {
-            return instanceFn ? instanceConstFn(instance) : Visitor::visit(instance);
+            return instanceConstFn ? instanceConstFn(instance) : Visitor::visit(instance);
         }
 
 
diff --git a/source/RobotAPI/libraries/armem/server/ComponentPlugin.cpp b/source/RobotAPI/libraries/armem/server/ComponentPlugin.cpp
index 7b3a1d05817c9c25675abe2e5b8ab011aba1d92d..ddb1a96a79fefe069c3edaae44c53a211fc97e30 100644
--- a/source/RobotAPI/libraries/armem/server/ComponentPlugin.cpp
+++ b/source/RobotAPI/libraries/armem/server/ComponentPlugin.cpp
@@ -1,5 +1,6 @@
 #include "ComponentPlugin.h"
 
+#include <ArmarXCore/core/Component.h>
 #include <ArmarXCore/core/exceptions/local/ExpressionException.h>
 
 #include <RobotAPI/libraries/armem/core/error.h>
@@ -11,8 +12,7 @@
 
 namespace armarx::armem::server::plugins
 {
-    ComponentPlugin::~ComponentPlugin()
-    {}
+    ComponentPlugin::~ComponentPlugin() = default;
 
 
     void ComponentPlugin::postCreatePropertyDefinitions(PropertyDefinitionsPtr& properties)
@@ -118,6 +118,8 @@ namespace armarx::armem::server
         addPlugin(plugin);
     }
 
+    ComponentPluginUser::~ComponentPluginUser() = default;
+
 
     // WRITING
     data::AddSegmentsResult ComponentPluginUser::addSegments(const data::AddSegmentsInput& input, const Ice::Current&)
@@ -128,7 +130,7 @@ namespace armarx::armem::server
 
     data::AddSegmentsResult ComponentPluginUser::addSegments(const data::AddSegmentsInput& input, bool addCoreSegments)
     {
-        std::scoped_lock lock(workingMemoryMutex);
+        // std::scoped_lock lock(workingMemoryMutex);
         data::AddSegmentsResult result = iceMemory.addSegments(input, addCoreSegments);
         return result;
     }
@@ -136,7 +138,7 @@ namespace armarx::armem::server
 
     data::CommitResult ComponentPluginUser::commit(const data::Commit& commitIce, const Ice::Current&)
     {
-        std::scoped_lock lock(workingMemoryMutex);
+        // std::scoped_lock lock(workingMemoryMutex);
         return iceMemory.commit(commitIce);
     }
 
@@ -144,19 +146,20 @@ namespace armarx::armem::server
     // READING
     armem::query::data::Result ComponentPluginUser::query(const armem::query::data::Input& input, const Ice::Current&)
     {
-        std::scoped_lock lock(workingMemoryMutex);
+        // std::scoped_lock lock(workingMemoryMutex);
         return iceMemory.query(input);
     }
 
-    // LTM LOADING
+
+    // LTM STORING
     data::StoreResult ComponentPluginUser::store(const data::StoreInput& input, const Ice::Current&)
     {
-        std::scoped_lock lock(workingMemoryMutex, longtermMemoryMutex);
+        std::scoped_lock lock(/*workingMemoryMutex,*/ longtermMemoryMutex);
         return iceMemory.store(input);
     }
 
 
-    // LTM STORING
+    // LTM LOADING
     armem::query::data::Result ComponentPluginUser::load(const armem::query::data::Input& input, const Ice::Current&)
     {
         std::scoped_lock lock(longtermMemoryMutex);
diff --git a/source/RobotAPI/libraries/armem/server/ComponentPlugin.h b/source/RobotAPI/libraries/armem/server/ComponentPlugin.h
index 5f9ef1d574df06b1644d733e494273ce0660dbbf..06ba31f7a128549f51be85de300a92bdd310cf95 100644
--- a/source/RobotAPI/libraries/armem/server/ComponentPlugin.h
+++ b/source/RobotAPI/libraries/armem/server/ComponentPlugin.h
@@ -2,7 +2,7 @@
 
 #include <mutex>
 
-#include <ArmarXCore/core/Component.h>
+#include <ArmarXCore/core/ComponentPlugin.h>
 
 #include <RobotAPI/interface/armem/server/MemoryInterface.h>
 #include <RobotAPI/interface/armem/client/MemoryListenerInterface.h>
@@ -10,8 +10,8 @@
 
 #include <RobotAPI/libraries/armem/core/workingmemory/Memory.h>
 #include <RobotAPI/libraries/armem/core/longtermmemory/Memory.h>
-
 #include <RobotAPI/libraries/armem/client/MemoryNameSystemComponentPlugin.h>
+
 #include "MemoryToIceAdapter.h"
 
 
@@ -73,7 +73,7 @@ namespace armarx::armem::server
     public:
 
         ComponentPluginUser();
-        virtual ~ComponentPluginUser() override = default;
+        virtual ~ComponentPluginUser() override;
 
 
         // WritingInterface interface
@@ -96,9 +96,11 @@ namespace armarx::armem::server
 
 
     public:
+
         /// The actual memory.
         wm::Memory workingMemory;
-        std::mutex workingMemoryMutex;
+        // [[deprecated ("The global working memory mutex is deprecated. Use the core segment mutexes instead.")]]
+        // std::mutex workingMemoryMutex;
 
         bool longtermMemoryEnabled = true;
         ltm::Memory longtermMemory;
@@ -112,6 +114,7 @@ namespace armarx::armem::server
 
 
     private:
+
         plugins::ComponentPlugin* plugin = nullptr;
 
     };
diff --git a/source/RobotAPI/libraries/armem/server/MemoryRemoteGui.cpp b/source/RobotAPI/libraries/armem/server/MemoryRemoteGui.cpp
index 9ab34efd946541a37ae825d6338a355aec0dd722..9347cb7e9234723d33407693cb68ec1f5ea8448d 100644
--- a/source/RobotAPI/libraries/armem/server/MemoryRemoteGui.cpp
+++ b/source/RobotAPI/libraries/armem/server/MemoryRemoteGui.cpp
@@ -31,9 +31,10 @@ namespace armarx::armem::server
     }
 
 
-
     MemoryRemoteGui::GroupBox MemoryRemoteGui::makeGroupBox(const wm::CoreSegment& coreSegment) const
     {
+        std::scoped_lock lock(coreSegment.mutex());
+
         GroupBox group;
         group.setLabel(makeGroupLabel("Core Segment", coreSegment.name(), coreSegment.providerSegments().size()));
 
@@ -50,7 +51,6 @@ namespace armarx::armem::server
     }
 
 
-
     MemoryRemoteGui::GroupBox MemoryRemoteGui::makeGroupBox(const wm::ProviderSegment& providerSegment) const
     {
         GroupBox group;
@@ -69,7 +69,6 @@ namespace armarx::armem::server
     }
 
 
-
     MemoryRemoteGui::GroupBox MemoryRemoteGui::makeGroupBox(const wm::Entity& entity) const
     {
         GroupBox group;
@@ -109,7 +108,6 @@ namespace armarx::armem::server
     }
 
 
-
     MemoryRemoteGui::GroupBox MemoryRemoteGui::makeGroupBox(const wm::EntitySnapshot& snapshot) const
     {
         GroupBox group;
@@ -129,6 +127,7 @@ namespace armarx::armem::server
         return group;
     }
 
+
     MemoryRemoteGui::GroupBox MemoryRemoteGui::makeGroupBox(const wm::EntityInstance& instance) const
     {
         GroupBox group;
@@ -153,7 +152,6 @@ namespace armarx::armem::server
     }
 
 
-
     std::string MemoryRemoteGui::makeGroupLabel(
         const std::string& term, const std::string& name, size_t size,
         const std::string& namePrefix, const std::string& nameSuffix) const
diff --git a/source/RobotAPI/libraries/armem/server/MemoryToIceAdapter.cpp b/source/RobotAPI/libraries/armem/server/MemoryToIceAdapter.cpp
index a846cffac89c6118b6c476d3531e47cd49f96f8a..c40805a0f8a79413eb33418154a18194be6a22ba 100644
--- a/source/RobotAPI/libraries/armem/server/MemoryToIceAdapter.cpp
+++ b/source/RobotAPI/libraries/armem/server/MemoryToIceAdapter.cpp
@@ -55,6 +55,7 @@ namespace armarx::armem::server
 
         if (input.providerSegmentName.size() > 0)
         {
+            std::scoped_lock lock(coreSegment->mutex());
             try
             {
                 coreSegment->addProviderSegment(input.providerSegmentName);
@@ -94,6 +95,7 @@ namespace armarx::armem::server
         return output;
     }
 
+
     data::CommitResult
     MemoryToIceAdapter::commit(const data::Commit& commitIce, Time timeArrived)
     {
@@ -140,9 +142,21 @@ namespace armarx::armem::server
 
     armem::CommitResult
     MemoryToIceAdapter::commit(const armem::Commit& commit)
+    {
+        return this->_commit(commit, false);
+    }
+
+
+    armem::CommitResult MemoryToIceAdapter::commitLocking(const armem::Commit& commit)
+    {
+        return this->_commit(commit, true);
+    }
+
+
+    armem::CommitResult MemoryToIceAdapter::_commit(const armem::Commit& commit, bool locking)
     {
         std::vector<data::MemoryID> updatedIDs;
-        const bool publishUpdates = memoryListenerTopic;
+        const bool publishUpdates = bool(memoryListenerTopic);
 
         CommitResult commitResult;
         for (const EntityUpdate& update : commit.updates)
@@ -150,7 +164,9 @@ namespace armarx::armem::server
             EntityUpdateResult& result = commitResult.results.emplace_back();
             try
             {
-                auto updateResult = workingMemory->update(update);
+                auto updateResult = locking
+                                    ? workingMemory->updateLocking(update)
+                                    : workingMemory->update(update);
 
                 result.success = true;
                 result.snapshotID = updateResult.id;
@@ -200,29 +216,27 @@ namespace armarx::armem::server
     {
         ARMARX_CHECK_NOT_NULL(workingMemory);
 
-        armem::wm::query_proc::MemoryQueryProcessor wm_processor(
-            input.withData ? armem::DataMode::WithData
-            : armem::DataMode::NoData);
-
-        armem::query::data::Result result;
-        wm::Memory wm_result = wm_processor.process(input, *workingMemory, /* execute if: */ { query::data::QueryTarget::WM });
+        // Core segment processors will aquire the core segment locks.
+        armem::wm::query_proc::MemoryQueryProcessor wmProcessor(
+            input.withData ? armem::DataMode::WithData : armem::DataMode::NoData);
+        wm::Memory wmResult = wmProcessor.process(input, *workingMemory, /* execute if: */ { query::data::QueryTarget::WM });
 
-        armem::ltm::query_proc::MemoryQueryProcessor ltm_processor;
-        ltm::Memory ltm_result = ltm_processor.process(input, *longtermMemory, /* execute if: */ { query::data::QueryTarget::LTM });
+        armem::ltm::query_proc::MemoryQueryProcessor ltmProcessor;
+        ltm::Memory ltmResult = ltmProcessor.process(input, *longtermMemory, /* execute if: */ { query::data::QueryTarget::LTM });
 
-
-        if (ltm_result.hasData())
+        armem::query::data::Result result;
+        if (ltmResult.hasData())
         {
             // ATTENTION: This code block moves data from LTM back into WM.
             // However, since some segments are constrained, the WM might send data back to LTM.
             // This may also affect the data returned by the current query.
             // However, this is expected behavior, since we copy the data in the processor (copyEmpty) we can safely return the copy and
             // remove the original memory reference from WM here.
-            wm::Memory ltm_converted = ltm_result.convert();
-            wm_result.append(ltm_converted);
+            wm::Memory ltmConverted = ltmResult.convert();
+            wmResult.append(ltmConverted);
 
             // query again to limit output size (TODO: Skip if querytype is all)
-            wm::Memory merged_result = wm_processor.process(input, wm_result);
+            wm::Memory merged_result = wmProcessor.process(input, wmResult);
             result.memory = toIce<data::MemoryPtr>(merged_result);
 
             // also move results of ltm to wm
@@ -233,7 +247,7 @@ namespace armarx::armem::server
         }
         else
         {
-            result.memory = toIce<data::MemoryPtr>(wm_result);
+            result.memory = toIce<data::MemoryPtr>(wmResult);
         }
 
         result.success = true;
@@ -245,6 +259,13 @@ namespace armarx::armem::server
         return result;
     }
 
+
+    client::QueryResult MemoryToIceAdapter::query(const client::QueryInput& input)
+    {
+        return client::QueryResult::fromIce(query(input.toIce()));
+    }
+
+
     // LTM LOADING FROM LTM
     query::data::Result MemoryToIceAdapter::load(const armem::query::data::Input& query)
     {
@@ -255,6 +276,7 @@ namespace armarx::armem::server
         return output;
     }
 
+
     // LTM STORING
     data::StoreResult MemoryToIceAdapter::store(const armem::data::StoreInput& input)
     {
@@ -282,9 +304,8 @@ namespace armarx::armem::server
         return output;
     }
 
-    client::QueryResult MemoryToIceAdapter::query(const client::QueryInput& input)
-    {
-        return client::QueryResult::fromIce(query(input.toIce()));
-    }
+
+
+
 
 }
diff --git a/source/RobotAPI/libraries/armem/server/MemoryToIceAdapter.h b/source/RobotAPI/libraries/armem/server/MemoryToIceAdapter.h
index 919c5fc8dc74ec3f742ac1c33365bc2c680ac768..f4b4b4c94eac3a51cb8c90e2fcabfc09288e3ead 100644
--- a/source/RobotAPI/libraries/armem/server/MemoryToIceAdapter.h
+++ b/source/RobotAPI/libraries/armem/server/MemoryToIceAdapter.h
@@ -39,6 +39,8 @@ namespace armarx::armem::server
         data::CommitResult commit(const data::Commit& commitIce, Time timeArrived);
         data::CommitResult commit(const data::Commit& commitIce);
         armem::CommitResult commit(const armem::Commit& commit);
+        armem::CommitResult commitLocking(const armem::Commit& commit);
+
 
         // READING
         query::data::Result query(const armem::query::data::Input& input);
@@ -57,6 +59,11 @@ namespace armarx::armem::server
 
         client::MemoryListenerInterfacePrx memoryListenerTopic;
 
+
+    private:
+
+        armem::CommitResult _commit(const armem::Commit& commit, bool locking);
+
     };
 
 
diff --git a/source/RobotAPI/libraries/armem/server/query_proc/base/BaseQueryProcessorBase.cpp b/source/RobotAPI/libraries/armem/server/query_proc/base/BaseQueryProcessorBase.cpp
index ce437fd67bdd2ba3aa6ac9943093525db99a581e..34e2abd99c889d65723065c8b4726b2ea0aa9bd1 100644
--- a/source/RobotAPI/libraries/armem/server/query_proc/base/BaseQueryProcessorBase.cpp
+++ b/source/RobotAPI/libraries/armem/server/query_proc/base/BaseQueryProcessorBase.cpp
@@ -1 +1,2 @@
 #include "BaseQueryProcessorBase.h"
+
diff --git a/source/RobotAPI/libraries/armem/server/query_proc/base/BaseQueryProcessorBase.h b/source/RobotAPI/libraries/armem/server/query_proc/base/BaseQueryProcessorBase.h
index f71aede29731259471cf5e8dd660917b3e848bb1..95943dd2f18289360336c22b910913835a84c604 100644
--- a/source/RobotAPI/libraries/armem/server/query_proc/base/BaseQueryProcessorBase.h
+++ b/source/RobotAPI/libraries/armem/server/query_proc/base/BaseQueryProcessorBase.h
@@ -19,6 +19,9 @@ namespace armarx::armem::base::query_proc
 
     public:
 
+        virtual ~BaseQueryProcessorBase() = default;
+
+
         DataT process(const QueryT& query, const DataT& data, const query::data::QueryTargets& executeIf = {}) const
         {
             DataT result = data.copyEmpty();
diff --git a/source/RobotAPI/libraries/armem/server/query_proc/base/CoreSegmentQueryProcessorBase.h b/source/RobotAPI/libraries/armem/server/query_proc/base/CoreSegmentQueryProcessorBase.h
index f8ab8c113e510e57a1ab2b53af6a06e60e393ce1..9d7b2518227e4ddf0c5d759963af193656e39894 100644
--- a/source/RobotAPI/libraries/armem/server/query_proc/base/CoreSegmentQueryProcessorBase.h
+++ b/source/RobotAPI/libraries/armem/server/query_proc/base/CoreSegmentQueryProcessorBase.h
@@ -1,17 +1,15 @@
 #pragma once
 
-#include <RobotAPI/interface/armem/query.h>
-
-#include "BaseQueryProcessorBase.h"
-#include "ProviderSegmentQueryProcessorBase.h"
-
 #include <regex>
 
 #include <ArmarXCore/core/logging/Logging.h>
 #include <ArmarXCore/core/exceptions/local/ExpressionException.h>
 
+#include <RobotAPI/interface/armem/query.h>
 #include <RobotAPI/libraries/armem/core/error.h>
 
+#include "BaseQueryProcessorBase.h"
+#include "ProviderSegmentQueryProcessorBase.h"
 
 
 namespace armarx::armem::base::query_proc
@@ -33,9 +31,9 @@ namespace armarx::armem::base::query_proc
         using EntitySnapshotT = typename EntityT::EntitySnapshotT;
 
         using Base::process;
-        void process(_CoreSegmentT& result,
-                     const armem::query::data::CoreSegmentQuery& query,
-                     const _CoreSegmentT& coreSegment) const override
+        virtual void process(_CoreSegmentT& result,
+                             const armem::query::data::CoreSegmentQuery& query,
+                             const _CoreSegmentT& coreSegment) const override
         {
             if (auto q = dynamic_cast<const armem::query::data::core::All*>(&query))
             {
diff --git a/source/RobotAPI/libraries/armem/server/query_proc/diskmemory/EntityQueryProcessor.h b/source/RobotAPI/libraries/armem/server/query_proc/diskmemory/EntityQueryProcessor.h
index 4d1b9e14e21804f1e44f1a2fd6456da37a113c03..c57c2c2da39ca53ce97d27b498e69b648a16f25a 100644
--- a/source/RobotAPI/libraries/armem/server/query_proc/diskmemory/EntityQueryProcessor.h
+++ b/source/RobotAPI/libraries/armem/server/query_proc/diskmemory/EntityQueryProcessor.h
@@ -19,11 +19,14 @@ namespace armarx::armem::d_ltm::query_proc
         using Base = BaseQueryProcessor<d_ltm::Entity, armem::query::data::EntityQuery>;
 
     public:
+
         EntityQueryProcessor() :
             Base()
         {}
 
+
     private:
+
         void addResultSnapshot(d_ltm::Entity& result, d_ltm::Entity::ContainerT::const_iterator it) const override
         {
             addResultSnapshot(result, it->second);
diff --git a/source/RobotAPI/libraries/armem/server/query_proc/workingmemory/BaseQueryProcessor.h b/source/RobotAPI/libraries/armem/server/query_proc/workingmemory/BaseQueryProcessor.h
index 99811dcc72d168dfecb0c5864f0760c4d5634a6e..933f9a6fd628b8c2747c2c6449499e596593935b 100644
--- a/source/RobotAPI/libraries/armem/server/query_proc/workingmemory/BaseQueryProcessor.h
+++ b/source/RobotAPI/libraries/armem/server/query_proc/workingmemory/BaseQueryProcessor.h
@@ -1,11 +1,9 @@
 #pragma once
 
-#include <RobotAPI/libraries/armem/core/workingmemory/ice_conversions.h>
-
 #include <RobotAPI/interface/armem/query.h>
 #include <RobotAPI/libraries/armem/core/DataMode.h>
 
-#include "../base/BaseQueryProcessorBase.h"
+#include <RobotAPI/libraries/armem/server/query_proc/base/BaseQueryProcessorBase.h>
 
 
 namespace armarx::armem::wm::query_proc
@@ -20,11 +18,15 @@ namespace armarx::armem::wm::query_proc
         using Base = base::query_proc::BaseQueryProcessorBase<DataT, QueryT>;
 
     public:
+
         BaseQueryProcessor(DataMode dataMode = DataMode::WithData) :
             dataMode(dataMode)
         {}
 
+
     protected:
+
         DataMode dataMode;
+
     };
 }
diff --git a/source/RobotAPI/libraries/armem/server/query_proc/workingmemory/CoreSegmentQueryProcessor.cpp b/source/RobotAPI/libraries/armem/server/query_proc/workingmemory/CoreSegmentQueryProcessor.cpp
index afbe35ad15eea0342b0b0d4df0200aaf0d32aa2a..bda9ad04de5ac7cd46be68a2f5f7ca2ec1419040 100644
--- a/source/RobotAPI/libraries/armem/server/query_proc/workingmemory/CoreSegmentQueryProcessor.cpp
+++ b/source/RobotAPI/libraries/armem/server/query_proc/workingmemory/CoreSegmentQueryProcessor.cpp
@@ -1 +1,39 @@
 #include "CoreSegmentQueryProcessor.h"
+
+#include <RobotAPI/libraries/armem/core/workingmemory/ice_conversions.h>
+
+
+namespace armarx::armem::wm::query_proc
+{
+
+    CoreSegmentQueryProcessor::CoreSegmentQueryProcessor(DataMode dataMode) :
+        Base(dataMode), providerSegmentProcessor(dataMode)
+    {}
+
+
+    CoreSegmentQueryProcessor::~CoreSegmentQueryProcessor() = default;
+
+
+    void CoreSegmentQueryProcessor::process(
+        CoreSegment& result, const armem::query::data::CoreSegmentQuery& query, const CoreSegment& coreSegment) const
+    {
+        std::scoped_lock lock(coreSegment.mutex());
+        CoreSegmentQueryProcessorBase::process(result, query, coreSegment);
+    }
+
+
+    data::CoreSegment CoreSegmentQueryProcessor::processToIce(const armem::query::data::CoreSegmentQuery& query, const wm::CoreSegment& coreSegment) const
+    {
+        data::CoreSegment data;
+        toIce(data, process(query, coreSegment));
+        return data;
+    }
+
+
+    ProviderSegment CoreSegmentQueryProcessor::providerSegmentProcessorProcess(const armem::query::data::ProviderSegmentQuerySeq& q, const ProviderSegment& s) const
+    {
+        return providerSegmentProcessor.process(q, s, {armem::query::data::QueryTarget::WM});
+    }
+
+
+}
diff --git a/source/RobotAPI/libraries/armem/server/query_proc/workingmemory/CoreSegmentQueryProcessor.h b/source/RobotAPI/libraries/armem/server/query_proc/workingmemory/CoreSegmentQueryProcessor.h
index 390ab66f656ece6010457f12f09917d9fca413f6..f9e1d59c9f75866e3817440bb163ec5789c0f359 100644
--- a/source/RobotAPI/libraries/armem/server/query_proc/workingmemory/CoreSegmentQueryProcessor.h
+++ b/source/RobotAPI/libraries/armem/server/query_proc/workingmemory/CoreSegmentQueryProcessor.h
@@ -1,8 +1,11 @@
 #pragma once
 
-#include "BaseQueryProcessor.h"
-#include "../base/CoreSegmentQueryProcessorBase.h"
+#include <mutex>
+
+#include <RobotAPI/libraries/armem/core/workingmemory/CoreSegment.h>
+#include <RobotAPI/libraries/armem/server/query_proc/base/CoreSegmentQueryProcessorBase.h>
 
+#include "BaseQueryProcessor.h"
 #include "ProviderSegmentQueryProcessor.h"
 
 
@@ -18,23 +21,28 @@ namespace armarx::armem::wm::query_proc
         using Base = BaseQueryProcessor<wm::CoreSegment, armem::query::data::CoreSegmentQuery>;
 
     public:
-        CoreSegmentQueryProcessor(DataMode dataMode = DataMode::WithData) :
-            Base(dataMode), providerSegmentProcessor(dataMode)
-        {}
+
+        CoreSegmentQueryProcessor(DataMode dataMode = DataMode::WithData);
+        virtual ~CoreSegmentQueryProcessor() override;
 
         using Base::process;
-        data::CoreSegment processToIce(const armem::query::data::CoreSegmentQuery& query, const wm::CoreSegment& coreSegment) const
-        {
-            return toIce<data::CoreSegment>(process(query, coreSegment));
-        }
+
+        /// Locks the core segment, then delegates back to `CoreSegmentQueryProcessorBase`.
+        void process(CoreSegment& result,
+                     const armem::query::data::CoreSegmentQuery& query,
+                     const CoreSegment& coreSegment) const override;
+
+        data::CoreSegment processToIce(const armem::query::data::CoreSegmentQuery& query, const wm::CoreSegment& coreSegment) const;
+
 
     protected:
-        virtual ProviderSegmentT providerSegmentProcessorProcess(const armem::query::data::ProviderSegmentQuerySeq& q, const ProviderSegmentT& s) const override
-        {
-            return providerSegmentProcessor.process(q, s, {armem::query::data::QueryTarget::WM});
-        }
+
+        virtual ProviderSegment providerSegmentProcessorProcess(const armem::query::data::ProviderSegmentQuerySeq& q, const ProviderSegmentT& s) const override;
+
 
     private:
+
         ProviderSegmentQueryProcessor providerSegmentProcessor;
+
     };
 }
diff --git a/source/RobotAPI/libraries/armem/server/query_proc/workingmemory/EntityQueryProcessor.cpp b/source/RobotAPI/libraries/armem/server/query_proc/workingmemory/EntityQueryProcessor.cpp
index c1c321b026b173c6552758fb9d8b9fdf722ea5a4..7ef31f2badfbffbf49f132c855b2143b8ddc10bd 100644
--- a/source/RobotAPI/libraries/armem/server/query_proc/workingmemory/EntityQueryProcessor.cpp
+++ b/source/RobotAPI/libraries/armem/server/query_proc/workingmemory/EntityQueryProcessor.cpp
@@ -1 +1,43 @@
 #include "EntityQueryProcessor.h"
+
+#include <RobotAPI/libraries/armem/core/workingmemory/ice_conversions.h>
+
+
+namespace armarx::armem::wm::query_proc
+{
+    EntityQueryProcessor::EntityQueryProcessor(DataMode dataMode) :
+        Base(dataMode)
+    {}
+
+
+    EntityQueryProcessor::~EntityQueryProcessor() = default;
+
+
+    void EntityQueryProcessor::addResultSnapshot(wm::Entity& result, const wm::EntitySnapshot& snapshot) const
+    {
+        bool withData = (dataMode == DataMode::WithData);
+        if (withData)
+        {
+            result.addSnapshot(snapshot.copy());
+        }
+        else
+        {
+            result.addSnapshot(snapshot.copyWithoutData());
+        }
+    }
+
+
+    data::Entity EntityQueryProcessor::processToIce(const armem::query::data::EntityQuery& query, const wm::Entity& entity) const
+    {
+        data::Entity data;
+        toIce(data, process(query, entity));
+        return data;
+    }
+
+
+    void EntityQueryProcessor::addResultSnapshot(wm::Entity& result, wm::Entity::ContainerT::const_iterator it) const
+    {
+        addResultSnapshot(result, it->second);
+    }
+
+}
diff --git a/source/RobotAPI/libraries/armem/server/query_proc/workingmemory/EntityQueryProcessor.h b/source/RobotAPI/libraries/armem/server/query_proc/workingmemory/EntityQueryProcessor.h
index 94dc905e489be501257be508cff03c7efee8f8b8..dde53a8ff3393dde385ccc49aa937fcf196476d0 100644
--- a/source/RobotAPI/libraries/armem/server/query_proc/workingmemory/EntityQueryProcessor.h
+++ b/source/RobotAPI/libraries/armem/server/query_proc/workingmemory/EntityQueryProcessor.h
@@ -1,9 +1,10 @@
 #pragma once
 
+#include <RobotAPI/libraries/armem/core/workingmemory/Entity.h>
+#include <RobotAPI/libraries/armem/server/query_proc/base/EntityQueryProcessorBase.h>
+
 #include "BaseQueryProcessor.h"
-#include "../base/EntityQueryProcessorBase.h"
 
-#include "EntityQueryProcessor.h"
 
 namespace armarx::armem::wm::query_proc
 {
@@ -17,33 +18,17 @@ namespace armarx::armem::wm::query_proc
         using Base = BaseQueryProcessor<wm::Entity, armem::query::data::EntityQuery>;
 
     public:
-        EntityQueryProcessor(DataMode dataMode = DataMode::WithData) :
-            Base(dataMode)
-        {}
 
-        data::Entity processToIce(const armem::query::data::EntityQuery& query, const wm::Entity& entity) const
-        {
-            return toIce<data::Entity>(process(query, entity));
-        }
+        EntityQueryProcessor(DataMode dataMode = DataMode::WithData);
+        virtual ~EntityQueryProcessor() override;
+
+        data::Entity processToIce(const armem::query::data::EntityQuery& query, const wm::Entity& entity) const;
+
 
     private:
-        void addResultSnapshot(wm::Entity& result, wm::Entity::ContainerT::const_iterator it) const override
-        {
-            addResultSnapshot(result, it->second);
-        }
-
-        void addResultSnapshot(wm::Entity& result, const wm::EntitySnapshot& snapshot) const override
-        {
-            bool withData = (dataMode == DataMode::WithData);
-            if (withData)
-            {
-                result.addSnapshot(snapshot.copy());
-            }
-            else
-            {
-                result.addSnapshot(snapshot.copyWithoutData());
-            }
-        }
+
+        void addResultSnapshot(wm::Entity& result, wm::Entity::ContainerT::const_iterator it) const override;
+        void addResultSnapshot(wm::Entity& result, const wm::EntitySnapshot& snapshot) const override;
 
     };
 
diff --git a/source/RobotAPI/libraries/armem/server/query_proc/workingmemory/MemoryQueryProcessor.cpp b/source/RobotAPI/libraries/armem/server/query_proc/workingmemory/MemoryQueryProcessor.cpp
index 69b04de6c9e623286a5bda836dddfdc8b551b64a..dd249b61caaacaca11e369b19b8f4e0da1dc5cf5 100644
--- a/source/RobotAPI/libraries/armem/server/query_proc/workingmemory/MemoryQueryProcessor.cpp
+++ b/source/RobotAPI/libraries/armem/server/query_proc/workingmemory/MemoryQueryProcessor.cpp
@@ -1 +1,22 @@
 #include "MemoryQueryProcessor.h"
+
+
+namespace armarx::armem::wm::query_proc
+{
+
+    MemoryQueryProcessor::MemoryQueryProcessor(DataMode dataMode) :
+        Base(dataMode), coreSegmentProcessor(dataMode)
+    {}
+
+
+    MemoryQueryProcessor::~MemoryQueryProcessor()
+    {
+    }
+
+
+    CoreSegment MemoryQueryProcessor::coreSegmentProcessorProcess(const armem::query::data::CoreSegmentQuerySeq& q, const CoreSegment& s) const
+    {
+        return coreSegmentProcessor.process(q, s, {armem::query::data::QueryTarget::WM});
+    }
+
+}
diff --git a/source/RobotAPI/libraries/armem/server/query_proc/workingmemory/MemoryQueryProcessor.h b/source/RobotAPI/libraries/armem/server/query_proc/workingmemory/MemoryQueryProcessor.h
index 8284df202bbcf602e2433639fe85388ca13d75ff..c57eea94a464a2e2191e614b5f1d6095d716405a 100644
--- a/source/RobotAPI/libraries/armem/server/query_proc/workingmemory/MemoryQueryProcessor.h
+++ b/source/RobotAPI/libraries/armem/server/query_proc/workingmemory/MemoryQueryProcessor.h
@@ -1,10 +1,13 @@
 #pragma once
 
+#include <RobotAPI/libraries/armem/core/workingmemory/Memory.h>
+#include <RobotAPI/libraries/armem/server/query_proc/base/MemoryQueryProcessorBase.h>
+
 #include "BaseQueryProcessor.h"
-#include "../base/MemoryQueryProcessorBase.h"
 
 #include "CoreSegmentQueryProcessor.h"
 
+
 namespace armarx::armem::wm::query_proc
 {
     /**
@@ -17,18 +20,20 @@ namespace armarx::armem::wm::query_proc
         using Base = BaseQueryProcessor<wm::Memory, armem::query::data::MemoryQuery>;
 
     public:
-        MemoryQueryProcessor(DataMode dataMode = DataMode::WithData) :
-            Base(dataMode), coreSegmentProcessor(dataMode)
-        {}
+
+        MemoryQueryProcessor(DataMode dataMode = DataMode::WithData);
+        virtual ~MemoryQueryProcessor() override;
+
 
     protected:
-        virtual CoreSegmentT coreSegmentProcessorProcess(const armem::query::data::CoreSegmentQuerySeq& q, const CoreSegmentT& s) const override
-        {
-            return coreSegmentProcessor.process(q, s, {armem::query::data::QueryTarget::WM});
-        }
+
+        virtual CoreSegment coreSegmentProcessorProcess(
+            const armem::query::data::CoreSegmentQuerySeq& q, const CoreSegment& s) const override;
 
 
     private:
+
         CoreSegmentQueryProcessor coreSegmentProcessor;
+
     };
 }
diff --git a/source/RobotAPI/libraries/armem/server/query_proc/workingmemory/ProviderSegmentQueryProcessor.cpp b/source/RobotAPI/libraries/armem/server/query_proc/workingmemory/ProviderSegmentQueryProcessor.cpp
index 9a2a4405001f0904b74fc6afcf96813eef0879cd..a5e23184fa999dc44d72de7588cf77fad0503729 100644
--- a/source/RobotAPI/libraries/armem/server/query_proc/workingmemory/ProviderSegmentQueryProcessor.cpp
+++ b/source/RobotAPI/libraries/armem/server/query_proc/workingmemory/ProviderSegmentQueryProcessor.cpp
@@ -1 +1,30 @@
 #include "ProviderSegmentQueryProcessor.h"
+
+#include <RobotAPI/libraries/armem/core/workingmemory/ice_conversions.h>
+
+
+namespace armarx::armem::wm::query_proc
+{
+
+    ProviderSegmentQueryProcessor::ProviderSegmentQueryProcessor(DataMode dataMode) :
+        Base(dataMode), entityProcessor(dataMode)
+    {}
+
+
+    ProviderSegmentQueryProcessor::~ProviderSegmentQueryProcessor() = default;
+
+
+    data::ProviderSegment ProviderSegmentQueryProcessor::processToIce(const armem::query::data::ProviderSegmentQuery& query, const wm::ProviderSegment& providerSegment) const
+    {
+        data::ProviderSegment data;
+        toIce(data, process(query, providerSegment));
+        return data;
+    }
+
+
+    Entity ProviderSegmentQueryProcessor::entityProcessorProcess(const armem::query::data::EntityQuerySeq& q, const Entity& s) const
+    {
+        return entityProcessor.process(q, s, {armem::query::data::QueryTarget::WM});
+    }
+
+}
diff --git a/source/RobotAPI/libraries/armem/server/query_proc/workingmemory/ProviderSegmentQueryProcessor.h b/source/RobotAPI/libraries/armem/server/query_proc/workingmemory/ProviderSegmentQueryProcessor.h
index 468138d9e2bbd526db3632019beca6a5a29f8269..8e4f5a5e85d6c3c7f58433a0c2ddcd50074c7d7e 100644
--- a/source/RobotAPI/libraries/armem/server/query_proc/workingmemory/ProviderSegmentQueryProcessor.h
+++ b/source/RobotAPI/libraries/armem/server/query_proc/workingmemory/ProviderSegmentQueryProcessor.h
@@ -1,10 +1,12 @@
 #pragma once
 
-#include "BaseQueryProcessor.h"
-#include "../base/ProviderSegmentQueryProcessorBase.h"
+#include <RobotAPI/libraries/armem/core/workingmemory/ProviderSegment.h>
+#include <RobotAPI/libraries/armem/server/query_proc/base/ProviderSegmentQueryProcessorBase.h>
 
+#include "BaseQueryProcessor.h"
 #include "EntityQueryProcessor.h"
 
+
 namespace armarx::armem::wm::query_proc
 {
     /**
@@ -17,23 +19,22 @@ namespace armarx::armem::wm::query_proc
         using Base = BaseQueryProcessor<wm::ProviderSegment, armem::query::data::ProviderSegmentQuery>;
 
     public:
-        ProviderSegmentQueryProcessor(DataMode dataMode = DataMode::WithData) :
-            Base(dataMode), entityProcessor(dataMode)
-        {}
+
+        ProviderSegmentQueryProcessor(DataMode dataMode = DataMode::WithData);
+        virtual ~ProviderSegmentQueryProcessor() override;
+
 
         using Base::process;
-        data::ProviderSegment processToIce(const armem::query::data::ProviderSegmentQuery& query, const wm::ProviderSegment& providerSegment) const
-        {
-            return toIce<data::ProviderSegment>(process(query, providerSegment));
-        }
+        data::ProviderSegment processToIce(const armem::query::data::ProviderSegmentQuery& query, const wm::ProviderSegment& providerSegment) const;
+
 
     protected:
-        virtual EntityT entityProcessorProcess(const armem::query::data::EntityQuerySeq& q, const EntityT& s) const override
-        {
-            return entityProcessor.process(q, s, {armem::query::data::QueryTarget::WM});
-        }
+
+        virtual Entity entityProcessorProcess(const armem::query::data::EntityQuerySeq& q, const Entity& s) const override;
 
     private:
+
         EntityQueryProcessor entityProcessor;
+
     };
 }
diff --git a/source/RobotAPI/libraries/armem/server/segment/SpecializedSegment.cpp b/source/RobotAPI/libraries/armem/server/segment/SpecializedSegment.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..8184e27c985877a19aaa873db07883685140b17b
--- /dev/null
+++ b/source/RobotAPI/libraries/armem/server/segment/SpecializedSegment.cpp
@@ -0,0 +1,79 @@
+#include "SpecializedSegment.h"
+
+#include <ArmarXCore/core/application/properties/PropertyDefinitionContainer.h>
+#include <ArmarXCore/core/application/properties/PluginAll.h>
+#include <ArmarXCore/core/exceptions/local/ExpressionException.h>
+
+#include <RobotAPI/libraries/aron/core/navigator/type/container/Object.h>
+#include <RobotAPI/libraries/armem/server/MemoryToIceAdapter.h>
+
+
+namespace armarx::armem::server::segment
+{
+
+    SpecializedSegment::SpecializedSegment(
+            server::MemoryToIceAdapter& iceMemory,
+            aron::typenavigator::ObjectNavigatorPtr aronType,
+            const std::string& defaultCoreSegmentName,
+            int64_t defaultMaxHistorySize
+            ) :
+        iceMemory(iceMemory), aronType(aronType)
+    {
+        setDefaultCoreSegmentName(defaultCoreSegmentName);
+        setDefaultMaxHistorySize(defaultMaxHistorySize);
+    }
+
+
+    SpecializedSegment::~SpecializedSegment()
+    {
+    }
+
+
+    void SpecializedSegment::defineProperties(armarx::PropertyDefinitionsPtr defs, const std::string& prefix)
+    {
+        defs->optional(properties.coreSegmentName,
+                       prefix + "seg.CoreSegmentName",
+                       "Name of the " + properties.coreSegmentName + " core segment.");
+
+        defs->optional(properties.maxHistorySize,
+                       prefix + "seg.MaxHistorySize",
+                       "Maximal size of the " + properties.coreSegmentName + " entity histories (-1 for infinite).");
+    }
+
+
+    void SpecializedSegment::init()
+    {
+        ARMARX_CHECK_NOT_NULL(iceMemory.workingMemory);
+        Logging::setTag(properties.coreSegmentName + " Core Segment");
+
+        ARMARX_INFO << "Adding core segment '" << properties.coreSegmentName << "'";
+        coreSegment = &iceMemory.workingMemory->addCoreSegment(properties.coreSegmentName, aronType);
+        coreSegment->setMaxHistorySize(properties.maxHistorySize);
+    }
+
+
+    std::mutex& SpecializedSegment::mutex() const
+    {
+        ARMARX_CHECK_NOT_NULL(coreSegment);
+        return coreSegment->mutex();
+    }
+
+
+    void SpecializedSegment::setDefaultCoreSegmentName(const std::string& coreSegmentName)
+    {
+        this->properties.coreSegmentName = coreSegmentName;
+    }
+
+
+    void SpecializedSegment::setDefaultMaxHistorySize(int64_t maxHistorySize)
+    {
+        this->properties.maxHistorySize = maxHistorySize;
+    }
+
+
+    void SpecializedSegment::setAronType(aron::typenavigator::ObjectNavigatorPtr aronType)
+    {
+        this->aronType = aronType;
+    }
+
+}
diff --git a/source/RobotAPI/libraries/armem/server/segment/SpecializedSegment.h b/source/RobotAPI/libraries/armem/server/segment/SpecializedSegment.h
new file mode 100644
index 0000000000000000000000000000000000000000..fd3a456c55d785471e86a0d3f1e12a5491d3e32c
--- /dev/null
+++ b/source/RobotAPI/libraries/armem/server/segment/SpecializedSegment.h
@@ -0,0 +1,77 @@
+#pragma once
+
+#include <mutex>
+#include <string>
+
+#include <ArmarXCore/core/application/properties/forward_declarations.h>
+#include <ArmarXCore/core/logging/Logging.h>
+
+
+namespace armarx::aron::typenavigator
+{
+    using ObjectNavigatorPtr = std::shared_ptr<class ObjectNavigator>;
+}
+namespace armarx::armem
+{
+    namespace server
+    {
+        class MemoryToIceAdapter;
+    }
+
+    namespace wm
+    {
+        class CoreSegment;
+    }
+}
+
+namespace armarx::armem::server::segment
+{
+
+    /**
+     * @brief Specialized management of a core segment.
+     */
+    class SpecializedSegment :
+            public armarx::Logging
+    {
+    public:
+
+        SpecializedSegment(
+                server::MemoryToIceAdapter& iceMemory,
+                aron::typenavigator::ObjectNavigatorPtr aronType = nullptr,
+                const std::string& defaultCoreSegmentName = "",
+                int64_t defaultMaxHistorySize = -1);
+
+        virtual ~SpecializedSegment();
+
+
+        virtual void defineProperties(armarx::PropertyDefinitionsPtr defs, const std::string& prefix = "");
+        virtual void init();
+        // void connect();
+
+        std::mutex& mutex() const;
+
+
+    protected:
+
+        void setDefaultCoreSegmentName(const std::string& coreSegmentName);
+        void setDefaultMaxHistorySize(int64_t maxHistorySize);
+        void setAronType(aron::typenavigator::ObjectNavigatorPtr aronType);
+
+
+    protected:
+
+        server::MemoryToIceAdapter& iceMemory;
+        wm::CoreSegment* coreSegment = nullptr;
+        aron::typenavigator::ObjectNavigatorPtr aronType;
+
+        struct Properties
+        {
+            std::string coreSegmentName = "";
+            int64_t maxHistorySize = -1;
+        };
+        Properties properties;
+
+
+    };
+
+}
diff --git a/source/RobotAPI/libraries/armem_objects/CMakeLists.txt b/source/RobotAPI/libraries/armem_objects/CMakeLists.txt
index 54eb919e1804ce099efe5ade4ea14294a202e0bb..ab26b1f8a38b5e18b16dc49a498c9369d6d918db 100644
--- a/source/RobotAPI/libraries/armem_objects/CMakeLists.txt
+++ b/source/RobotAPI/libraries/armem_objects/CMakeLists.txt
@@ -16,6 +16,7 @@ armarx_add_library(
         RobotAPI::Core
         RobotAPI::armem
         RobotAPI::armem_robot
+
     HEADERS
         aron_conversions.h
         aron_forward_declarations.h
@@ -32,11 +33,6 @@ armarx_add_library(
         server/instance/Visu.h
         server/instance/ArticulatedObjectVisu.h
 
-        # server/articulated_object_class/Segment.h
-        # server/articulated_object_instance/Segment.h
-        # server/articulated_object/SegmentAdapter.h
-        # server/articulated_object_instance/Visu.h
-
         server/attachments/Segment.h
 
         client/articulated_object/Reader.h
@@ -64,12 +60,6 @@ armarx_add_library(
         server/instance/Visu.cpp
         server/instance/ArticulatedObjectVisu.cpp
 
-        server/articulated_object_class/Segment.cpp
-
-        # server/articulated_object_instance/Segment.cpp
-        # server/articulated_object/SegmentAdapter.cpp
-        # server/articulated_object_instance/Visu.cpp
-
         server/attachments/Segment.cpp
 
         client/articulated_object/Reader.cpp
diff --git a/source/RobotAPI/libraries/armem_objects/server/articulated_object_class/Segment.cpp b/source/RobotAPI/libraries/armem_objects/server/articulated_object_class/Segment.cpp
deleted file mode 100644
index 425b5af02da13e58f4a654a0784029f5fbe9a9e0..0000000000000000000000000000000000000000
--- a/source/RobotAPI/libraries/armem_objects/server/articulated_object_class/Segment.cpp
+++ /dev/null
@@ -1,185 +0,0 @@
-#include "Segment.h"
-
-#include <SimoxUtility/algorithm/get_map_keys_values.h>
-#include <sstream>
-
-#include <ArmarXCore/core/time/TimeUtil.h>
-#include "ArmarXCore/core/logging/Logging.h"
-
-#include "RobotAPI/libraries/aron/common/aron_conversions.h"
-
-#include <RobotAPI/libraries/armem/core/aron_conversions.h>
-#include <RobotAPI/libraries/armem/core/workingmemory/visitor.h>
-#include "RobotAPI/libraries/armem/core/MemoryID.h"
-#include <RobotAPI/libraries/armem/client/Writer.h>
-#include <RobotAPI/libraries/armem/client/query/Builder.h>
-#include <RobotAPI/libraries/armem/client/query/query_fns.h>
-#include <RobotAPI/libraries/armem/server/MemoryToIceAdapter.h>
-
-#include "RobotAPI/libraries/armem_robot/robot_conversions.h"
-#include <RobotAPI/libraries/armem_robot/aron/Robot.aron.generated.h>
-#include <RobotAPI/libraries/armem_robot/aron_conversions.h>
-
-
-namespace armarx::armem::server::obj::articulated_object_class
-{
-
-    Segment::Segment(armem::server::MemoryToIceAdapter& memoryToIceAdapter, std::mutex& memoryMutex) :
-        iceMemory(memoryToIceAdapter),
-        memoryMutex(memoryMutex)
-    {
-        Logging::setTag("ArticulatedObjectInstanceSegment");
-    }
-
-    Segment::~Segment() = default;
-
-    void Segment::defineProperties(armarx::PropertyDefinitionsPtr defs, const std::string& prefix)
-    {
-        defs->optional(p.coreClassSegmentName, prefix + "CoreSegmentName", "Name of the object instance core segment.");
-        defs->optional(p.maxHistorySize, prefix + "MaxHistorySize", "Maximal size of object poses history (-1 for infinite).");
-
-        defs->optional(p.objectsPackage, prefix + "ObjectsPackage", "Name of the objects package to load from.");
-        defs->optional(p.loadFromObjectsPackage, prefix + "LoadFromObjectsPackage",
-                       "If true, load the objects from the objects package on startup.");
-
-    }
-
-    void Segment::init()
-    {
-        ARMARX_CHECK_NOT_NULL(iceMemory.workingMemory);
-
-        coreSegment = &iceMemory.workingMemory->addCoreSegment(p.coreClassSegmentName, arondto::RobotDescription::toAronType());
-        coreSegment->setMaxHistorySize(p.maxHistorySize);
-
-        if (p.loadFromObjectsPackage)
-        {
-            loadByObjectFinder(p.objectsPackage);
-        }
-    }
-
-    void Segment::connect(viz::Client arviz)
-    {
-        // this->visu = std::make_unique<Visu>(arviz, *this);
-    }
-
-    void Segment::loadByObjectFinder(const std::string& package)
-    {
-        ObjectFinder finder(package);
-
-        const auto knownArticulatedObjectDescriptions = finder.findAllArticulatedObjectsByDataset(true);
-        ARMARX_DEBUG << "Found " << knownArticulatedObjectDescriptions.size() << " articulated objects";
-
-        loadObjectsIntoMemory(knownArticulatedObjectDescriptions, package);
-    }
-
-    void Segment::loadObjectsIntoMemory(const std::unordered_map<std::string, std::vector<armem::articulated_object::ArticulatedObjectDescription>>& datasets, const std::string& package)
-    {
-        const Time now = TimeUtil::GetTime();
-
-        const MemoryID providerID = coreSegment->id().withProviderSegmentName(package);
-        coreSegment->addProviderSegment(providerID.providerSegmentName);
-
-        // ARMARX_INFO << "Loading up to " << infos.size() << " object classes from '"
-        //             << objectFinder.getPackageName() << "' ...";
-        Commit commit;
-
-        for (const auto& [datasetName, descriptions] : datasets)
-        {
-
-            for (const armem::articulated_object::ArticulatedObjectDescription& desc : descriptions)
-            {
-                EntityUpdate& update = commit.updates.emplace_back();
-                update.entityID = providerID.withEntityName(desc.name);
-                update.timeArrived = update.timeCreated = update.timeSent = now;
-
-                arondto::RobotDescription aronRobotDescription;
-                toAron(aronRobotDescription, desc);
-                // TODO toAron(aronRobotDescription.timestamp, now);
-
-                update.instancesData = { aronRobotDescription.toAron()};
-            }
-
-            ARMARX_INFO << "Loaded " << commit.updates.size() << " articulated object classes from '"
-                        << package << "' in dataset '" << datasetName << "'.";
-        }
-        iceMemory.commit(commit);
-    }
-
-
-
-    std::unordered_map<armem::MemoryID, ::armarx::armem::articulated_object::ArticulatedObjectDescription> Segment::getKnownObjectClasses() const
-    {
-        std::unordered_map<armem::MemoryID, ::armarx::armem::articulated_object::ArticulatedObjectDescription> objects;
-
-        for (const auto& [_, provSeg] : iceMemory.workingMemory->getCoreSegment(p.coreClassSegmentName))
-        {
-            for (const auto& [name, entity] :  provSeg.entities())
-            {
-                for (const auto& snapshot : simox::alg::get_values(entity.history()))
-                {
-                    const auto& entityInstance = snapshot.getInstance(0);
-                    const auto description = robot::convertRobotDescription(entityInstance);
-
-                    if (not description)
-                    {
-                        ARMARX_WARNING << "Could not convert entity instance to 'RobotDescription'";
-                        continue;
-                    }
-
-                    ARMARX_DEBUG << "Key is " << armem::MemoryID(snapshot.id());
-
-                    objects.emplace(armem::MemoryID(snapshot.id()), *description);
-                }
-            }
-        }
-
-        ARMARX_INFO << deactivateSpam(10) <<  "Number of known articulated object classes: " << objects.size();
-
-        return objects;
-    }
-
-
-
-    // void Segment::RemoteGui::setup(const Segment& data)
-    // {
-    //     using namespace armarx::RemoteGui::Client;
-
-    //     maxHistorySize.setValue(std::max(1, int(data.p.maxHistorySize)));
-    //     maxHistorySize.setRange(1, 1e6);
-    //     infiniteHistory.setValue(data.p.maxHistorySize == -1);
-    //     discardSnapshotsWhileAttached.setValue(data.p.discardSnapshotsWhileAttached);
-
-    //     GridLayout grid;
-    //     int row = 0;
-    //     grid.add(Label("Max History Size"), {row, 0}).add(maxHistorySize, {row, 1});
-    //     row++;
-    //     grid.add(Label("Infinite History Size"), {row, 0}).add(infiniteHistory, {row, 1});
-    //     row++;
-    //     grid.add(Label("Discard Snapshots while Attached"), {row, 0}).add(discardSnapshotsWhileAttached, {row, 1});
-    //     row++;
-
-    //     group.setLabel("Data");
-    //     group.addChild(grid);
-    // }
-
-    // void Segment::RemoteGui::update(Segment& data)
-    // {
-    //     if (infiniteHistory.hasValueChanged() || maxHistorySize.hasValueChanged()
-    //         || discardSnapshotsWhileAttached.hasValueChanged())
-    //     {
-    //         std::scoped_lock lock(data.memoryMutex);
-
-    //         if (infiniteHistory.hasValueChanged() || maxHistorySize.hasValueChanged())
-    //         {
-    //             data.p.maxHistorySize = infiniteHistory.getValue() ? -1 : maxHistorySize.getValue();
-    //             if (data.coreSegment)
-    //             {
-    //                 data.coreSegment->setMaxHistorySize(long(data.p.maxHistorySize));
-    //             }
-    //         }
-
-    //         data.p.discardSnapshotsWhileAttached = discardSnapshotsWhileAttached.getValue();
-    //     }
-    // }
-
-}  // namespace armarx::armem::server::obj::articulated_object_class
diff --git a/source/RobotAPI/libraries/armem_objects/server/articulated_object_class/Segment.h b/source/RobotAPI/libraries/armem_objects/server/articulated_object_class/Segment.h
deleted file mode 100644
index e2a7bbc6fbf2c875e11fb25427f5a7a8809aee4c..0000000000000000000000000000000000000000
--- a/source/RobotAPI/libraries/armem_objects/server/articulated_object_class/Segment.h
+++ /dev/null
@@ -1,112 +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/>.
- *
- * @author     Fabian Reister ( fabian dot reister at kit dot edu )
- * @date       2021
- * @copyright  http://www.gnu.org/licenses/gpl-2.0.txt
- *             GNU General Public License
- */
-
-#pragma once
-
-#include <string>
-#include <optional>
-#include <mutex>
-#include <unordered_map>
-
-#include <ArmarXCore/core/logging/Logging.h>
-#include "ArmarXCore/core/application/properties/PropertyDefinitionContainer.h"
-
-// #include "ArmarXGui/libraries/RemoteGui/Client/Widgets.h"
-
-#include "RobotAPI/components/ArViz/Client/Client.h"
-
-#include "RobotAPI/libraries/armem/core/MemoryID.h"
-#include "RobotAPI/libraries/armem_objects/types.h"
-
-#include <RobotAPI/libraries/ArmarXObjects/ObjectFinder.h>
-
-namespace armarx::armem
-{
-    namespace server
-    {
-        class MemoryToIceAdapter;
-    }
-
-    namespace wm
-    {
-        class CoreSegment;
-    }
-}  // namespace armarx::armem
-
-
-namespace armarx::armem::server::obj::articulated_object_class
-{
-    class Visu;
-
-    class Segment : public armarx::Logging
-    {
-    public:
-        Segment(server::MemoryToIceAdapter& iceMemory,
-                std::mutex& memoryMutex);
-
-        virtual ~Segment();
-
-        void connect(viz::Client arviz);
-
-        void defineProperties(armarx::PropertyDefinitionsPtr defs, const std::string& prefix = "");
-
-        void init();
-
-        std::unordered_map<armem::MemoryID, ::armarx::armem::articulated_object::ArticulatedObjectDescription> getKnownObjectClasses() const;
-
-
-    private:
-        void loadByObjectFinder(const std::string& package);
-        void loadObjectsIntoMemory(const std::unordered_map<std::string, std::vector<armem::articulated_object::ArticulatedObjectDescription>>& datasets, const std::string& package);
-
-        server::MemoryToIceAdapter& iceMemory;
-        wm::CoreSegment* coreSegment = nullptr;
-        std::mutex& memoryMutex;
-
-        struct Properties
-        {
-            std::string coreClassSegmentName = "ArticulatedObjectClass";
-            int64_t maxHistorySize = -1;
-
-            std::string objectsPackage = ObjectFinder::DefaultObjectsPackageName;
-            bool loadFromObjectsPackage = true;
-        };
-        Properties p;
-
-        // std::unique_ptr<Visu> visu;
-
-    public:
-
-        // struct RemoteGui
-        // {
-        //     armarx::RemoteGui::Client::GroupBox group;
-
-        //     armarx::RemoteGui::Client::IntSpinBox maxHistorySize;
-        //     armarx::RemoteGui::Client::CheckBox infiniteHistory;
-        //     armarx::RemoteGui::Client::CheckBox discardSnapshotsWhileAttached;
-
-        //     void setup(const Segment& data);
-        //     void update(Segment& data);
-        // };
-
-    };
-
-}  // namespace armarx::armem::server::obj::articulated_object_class
diff --git a/source/RobotAPI/libraries/armem_objects/server/articulated_object_instance/Segment.cpp b/source/RobotAPI/libraries/armem_objects/server/articulated_object_instance/Segment.cpp
deleted file mode 100644
index dba8c91a83e3449fd0dc2a4bdb8ef79632a572e0..0000000000000000000000000000000000000000
--- a/source/RobotAPI/libraries/armem_objects/server/articulated_object_instance/Segment.cpp
+++ /dev/null
@@ -1,175 +0,0 @@
-#include "Segment.h"
-
-#include <sstream>
-
-#include <SimoxUtility/algorithm/get_map_keys_values.h>
-
-#include <ArmarXCore/core/time/TimeUtil.h>
-#include <ArmarXCore/core/exceptions/local/ExpressionException.h>
-
-#include <RobotAPI/libraries/core/remoterobot/RemoteRobot.h>
-
-#include <RobotAPI/libraries/aron/common/aron_conversions.h>
-
-#include <RobotAPI/libraries/armem/core/aron_conversions.h>
-#include <RobotAPI/libraries/armem/client/Writer.h>
-#include <RobotAPI/libraries/armem/client/query/Builder.h>
-#include <RobotAPI/libraries/armem/client/query/query_fns.h>
-#include <RobotAPI/libraries/armem/aron/MemoryID.aron.generated.h>
-
-#include <RobotAPI/libraries/armem_robot/aron/Robot.aron.generated.h>
-#include <RobotAPI/libraries/armem_robot/aron/RobotDescription.aron.generated.h>
-#include <RobotAPI/libraries/armem_robot/aron_conversions.h>
-#include <RobotAPI/libraries/armem_robot/robot_conversions.h>
-
-#include <RobotAPI/libraries/armem_objects/server/articulated_object_class/Segment.h>
-
-#include "Visu.h"
-
-
-namespace armarx::armem::server::obj::articulated_object_instance
-{
-
-    Segment::Segment(armem::server::MemoryToIceAdapter& memoryToIceAdapter, std::mutex& memoryMutex) :
-        iceMemory(memoryToIceAdapter),
-        memoryMutex(memoryMutex)
-    {
-        Logging::setTag("ArticulatedObjectInstanceSegment");
-    }
-
-    Segment::~Segment() = default;
-
-    void Segment::defineProperties(armarx::PropertyDefinitionsPtr& defs, const std::string& prefix)
-    {
-        defs->optional(p.coreInstanceSegmentName, prefix + "CoreSegmentName", "Name of the object instance core segment.");
-        defs->optional(p.maxHistorySize, prefix + "MaxHistorySize", "Maximal size of object poses history (-1 for infinite).");
-    }
-
-    void Segment::init()
-    {
-        ARMARX_CHECK_NOT_NULL(iceMemory.workingMemory);
-
-        coreSegment = &iceMemory.workingMemory->addCoreSegment(p.coreInstanceSegmentName, arondto::Robot::toAronType());
-        coreSegment->setMaxHistorySize(p.maxHistorySize);
-
-    }
-
-    void Segment::connect(viz::Client arviz)
-    {
-        this->visu = std::make_unique<Visu>(arviz, *this);
-        visu->init();
-    }
-
-    void Segment::setArticulatedObjectClassSegment(const articulated_object_class::Segment& segment)
-    {
-        classSegment = &segment;
-    }
-
-    ::armarx::armem::articulated_object::ArticulatedObjects Segment::getArticulatedObjects() const
-    {
-        ARMARX_CHECK_NOT_NULL(classSegment);
-        const auto knownObjectClasses = classSegment->getKnownObjectClasses();
-
-        ARMARX_DEBUG << "Class segment has " << knownObjectClasses.size() << " known articulated objects";
-
-        const auto escape = [](std::string & v)
-        {
-            v = simox::alg::replace_all(v, "/", "\\/");
-        };
-
-        const auto resolveDescriptionLink = [&](auto & articulatedObject, const auto & aronDescriptionLink) -> bool
-        {
-            armem::MemoryID descriptionLink;
-            fromAron(aronDescriptionLink, descriptionLink);
-
-            escape(descriptionLink.providerSegmentName);
-
-            ARMARX_DEBUG << "Lookup key is " << descriptionLink;
-
-            // const auto keys = simox::alg::get_keys(knownObjectClasses);
-            // ARMARX_DEBUG << "Known keys " << keys;
-
-            const auto it = knownObjectClasses.find(descriptionLink);
-            if (it == knownObjectClasses.end())
-            {
-                ARMARX_WARNING << "Unknown object class " << descriptionLink
-                               << "Known classes are " << simox::alg::get_keys(knownObjectClasses);
-                return false;
-            }
-
-            articulatedObject.description = it->second;
-            return true;
-        };
-
-        ::armarx::armem::articulated_object::ArticulatedObjects objects;
-        for (const auto& [_, provSeg] : iceMemory.workingMemory->getCoreSegment(p.coreInstanceSegmentName))
-        {
-            for (const auto& [_, entity] :  provSeg.entities())
-            {
-                const auto& entityInstance = entity.getLatestSnapshot().getInstance(0);
-
-                arondto::Robot aronArticulatedObject;
-                aronArticulatedObject.fromAron(entityInstance.data());
-
-                armem::articulated_object::ArticulatedObject articulatedObject;
-                fromAron(aronArticulatedObject, articulatedObject);
-
-                // resolve memory link for description
-                const arondto::MemoryID& aronDescriptionLink = aronArticulatedObject.description;
-                if (not resolveDescriptionLink(articulatedObject, aronDescriptionLink))
-                {
-                    continue;
-                }
-
-                objects.push_back(articulatedObject);
-            }
-        }
-
-        return objects;
-    }
-
-
-
-    // void Segment::RemoteGui::setup(const Segment& data)
-    // {
-    //     using namespace armarx::RemoteGui::Client;
-
-    //     maxHistorySize.setValue(std::max(1, int(data.p.maxHistorySize)));
-    //     maxHistorySize.setRange(1, 1e6);
-    //     infiniteHistory.setValue(data.p.maxHistorySize == -1);
-    //     discardSnapshotsWhileAttached.setValue(data.p.discardSnapshotsWhileAttached);
-
-    //     GridLayout grid;
-    //     int row = 0;
-    //     grid.add(Label("Max History Size"), {row, 0}).add(maxHistorySize, {row, 1});
-    //     row++;
-    //     grid.add(Label("Infinite History Size"), {row, 0}).add(infiniteHistory, {row, 1});
-    //     row++;
-    //     grid.add(Label("Discard Snapshots while Attached"), {row, 0}).add(discardSnapshotsWhileAttached, {row, 1});
-    //     row++;
-
-    //     group.setLabel("Data");
-    //     group.addChild(grid);
-    // }
-
-    // void Segment::RemoteGui::update(Segment& data)
-    // {
-    //     if (infiniteHistory.hasValueChanged() || maxHistorySize.hasValueChanged()
-    //         || discardSnapshotsWhileAttached.hasValueChanged())
-    //     {
-    //         std::scoped_lock lock(data.memoryMutex);
-
-    //         if (infiniteHistory.hasValueChanged() || maxHistorySize.hasValueChanged())
-    //         {
-    //             data.p.maxHistorySize = infiniteHistory.getValue() ? -1 : maxHistorySize.getValue();
-    //             if (data.coreSegment)
-    //             {
-    //                 data.coreSegment->setMaxHistorySize(long(data.p.maxHistorySize));
-    //             }
-    //         }
-
-    //         data.p.discardSnapshotsWhileAttached = discardSnapshotsWhileAttached.getValue();
-    //     }
-    // }
-
-}  // namespace armarx::armem::server::obj::articulated_object_instance
diff --git a/source/RobotAPI/libraries/armem_objects/server/articulated_object_instance/Segment.h b/source/RobotAPI/libraries/armem_objects/server/articulated_object_instance/Segment.h
deleted file mode 100644
index 2d50be817effddb795e8cd6adf1bda992d177e87..0000000000000000000000000000000000000000
--- a/source/RobotAPI/libraries/armem_objects/server/articulated_object_instance/Segment.h
+++ /dev/null
@@ -1,112 +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/>.
- *
- * @author     Fabian Reister ( fabian dot reister at kit dot edu )
- * @date       2021
- * @copyright  http://www.gnu.org/licenses/gpl-2.0.txt
- *             GNU General Public License
- */
-
-#pragma once
-
-#include <cstdint>
-#include <map>
-#include <string>
-#include <optional>
-#include <mutex>
-
-#include "ArmarXCore/core/application/properties/PropertyDefinitionContainer.h"
-
-#include "ArmarXGui/libraries/RemoteGui/Client/Widgets.h"
-
-#include <RobotAPI/interface/core/RobotState.h>
-
-#include <RobotAPI/libraries/armem/core/workingmemory/Memory.h>
-#include <RobotAPI/libraries/armem/server/MemoryToIceAdapter.h>
-
-#include "RobotAPI/components/ArViz/Client/Client.h"
-
-#include "RobotAPI/libraries/armem_objects/types.h"
-
-
-namespace armarx::armem::server::obj::articulated_object_class
-{
-    class Segment;
-}
-
-namespace armarx::armem::server::obj::articulated_object_instance
-{
-    class Visu;
-
-    class Segment : public armarx::Logging
-    {
-    public:
-
-        struct CommitStats
-        {
-            int numUpdated = 0;
-        };
-
-
-        Segment(server::MemoryToIceAdapter& iceMemory,
-                std::mutex& memoryMutex);
-
-        virtual ~Segment();
-
-        void connect(viz::Client arviz);
-
-        void defineProperties(armarx::PropertyDefinitionsPtr& defs, const std::string& prefix = "");
-
-        void init();
-
-        void setArticulatedObjectClassSegment(const articulated_object_class::Segment& segment);
-
-        ::armarx::armem::articulated_object::ArticulatedObjects getArticulatedObjects() const;
-
-    private:
-
-        server::MemoryToIceAdapter& iceMemory;
-        wm::CoreSegment* coreSegment = nullptr;
-        std::mutex& memoryMutex;
-
-        articulated_object_class::Segment const*  classSegment;
-
-
-        struct Properties
-        {
-            std::string coreInstanceSegmentName = "ArticulatedObjectInstance";
-            int64_t maxHistorySize = -1;
-        };
-        Properties p;
-
-        std::unique_ptr<Visu> visu;
-
-    public:
-
-        // struct RemoteGui
-        // {
-        //     armarx::RemoteGui::Client::GroupBox group;
-
-        //     armarx::RemoteGui::Client::IntSpinBox maxHistorySize;
-        //     armarx::RemoteGui::Client::CheckBox infiniteHistory;
-        //     armarx::RemoteGui::Client::CheckBox discardSnapshotsWhileAttached;
-
-        //     void setup(const Segment& data);
-        //     void update(Segment& data);
-        // };
-
-    };
-
-}  // namespace armarx::armem::server::obj::articulated_object_instance
diff --git a/source/RobotAPI/libraries/armem_objects/server/attachments/Segment.cpp b/source/RobotAPI/libraries/armem_objects/server/attachments/Segment.cpp
index f2490c841d0042a133fb1c8cf58740eb2af614cd..bb5d930da65b6ddb0e7966aa53e5e8fa766d383d 100644
--- a/source/RobotAPI/libraries/armem_objects/server/attachments/Segment.cpp
+++ b/source/RobotAPI/libraries/armem_objects/server/attachments/Segment.cpp
@@ -4,6 +4,7 @@
 
 #include <ArmarXCore/core/time/TimeUtil.h>
 #include "ArmarXCore/core/logging/Logging.h"
+#include <ArmarXCore/core/application/properties/forward_declarations.h>
 
 #include "RobotAPI/libraries/armem/util/util.h"
 #include "RobotAPI/libraries/aron/common/aron_conversions.h"
@@ -23,9 +24,8 @@
 
 namespace armarx::armem::server::obj::attachments
 {
-    Segment::Segment(armem::server::MemoryToIceAdapter& memoryToIceAdapter, std::mutex& memoryMutex) :
-        iceMemory(memoryToIceAdapter),
-        memoryMutex(memoryMutex)
+    Segment::Segment(armem::server::MemoryToIceAdapter& memoryToIceAdapter) :
+        iceMemory(memoryToIceAdapter)
     {
         Logging::setTag("Attachments");
     }
@@ -34,7 +34,7 @@ namespace armarx::armem::server::obj::attachments
 
     void Segment::defineProperties(armarx::PropertyDefinitionsPtr defs, const std::string& prefix)
     {
-        defs->optional(p.coreClassSegmentName, prefix + "CoreSegmentName", "Name of the object instance core segment.");
+        defs->optional(p.coreSegmentName, prefix + "CoreSegmentName", "Name of the object instance core segment.");
         defs->optional(p.maxHistorySize, prefix + "MaxHistorySize", "Maximal size of object poses history (-1 for infinite).");
     }
 
@@ -42,20 +42,22 @@ namespace armarx::armem::server::obj::attachments
     {
         ARMARX_CHECK_NOT_NULL(iceMemory.workingMemory);
 
-        coreSegment = &iceMemory.workingMemory->addCoreSegment(p.coreClassSegmentName, arondto::Robot::toAronType());
+        coreSegment = &iceMemory.workingMemory->addCoreSegment(p.coreSegmentName, arondto::Robot::toAronType());
         coreSegment->setMaxHistorySize(p.maxHistorySize);
     }
 
-    void Segment::connect(viz::Client arviz)
+    void Segment::connect()
     {
-        // this->visu = std::make_unique<Visu>(arviz, *this);
     }
 
     std::vector<armarx::armem::attachment::ObjectAttachment> Segment::getAttachments(const armem::Time& timestamp) const
     {
+        ARMARX_CHECK_NOT_NULL(coreSegment);
+        std::scoped_lock(coreSegment->mutex());
+
         std::vector<armarx::armem::attachment::ObjectAttachment> attachments;
 
-        for (const auto& [_, provSeg] : iceMemory.workingMemory->getCoreSegment(p.coreClassSegmentName))
+        for (const auto& [_, provSeg] : *coreSegment)
         {
             for (const auto& [name, entity] :  provSeg.entities())
             {
@@ -80,47 +82,4 @@ namespace armarx::armem::server::obj::attachments
         return attachments;
     }
 
-
-    // void Segment::RemoteGui::setup(const Segment& data)
-    // {
-    //     using namespace armarx::RemoteGui::Client;
-
-    //     maxHistorySize.setValue(std::max(1, int(data.p.maxHistorySize)));
-    //     maxHistorySize.setRange(1, 1e6);
-    //     infiniteHistory.setValue(data.p.maxHistorySize == -1);
-    //     discardSnapshotsWhileAttached.setValue(data.p.discardSnapshotsWhileAttached);
-
-    //     GridLayout grid;
-    //     int row = 0;
-    //     grid.add(Label("Max History Size"), {row, 0}).add(maxHistorySize, {row, 1});
-    //     row++;
-    //     grid.add(Label("Infinite History Size"), {row, 0}).add(infiniteHistory, {row, 1});
-    //     row++;
-    //     grid.add(Label("Discard Snapshots while Attached"), {row, 0}).add(discardSnapshotsWhileAttached, {row, 1});
-    //     row++;
-
-    //     group.setLabel("Data");
-    //     group.addChild(grid);
-    // }
-
-    // void Segment::RemoteGui::update(Segment& data)
-    // {
-    //     if (infiniteHistory.hasValueChanged() || maxHistorySize.hasValueChanged()
-    //         || discardSnapshotsWhileAttached.hasValueChanged())
-    //     {
-    //         std::scoped_lock lock(data.memoryMutex);
-
-    //         if (infiniteHistory.hasValueChanged() || maxHistorySize.hasValueChanged())
-    //         {
-    //             data.p.maxHistorySize = infiniteHistory.getValue() ? -1 : maxHistorySize.getValue();
-    //             if (data.coreSegment)
-    //             {
-    //                 data.coreSegment->setMaxHistorySize(long(data.p.maxHistorySize));
-    //             }
-    //         }
-
-    //         data.p.discardSnapshotsWhileAttached = discardSnapshotsWhileAttached.getValue();
-    //     }
-    // }
-
 }  // namespace armarx::armem::server::obj::attachments
diff --git a/source/RobotAPI/libraries/armem_objects/server/attachments/Segment.h b/source/RobotAPI/libraries/armem_objects/server/attachments/Segment.h
index 3817bc22a51227422848ebbe1e4296aa570fee24..0b9302d93390c473b87c67066bfe173237f3774b 100644
--- a/source/RobotAPI/libraries/armem_objects/server/attachments/Segment.h
+++ b/source/RobotAPI/libraries/armem_objects/server/attachments/Segment.h
@@ -27,7 +27,7 @@
 #include <unordered_map>
 
 #include <ArmarXCore/core/logging/Logging.h>
-#include "ArmarXCore/core/application/properties/PropertyDefinitionContainer.h"
+#include <ArmarXCore/core/application/properties/forward_declarations.h>
 
 // #include "ArmarXGui/libraries/RemoteGui/Client/Widgets.h"
 
@@ -37,6 +37,7 @@
 #include "RobotAPI/libraries/armem/core/Time.h"
 #include "RobotAPI/libraries/armem_objects/types.h"
 
+
 namespace armarx::armem
 {
     namespace server
@@ -59,16 +60,14 @@ namespace armarx::armem::server::obj::attachments
     class Segment : public armarx::Logging
     {
     public:
-        Segment(server::MemoryToIceAdapter& iceMemory,
-                std::mutex& memoryMutex);
 
+        Segment(server::MemoryToIceAdapter& iceMemory);
         virtual ~Segment();
 
-        void connect(viz::Client arviz);
-
         void defineProperties(armarx::PropertyDefinitionsPtr defs, const std::string& prefix = "");
 
         void init();
+        void connect();
 
         std::vector<armarx::armem::attachment::ObjectAttachment> getAttachments(const armem::Time& timestamp) const;
 
@@ -77,31 +76,14 @@ namespace armarx::armem::server::obj::attachments
 
         server::MemoryToIceAdapter& iceMemory;
         wm::CoreSegment* coreSegment = nullptr;
-        std::mutex& memoryMutex;
 
         struct Properties
         {
-            std::string coreClassSegmentName = "Attachments";
+            std::string coreSegmentName = "Attachments";
             int64_t maxHistorySize = -1;
         };
         Properties p;
 
-        // std::unique_ptr<Visu> visu;
-
-    public:
-
-        // struct RemoteGui
-        // {
-        //     armarx::RemoteGui::Client::GroupBox group;
-
-        //     armarx::RemoteGui::Client::IntSpinBox maxHistorySize;
-        //     armarx::RemoteGui::Client::CheckBox infiniteHistory;
-        //     armarx::RemoteGui::Client::CheckBox discardSnapshotsWhileAttached;
-
-        //     void setup(const Segment& data);
-        //     void update(Segment& data);
-        // };
-
     };
 
 }  // namespace armarx::armem::server::obj::attachments
diff --git a/source/RobotAPI/libraries/armem_objects/server/class/Segment.cpp b/source/RobotAPI/libraries/armem_objects/server/class/Segment.cpp
index 3e6ecfed37e3d75d60b3d509f97520c7627f0fcc..22608257c1abcf39340643870b704c2dadfcd54d 100644
--- a/source/RobotAPI/libraries/armem_objects/server/class/Segment.cpp
+++ b/source/RobotAPI/libraries/armem_objects/server/class/Segment.cpp
@@ -3,9 +3,11 @@
 #include <RobotAPI/libraries/aron/core/Exception.h>
 #include <RobotAPI/libraries/aron/common/aron_conversions.h>
 #include <RobotAPI/libraries/ArmarXObjects/aron_conversions.h>
+#include <RobotAPI/libraries/armem/server/MemoryToIceAdapter.h>
 #include <RobotAPI/libraries/armem_objects/aron_conversions.h>
+#include <RobotAPI/libraries/armem_objects/aron/ObjectClass.aron.generated.h>
 
-#include <ArmarXCore/core/Component.h>
+#include <ArmarXCore/core/application/properties/PropertyDefinitionContainer.h>
 #include <ArmarXCore/core/time/TimeUtil.h>
 
 #include <SimoxUtility/color/Color.h>
@@ -19,17 +21,21 @@
 namespace armarx::armem::server::obj::clazz
 {
 
-    Segment::Segment(armem::server::MemoryToIceAdapter& memoryToIceAdapter, std::mutex& memoryMutex) :
-        iceMemory(memoryToIceAdapter),
-        memoryMutex(memoryMutex)
+    Segment::Segment(armem::server::MemoryToIceAdapter& memoryToIceAdapter) :
+        SpecializedSegment(memoryToIceAdapter,
+                           arondto::ObjectClass::toAronType(), "Class", -1)
     {
-        Logging::setTag("ClassSegment");
     }
 
+
+    Segment::~Segment()
+    {
+    }
+
+
     void Segment::defineProperties(armarx::PropertyDefinitionsPtr defs, const std::string& prefix)
     {
-        defs->optional(p.coreSegmentName, prefix + "CoreSegmentName", "Name of the object clazz core segment.");
-        defs->optional(p.maxHistorySize, prefix + "MaxHistorySize", "Maximal size of object poses history (-1 for infinite).");
+        SpecializedSegment::defineProperties(defs, prefix);
 
         defs->optional(p.objectsPackage, prefix + "ObjectsPackage", "Name of the objects package to load from.");
         defs->optional(p.loadFromObjectsPackage, prefix + "LoadFromObjectsPackage",
@@ -38,12 +44,10 @@ namespace armarx::armem::server::obj::clazz
         floorVis.defineProperties(defs, prefix + "Floor.");
     }
 
+
     void Segment::init()
     {
-        ARMARX_CHECK_NOT_NULL(iceMemory.workingMemory);
-
-        coreSegment = &iceMemory.workingMemory->addCoreSegment(p.coreSegmentName, arondto::ObjectClass::toAronType());
-        coreSegment->setMaxHistorySize(p.maxHistorySize);
+        SpecializedSegment::init();
 
         if (p.loadFromObjectsPackage)
         {
@@ -51,6 +55,7 @@ namespace armarx::armem::server::obj::clazz
         }
     }
 
+
     void Segment::connect(viz::Client arviz)
     {
         this->arviz = arviz;
@@ -65,12 +70,14 @@ namespace armarx::armem::server::obj::clazz
         loadByObjectFinder(ObjectFinder(objectsPackage));
     }
 
+
     void Segment::loadByObjectFinder(const ObjectFinder& finder)
     {
         this->objectFinder = finder;
         loadByObjectFinder();
     }
 
+
     void Segment::loadByObjectFinder()
     {
         const Time now = TimeUtil::GetTime();
@@ -79,11 +86,6 @@ namespace armarx::armem::server::obj::clazz
         std::vector<ObjectInfo> infos = objectFinder.findAllObjects(checkPaths);
 
         const MemoryID providerID = coreSegment->id().withProviderSegmentName(objectFinder.getPackageName());
-        if (not coreSegment->hasProviderSegment(providerID.providerSegmentName))
-        {
-            coreSegment->addProviderSegment(providerID.providerSegmentName);
-        }
-
         ARMARX_INFO << "Loading up to " << infos.size() << " object classes from '"
                     << objectFinder.getPackageName() << "' ...";
         Commit commit;
@@ -91,7 +93,7 @@ namespace armarx::armem::server::obj::clazz
         {
             info.setLogError(false);
 
-            EntityUpdate& update = commit.updates.emplace_back();
+            EntityUpdate& update = commit.add();
             update.entityID = providerID.withEntityName(info.id().str());
             update.timeArrived = update.timeCreated = update.timeSent = now;
 
@@ -103,9 +105,10 @@ namespace armarx::armem::server::obj::clazz
         }
         ARMARX_INFO << "Loaded " << commit.updates.size() << " object classes from '"
                     << objectFinder.getPackageName() << "'.";
-        iceMemory.commit(commit);
+        iceMemory.commitLocking(commit);
     }
 
+
     void Segment::visualizeClass(const MemoryID& entityID, bool showAABB, bool showOOBB)
     {
         const Eigen::Matrix4f pose = Eigen::Matrix4f::Identity();
@@ -121,31 +124,32 @@ namespace armarx::armem::server::obj::clazz
         {
             try
             {
-                const armem::wm::Entity& entity = coreSegment->getEntity(entityID);
-                const armem::wm::EntityInstance& instance = entity.getLatestSnapshot().getInstance(0);
-
-                arondto::ObjectClass aron;
-                aron.fromAron(instance.data());
+                std::optional<arondto::ObjectClass> aron =
+                    coreSegment->getLatestEntityInstanceDataLockingAs<arondto::ObjectClass>(entityID, 0);
+                if (not aron.has_value())
+                {
+                    return;
+                }
 
-                if (!aron.simoxXmlPath.package.empty())
+                if (not aron->simoxXmlPath.package.empty())
                 {
                     layerObject.add(viz::Object(entityID.str())
-                                    .file(aron.simoxXmlPath.package, aron.simoxXmlPath.path)
+                                    .file(aron->simoxXmlPath.package, aron->simoxXmlPath.path)
                                     .pose(pose));
                 }
 
                 if (showAABB)
                 {
                     layerAABB.add(viz::Box("AABB")
-                                  .pose(pose * simox::math::pose(aron.aabb.center))
-                                  .size(aron.aabb.extents)
+                                  .pose(pose * simox::math::pose(aron->aabb.center))
+                                  .size(aron->aabb.extents)
                                   .color(simox::Color::cyan(255, 64)));
                 }
                 if (showOOBB)
                 {
                     layerOOBB.add(viz::Box("OOBB")
-                                  .pose(pose * simox::math::pose(aron.oobb.center, aron.oobb.orientation))
-                                  .size(aron.oobb.extents)
+                                  .pose(pose * simox::math::pose(aron->oobb.center, aron->oobb.orientation))
+                                  .size(aron->oobb.extents)
                                   .color(simox::Color::lime(255, 64)));
                 }
             }
@@ -164,17 +168,16 @@ namespace armarx::armem::server::obj::clazz
         arviz.commit(layerObject, layerOrigin, layerAABB, layerOOBB);
     }
 
+
     arondto::ObjectClass Segment::objectClassFromInfo(const ObjectInfo& info)
     {
         namespace fs = std::filesystem;
 
         arondto::ObjectClass data;
-
         toAron(data.id, info.id());
 
-        auto setPathIfExists = [](
-                armarx::arondto::PackagePath & aron,
-                const PackageFileLocation & location)
+        auto setPathIfExists = [](armarx::arondto::PackagePath & aron,
+                                  const PackageFileLocation & location)
         {
             if (fs::is_regular_file(location.absolutePath))
             {
@@ -223,21 +226,23 @@ namespace armarx::armem::server::obj::clazz
         group.addChildren({layout, VSpacer()});
     }
 
+
     void Segment::RemoteGui::update(Segment& segment)
     {
         data.update(segment);
         visu.update(segment);
     }
 
+
     void Segment::RemoteGui::Data::setup(const Segment& segment)
     {
         using namespace armarx::RemoteGui::Client;
 
         reloadButton.setLabel("Reload");
 
-        maxHistorySize.setValue(std::max(1, int(segment.p.maxHistorySize)));
+        maxHistorySize.setValue(std::max(1, int(segment.properties.maxHistorySize)));
         maxHistorySize.setRange(1, 1e6);
-        infiniteHistory.setValue(segment.p.maxHistorySize == -1);
+        infiniteHistory.setValue(segment.properties.maxHistorySize == -1);
 
         GridLayout grid;
         int row = 0;
@@ -253,27 +258,27 @@ namespace armarx::armem::server::obj::clazz
         group.addChild(grid);
     }
 
+
     void Segment::RemoteGui::Data::update(Segment& segment)
     {
         if (reloadButton.wasClicked())
         {
-            std::scoped_lock lock(segment.memoryMutex);
+            // Core segment mutex will be locked on commit.
             segment.loadByObjectFinder();
             rebuild = true;
         }
         if (infiniteHistory.hasValueChanged() || maxHistorySize.hasValueChanged())
         {
-            std::scoped_lock lock(segment.memoryMutex);
-            segment.p.maxHistorySize = infiniteHistory.getValue() ? -1 : maxHistorySize.getValue();
+            std::scoped_lock lock(segment.mutex());
+            segment.properties.maxHistorySize = infiniteHistory.getValue() ? -1 : maxHistorySize.getValue();
             if (segment.coreSegment)
             {
-                segment.coreSegment->setMaxHistorySize(long(segment.p.maxHistorySize));
+                segment.coreSegment->setMaxHistorySize(long(segment.properties.maxHistorySize));
             }
         }
     }
 
 
-
     void Segment::RemoteGui::Visu::setup(const Segment& segment)
     {
         using namespace armarx::RemoteGui::Client;
@@ -308,6 +313,7 @@ namespace armarx::armem::server::obj::clazz
         group.addChild(grid);
     }
 
+
     void Segment::RemoteGui::Visu::update(Segment& segment)
     {
         if (showButton.wasClicked())
@@ -315,7 +321,6 @@ namespace armarx::armem::server::obj::clazz
             const size_t index = static_cast<size_t>(showComboBox.getIndex());
             if (/*index >= 0 &&*/ index < showOptionsIndex.size())
             {
-                std::scoped_lock lock(segment.memoryMutex);
                 segment.visualizeClass(showOptionsIndex.at(index));
             }
         }
diff --git a/source/RobotAPI/libraries/armem_objects/server/class/Segment.h b/source/RobotAPI/libraries/armem_objects/server/class/Segment.h
index 88eaedbefb6529b873dfe6033e6a2857672c0586..15c7c4f373f20c43c0febfb142675c5058c45909 100644
--- a/source/RobotAPI/libraries/armem_objects/server/class/Segment.h
+++ b/source/RobotAPI/libraries/armem_objects/server/class/Segment.h
@@ -3,9 +3,6 @@
 #include <mutex>
 #include <string>
 
-#include <ArmarXCore/core/logging/Logging.h>
-#include <ArmarXCore/core/application/properties/PropertyDefinitionContainer.h>
-
 #include <ArmarXGui/libraries/RemoteGui/Client/Widgets.h>
 
 #include <RobotAPI/components/ArViz/Client/Client.h>
@@ -13,26 +10,30 @@
 #include <RobotAPI/libraries/ArmarXObjects/ObjectFinder.h>
 
 #include <RobotAPI/libraries/armem/core/workingmemory/Memory.h>
-#include <RobotAPI/libraries/armem/server/MemoryToIceAdapter.h>
-#include <RobotAPI/libraries/armem_objects/aron/ObjectClass.aron.generated.h>
+#include <RobotAPI/libraries/armem/server/segment/SpecializedSegment.h>
 #include <RobotAPI/libraries/armem_objects/server/class/FloorVis.h>
 
 
+namespace armarx::armem::arondto
+{
+    class ObjectClass;
+}
 namespace armarx::armem::server::obj::clazz
 {
 
-    class Segment : public armarx::Logging
+    class Segment : public segment::SpecializedSegment
     {
     public:
 
-        Segment(armem::server::MemoryToIceAdapter& iceMemory,
-                std::mutex& memoryMutex);
+        Segment(armem::server::MemoryToIceAdapter& iceMemory);
+        virtual ~Segment() override;
 
 
-        void defineProperties(armarx::PropertyDefinitionsPtr defs, const std::string& prefix = "");
-        void init();
+        void defineProperties(armarx::PropertyDefinitionsPtr defs, const std::string& prefix = "") override;
+        void init() override;
         void connect(viz::Client arviz);
 
+
         void loadByObjectFinder(const std::string& objectsPackage);
         void loadByObjectFinder(const ObjectFinder& finder);
         void loadByObjectFinder();
@@ -45,10 +46,6 @@ namespace armarx::armem::server::obj::clazz
 
     private:
 
-        armem::server::MemoryToIceAdapter& iceMemory;
-        armem::wm::CoreSegment* coreSegment = nullptr;
-        std::mutex& memoryMutex;
-
         ObjectFinder objectFinder;
 
         viz::Client arviz;
@@ -57,9 +54,6 @@ namespace armarx::armem::server::obj::clazz
 
         struct Properties
         {
-            std::string coreSegmentName = "Class";
-            long maxHistorySize = -1;
-
             std::string objectsPackage = ObjectFinder::DefaultObjectsPackageName;
             bool loadFromObjectsPackage = true;
         };
diff --git a/source/RobotAPI/libraries/armem_objects/server/instance/Segment.cpp b/source/RobotAPI/libraries/armem_objects/server/instance/Segment.cpp
index db706075c9bd5431fefd2b04b7634cf5e8ff6747..09a412f4bfa40a1a6288e86dfe65fa8b50953061 100644
--- a/source/RobotAPI/libraries/armem_objects/server/instance/Segment.cpp
+++ b/source/RobotAPI/libraries/armem_objects/server/instance/Segment.cpp
@@ -1,6 +1,7 @@
 #include "Segment.h"
 
 #include <RobotAPI/libraries/armem_objects/aron/ObjectClass.aron.generated.h>
+#include <RobotAPI/libraries/armem_objects/aron/ObjectInstance.aron.generated.h>
 #include <RobotAPI/libraries/armem_objects/aron_conversions.h>
 #include <RobotAPI/libraries/armem_objects/SceneSnapshot.h>
 
@@ -10,6 +11,7 @@
 #include <RobotAPI/libraries/armem/client/Writer.h>
 #include <RobotAPI/libraries/armem/client/query/Builder.h>
 #include <RobotAPI/libraries/armem/client/query/query_fns.h>
+#include <RobotAPI/libraries/armem/server/MemoryToIceAdapter.h>
 #include <RobotAPI/libraries/armem/util/util.h>
 
 #include <RobotAPI/libraries/aron/common/aron_conversions.h>
@@ -42,12 +44,10 @@
 namespace armarx::armem::server::obj::instance
 {
 
-    Segment::Segment(armem::server::MemoryToIceAdapter& memoryToIceAdapter, std::mutex& memoryMutex) :
-        iceMemory(memoryToIceAdapter),
-        memoryMutex(memoryMutex)
+    Segment::Segment(armem::server::MemoryToIceAdapter& memoryToIceAdapter) :
+        SpecializedSegment(memoryToIceAdapter,
+                           arondto::ObjectInstance::toAronType(), "Instance", 64)
     {
-        Logging::setTag("InstanceSegment");
-
         oobbCache.setFetchFn([this](const ObjectID & id) -> std::optional<simox::OrientedBoxf>
         {
             // Try to get OOBB from repository.
@@ -79,10 +79,15 @@ namespace armarx::armem::server::obj::instance
     }
 
 
+    Segment::~Segment()
+    {
+    }
+
+
     void Segment::defineProperties(armarx::PropertyDefinitionsPtr defs, const std::string& prefix)
     {
-        defs->optional(p.coreSegmentName, prefix + "CoreSegmentName", "Name of the object instance core segment.");
-        defs->optional(p.maxHistorySize, prefix + "MaxHistorySize", "Maximal size of object poses history (-1 for infinite).");
+        SpecializedSegment::defineProperties(defs, prefix);
+
         defs->optional(p.discardSnapshotsWhileAttached, prefix + "DiscardSnapshotsWhileAttached",
                        "If true, no new snapshots are stored while an object is attached to a robot node.\n"
                        "If false, new snapshots are stored, but the attachment is kept in the new snapshots.");
@@ -102,11 +107,7 @@ namespace armarx::armem::server::obj::instance
 
     void Segment::init()
     {
-        ARMARX_CHECK_NOT_NULL(iceMemory.workingMemory);
-
-        coreSegment = &iceMemory.workingMemory->addCoreSegment(p.coreSegmentName, arondto::ObjectInstance::toAronType());
-        coreSegment->setMaxHistorySize(p.maxHistorySize);
-
+        SpecializedSegment::init();
 
         if (not p.sceneSnapshotToLoad.empty())
         {
@@ -115,14 +116,17 @@ namespace armarx::armem::server::obj::instance
         }
     }
 
+
     void Segment::connect(viz::Client arviz)
     {
+        (void) arviz;
         // ARMARX_INFO << "ArticulatedObjectVisu";
         // this->visu = std::make_unique<ArticulatedObjectVisu>(arviz, *this);
         // visu->init();
     }
 
 
+
     Segment::CommitStats Segment::commitObjectPoses(
         const std::string& providerName,
         const objpose::data::ProvidedObjectPoseSeq& providedPoses,
@@ -135,7 +139,7 @@ namespace armarx::armem::server::obj::instance
         stats.numUpdated = 0;
         for (const objpose::data::ProvidedObjectPose& provided : providedPoses)
         {
-            const IceUtil::Time timestamp = IceUtil::Time::microSeconds(provided.timestampMicroSeconds);
+            const Time timestamp = Time::microSeconds(provided.timestampMicroSeconds);
 
             // Check whether we have an old snapshot for this object.
             std::optional<objpose::ObjectPose> previousPose;
@@ -208,9 +212,9 @@ namespace armarx::armem::server::obj::instance
 
     void Segment::commitObjectPoses(const ObjectPoseSeq& objectPoses, const std::string& providerName)
     {
-        ARMARX_CHECK_NOT_NULL(coreSegment);
         Time now = TimeUtil::GetTime();
 
+        ARMARX_CHECK_NOT_NULL(coreSegment);
         const MemoryID coreSegmentID = coreSegment->id();
 
         Commit commit;
@@ -241,6 +245,7 @@ namespace armarx::armem::server::obj::instance
             update.instancesData.push_back(dto.toAron());
 
         }
+        // Commit non-locking.
         iceMemory.commit(commit);
     }
 
@@ -668,7 +673,6 @@ namespace armarx::armem::server::obj::instance
                     // Store non-attached pose in new snapshot.
                     storeDetachedSnapshot(*entity, data, now, input.commitAttachedPose);
                 }
-
                 if (providerName.empty())
                 {
                     providerName = data.pose.providerName;
@@ -973,7 +977,6 @@ namespace armarx::armem::server::obj::instance
 
                 if (lockMemory)
                 {
-                    std::scoped_lock lock(memoryMutex);
                     commitSceneSnapshot(snapshot.value(), filename.string());
                 }
                 else
@@ -989,9 +992,9 @@ namespace armarx::armem::server::obj::instance
     {
         using namespace armarx::RemoteGui::Client;
 
-        maxHistorySize.setValue(std::max(1, int(data.p.maxHistorySize)));
+        maxHistorySize.setValue(std::max(1, int(data.properties.maxHistorySize)));
         maxHistorySize.setRange(1, 1e6);
-        infiniteHistory.setValue(data.p.maxHistorySize == -1);
+        infiniteHistory.setValue(data.properties.maxHistorySize == -1);
         discardSnapshotsWhileAttached.setValue(data.p.discardSnapshotsWhileAttached);
 
         storeLoadLine.setValue("Scene_" + timestampPlaceholder);
@@ -1026,39 +1029,39 @@ namespace armarx::armem::server::obj::instance
     }
 
 
-    void Segment::RemoteGui::update(Segment& data)
+    void Segment::RemoteGui::update(Segment& segment)
     {
         if (loadButton.wasClicked())
         {
             bool lockMemory = true;
-            data.commitSceneSnapshotFromFilename(storeLoadLine.getValue(), lockMemory);
+            segment.commitSceneSnapshotFromFilename(storeLoadLine.getValue(), lockMemory);
         }
 
         if (storeButton.wasClicked())
         {
             armem::obj::SceneSnapshot scene;
             {
-                std::scoped_lock lock(data.memoryMutex);
-                scene = data.getSceneSnapshot();
+                std::scoped_lock lock(segment.mutex());
+                scene = segment.getSceneSnapshot();
             }
-            data.storeScene(storeLoadLine.getValue(), scene);
+            segment.storeScene(storeLoadLine.getValue(), scene);
         }
 
         if (infiniteHistory.hasValueChanged() || maxHistorySize.hasValueChanged()
             || discardSnapshotsWhileAttached.hasValueChanged())
         {
-            std::scoped_lock lock(data.memoryMutex);
+            std::scoped_lock lock(segment.mutex());
 
             if (infiniteHistory.hasValueChanged() || maxHistorySize.hasValueChanged())
             {
-                data.p.maxHistorySize = infiniteHistory.getValue() ? -1 : maxHistorySize.getValue();
-                if (data.coreSegment)
+                segment.properties.maxHistorySize = infiniteHistory.getValue() ? -1 : maxHistorySize.getValue();
+                if (segment.coreSegment)
                 {
-                    data.coreSegment->setMaxHistorySize(long(data.p.maxHistorySize));
+                    segment.coreSegment->setMaxHistorySize(long(segment.properties.maxHistorySize));
                 }
             }
 
-            data.p.discardSnapshotsWhileAttached = discardSnapshotsWhileAttached.getValue();
+            segment.p.discardSnapshotsWhileAttached = discardSnapshotsWhileAttached.getValue();
         }
     }
 
diff --git a/source/RobotAPI/libraries/armem_objects/server/instance/Segment.h b/source/RobotAPI/libraries/armem_objects/server/instance/Segment.h
index 3ec6a2f22f41569945cc0c0ed3f5fd0a4021241e..918a4efade3c596763d90fec427b18fa78a774bf 100644
--- a/source/RobotAPI/libraries/armem_objects/server/instance/Segment.h
+++ b/source/RobotAPI/libraries/armem_objects/server/instance/Segment.h
@@ -10,32 +10,35 @@
 
 #include <ArmarXCore/core/logging/Logging.h>
 
-#include "RobotAPI/components/ArViz/Client/Client.h"
 #include <RobotAPI/interface/core/RobotState.h>
 #include <RobotAPI/interface/objectpose/ObjectPoseStorageInterface.h>
 
+#include <RobotAPI/components/ArViz/Client/Client.h>
+
 #include <RobotAPI/libraries/ArmarXObjects/ObjectID.h>
 #include <RobotAPI/libraries/ArmarXObjects/ObjectPose.h>
 #include <RobotAPI/libraries/ArmarXObjects/ObjectFinder.h>
 
 #include <RobotAPI/libraries/armem/core/workingmemory/Memory.h>
-#include <RobotAPI/libraries/armem/server/MemoryToIceAdapter.h>
-#include <RobotAPI/libraries/armem_objects/aron/ObjectInstance.aron.generated.h>
-
-#include "Decay.h"
+#include <RobotAPI/libraries/armem/server/segment/SpecializedSegment.h>
 
 #include "ArticulatedObjectVisu.h"
+#include "Decay.h"
 
 
 namespace armarx::armem::obj
 {
     struct SceneSnapshot;
 }
+namespace armarx::armem::arondto
+{
+    class ObjectInstance;
+}
 
 namespace armarx::armem::server::obj::instance
 {
 
-    class Segment : public armarx::Logging
+    class Segment : public segment::SpecializedSegment
     {
     public:
 
@@ -50,14 +53,12 @@ namespace armarx::armem::server::obj::instance
 
     public:
 
-        Segment(server::MemoryToIceAdapter& iceMemory,
-                std::mutex& memoryMutex);
-
+        Segment(server::MemoryToIceAdapter& iceMemory);
+        virtual ~Segment() override;
 
-        void defineProperties(armarx::PropertyDefinitionsPtr defs, const std::string& prefix = "");
-
-        void init();
 
+        void defineProperties(armarx::PropertyDefinitionsPtr defs, const std::string& prefix = "") override;
+        void init() override;
         void connect(viz::Client arviz);
 
 
@@ -179,16 +180,8 @@ namespace armarx::armem::server::obj::instance
 
     private:
 
-        server::MemoryToIceAdapter& iceMemory;
-        wm::CoreSegment* coreSegment = nullptr;
-        std::mutex& memoryMutex;
-
-
         struct Properties
         {
-            std::string coreSegmentName = "Instance";
-            // -1 would be infinite, but this can let the RAM grow quickly.
-            long maxHistorySize = 25;
             bool discardSnapshotsWhileAttached = true;
 
             /// Package containing the scene snapshots
@@ -209,6 +202,7 @@ namespace armarx::armem::server::obj::instance
 
         static const std::string timestampPlaceholder;
 
+
     public:
 
         struct RemoteGui
@@ -227,7 +221,9 @@ namespace armarx::armem::server::obj::instance
             void update(Segment& data);
         };
 
+
     private:
+
         std::unique_ptr<ArticulatedObjectVisu> visu;
 
     };
diff --git a/source/RobotAPI/libraries/armem_objects/server/instance/SegmentAdapter.cpp b/source/RobotAPI/libraries/armem_objects/server/instance/SegmentAdapter.cpp
index e0577877f2ac9e9c7e97e8aaa50d99c438fe4c9f..7cd8b1202ac34600f8bfc6ecc912037b49d8bee6 100644
--- a/source/RobotAPI/libraries/armem_objects/server/instance/SegmentAdapter.cpp
+++ b/source/RobotAPI/libraries/armem_objects/server/instance/SegmentAdapter.cpp
@@ -37,17 +37,18 @@
 namespace armarx::armem::server::obj::instance
 {
 
-    SegmentAdapter::SegmentAdapter(MemoryToIceAdapter& iceMemory, std::mutex& memoryMutex) :
-        segment(iceMemory, memoryMutex),
-        memoryMutex(memoryMutex)
+    SegmentAdapter::SegmentAdapter(MemoryToIceAdapter& iceMemory) :
+        segment(iceMemory)
     {
     }
 
+
     std::string SegmentAdapter::getName() const
     {
         return Logging::tag.tagName;
     }
 
+
     void SegmentAdapter::defineProperties(armarx::PropertyDefinitionsPtr defs, const std::string& prefix)
     {
         calibration.defineProperties(defs, prefix + "calibration.");
@@ -56,6 +57,7 @@ namespace armarx::armem::server::obj::instance
         visu.defineProperties(defs, prefix + "visu.");
     }
 
+
     void SegmentAdapter::init()
     {
         segment.setTag(getName());
@@ -66,6 +68,7 @@ namespace armarx::armem::server::obj::instance
         segment.init();
     }
 
+
     void SegmentAdapter::connect(
         RobotStateComponentInterfacePrx robotStateComponent,
         VirtualRobot::RobotPtr robot,
@@ -97,6 +100,7 @@ namespace armarx::armem::server::obj::instance
         segment.connect(arviz);
     }
 
+
     void SegmentAdapter::reportProviderAvailable(const std::string& providerName, const objpose::ProviderInfo& info, const Ice::Current&)
     {
         updateProviderInfo(providerName, info);
@@ -120,7 +124,7 @@ namespace armarx::armem::server::obj::instance
             return;
         }
         {
-            std::scoped_lock lock(memoryMutex);
+            std::scoped_lock lock(segment.mutex());
             std::stringstream ss;
             for (const auto& id : info.supportedObjects)
             {
@@ -161,7 +165,7 @@ namespace armarx::armem::server::obj::instance
         }
 
         {
-            std::scoped_lock lock(memoryMutex);
+            std::scoped_lock lock(segment.mutex());
             RemoteRobot::synchronizeLocalClone(segment.robot, segment.robotStateComponent);
 
             if (segment.robot->hasRobotNode(calibration.robotNode))
@@ -215,7 +219,7 @@ namespace armarx::armem::server::obj::instance
         TIMING_START(tGetObjectPoses);
 
         TIMING_START(tGetObjectPosesLock);
-        std::scoped_lock lock(memoryMutex);
+        std::scoped_lock lock(segment.mutex());
         TIMING_END_STREAM(tGetObjectPosesLock, ARMARX_VERBOSE);
 
         const IceUtil::Time now = TimeUtil::GetTime();
@@ -240,7 +244,7 @@ namespace armarx::armem::server::obj::instance
         TIMING_START(GetObjectPoses);
 
         TIMING_START(GetObjectPosesLock);
-        std::scoped_lock lock(memoryMutex);
+        std::scoped_lock lock(segment.mutex());
         TIMING_END_STREAM(GetObjectPosesLock, ARMARX_VERBOSE);
 
         const IceUtil::Time now = TimeUtil::GetTime();
@@ -292,7 +296,7 @@ namespace armarx::armem::server::obj::instance
         }
         else
         {
-            std::scoped_lock lock(memoryMutex);
+            std::scoped_lock lock(segment.mutex());
             for (const auto& objectID : input.request.objectIDs)
             {
                 bool found = true;
@@ -336,27 +340,31 @@ namespace armarx::armem::server::obj::instance
         return output;
     }
 
+
     objpose::ProviderInfoMap SegmentAdapter::getAvailableProvidersInfo(const Ice::Current&)
     {
-        std::scoped_lock lock(memoryMutex);
+        std::scoped_lock lock(segment.mutex());
         return segment.providers;
     }
 
+
     Ice::StringSeq SegmentAdapter::getAvailableProviderNames(const Ice::Current&)
     {
-        std::scoped_lock lock(memoryMutex);
+        std::scoped_lock lock(segment.mutex());
         return simox::alg::get_keys(segment.providers);
     }
 
+
     objpose::ProviderInfo SegmentAdapter::getProviderInfo(const std::string& providerName, const Ice::Current&)
     {
-        std::scoped_lock lock(memoryMutex);
+        std::scoped_lock lock(segment.mutex());
         return segment.getProviderInfo(providerName);
     }
 
+
     bool SegmentAdapter::hasProvider(const std::string& providerName, const Ice::Current&)
     {
-        std::scoped_lock lock(memoryMutex);
+        std::scoped_lock lock(segment.mutex());
         return segment.providers.count(providerName) > 0;
     }
 
@@ -364,28 +372,30 @@ namespace armarx::armem::server::obj::instance
     objpose::AttachObjectToRobotNodeOutput SegmentAdapter::attachObjectToRobotNode(
         const objpose::AttachObjectToRobotNodeInput& input, const Ice::Current&)
     {
-        std::scoped_lock lock(memoryMutex);
+        std::scoped_lock lock(segment.mutex());
         return segment.attachObjectToRobotNode(input);
     }
 
+
     objpose::DetachObjectFromRobotNodeOutput SegmentAdapter::detachObjectFromRobotNode(
         const objpose::DetachObjectFromRobotNodeInput& input, const Ice::Current&)
     {
-        std::scoped_lock lock(memoryMutex);
+        std::scoped_lock lock(segment.mutex());
         return segment.detachObjectFromRobotNode(input);
     }
 
+
     objpose::DetachAllObjectsFromRobotNodesOutput SegmentAdapter::detachAllObjectsFromRobotNodes(
         const objpose::DetachAllObjectsFromRobotNodesInput& input, const Ice::Current&)
     {
-        std::scoped_lock lock(memoryMutex);
+        std::scoped_lock lock(segment.mutex());
         return segment.detachAllObjectsFromRobotNodes(input);
     }
 
 
     objpose::AgentFramesSeq SegmentAdapter::getAttachableFrames(const Ice::Current&)
     {
-        std::scoped_lock lock(memoryMutex);
+        std::scoped_lock lock(segment.mutex());
 
         objpose::AgentFramesSeq output;
         std::vector<VirtualRobot::RobotPtr> agents = { segment.robot };
@@ -398,6 +408,7 @@ namespace armarx::armem::server::obj::instance
         return output;
     }
 
+
     objpose::SignalHeadMovementOutput
     SegmentAdapter::signalHeadMovement(const objpose::SignalHeadMovementInput& input, const Ice::Current&)
     {
@@ -423,7 +434,7 @@ namespace armarx::armem::server::obj::instance
                     objpose::ObjectPoseMap objectPoses;
                     visu.minConfidence = -1;
                     {
-                        std::scoped_lock lock(memoryMutex);
+                        std::scoped_lock lock(segment.mutex());
 
                         const IceUtil::Time now = TimeUtil::GetTime();
 
@@ -493,6 +504,7 @@ namespace armarx::armem::server::obj::instance
         group.addChild(layout);
     }
 
+
     void SegmentAdapter::RemoteGui::update(SegmentAdapter& adapter)
     {
         // Non-atomic variables need to be guarded by a mutex if accessed by multiple threads
@@ -502,7 +514,7 @@ namespace armarx::armem::server::obj::instance
         }
         this->segment.update(adapter.segment);
         {
-            std::scoped_lock lock(adapter.memoryMutex);
+            std::scoped_lock lock(adapter.segment.mutex());
             this->decay.update(adapter.segment.decay);
         }
         {
diff --git a/source/RobotAPI/libraries/armem_objects/server/instance/SegmentAdapter.h b/source/RobotAPI/libraries/armem_objects/server/instance/SegmentAdapter.h
index a1e356e53c77608937b0df952798d0427a3cc86b..353f2e0644dc044edfd1f260a76eb0c5d7857a11 100644
--- a/source/RobotAPI/libraries/armem_objects/server/instance/SegmentAdapter.h
+++ b/source/RobotAPI/libraries/armem_objects/server/instance/SegmentAdapter.h
@@ -55,7 +55,7 @@ namespace armarx::armem::server::obj::instance
     {
     public:
 
-        SegmentAdapter(MemoryToIceAdapter& iceMemory, std::mutex& memoryMutex);
+        SegmentAdapter(MemoryToIceAdapter& iceMemory);
 
         std::string getName() const;
         void defineProperties(armarx::PropertyDefinitionsPtr defs, const std::string& prefix = "");
@@ -127,7 +127,6 @@ namespace armarx::armem::server::obj::instance
         DebugObserverInterfacePrx debugObserver;
 
         instance::Segment segment;
-        std::mutex& memoryMutex;
 
         instance::RobotHeadMovement robotHead;
         std::mutex robotHeadMutex;
diff --git a/source/RobotAPI/libraries/armem_robot_state/CMakeLists.txt b/source/RobotAPI/libraries/armem_robot_state/CMakeLists.txt
index 498a422fb201bf435cfb8ddbfdc43b71ba1944a0..defd8a3f48aa68b63673498549a731b573b9b9b4 100644
--- a/source/RobotAPI/libraries/armem_robot_state/CMakeLists.txt
+++ b/source/RobotAPI/libraries/armem_robot_state/CMakeLists.txt
@@ -11,6 +11,8 @@ armarx_add_library(
         # ArmarX
         ArmarXCore 
         ArmarXCoreInterfaces
+        DebugObserverHelper
+        # ArmarXGui
         ArmarXGuiComponentPlugins
         # This package
         RobotAPICore 
@@ -73,9 +75,10 @@ armarx_enable_aron_file_generation_for_target(
     TARGET_NAME
         "${LIB_NAME}"
     ARON_FILES
+        aron/JointState.xml
+        aron/Proprioception.xml
         aron/TransformHeader.xml
         aron/Transform.xml
-        aron/JointState.xml
 )
 
 
diff --git a/source/RobotAPI/libraries/armem_robot_state/aron/Proprioception.xml b/source/RobotAPI/libraries/armem_robot_state/aron/Proprioception.xml
new file mode 100644
index 0000000000000000000000000000000000000000..9a402c5f0f1fd80d18cdb92278404a12d5044845
--- /dev/null
+++ b/source/RobotAPI/libraries/armem_robot_state/aron/Proprioception.xml
@@ -0,0 +1,119 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<!--
+Robot proprioception.
+-->
+<AronTypeDefinition>
+    <GenerateTypes>
+
+        <Object name="armarx::armem::prop::arondto::Joints">
+            
+            <ObjectChild key="positions">
+                <Dict>
+                    <Float />
+                </Dict>
+            </ObjectChild>
+
+            <ObjectChild key="velocities">
+                <Dict>
+                    <Float />
+                </Dict>
+            </ObjectChild>
+            
+            <ObjectChild key="accellerations">
+                <Dict>
+                    <Float />
+                </Dict>
+            </ObjectChild>
+            
+            <ObjectChild key="torques">
+                <Dict>
+                    <Float />
+                </Dict>
+            </ObjectChild>
+            
+            <ObjectChild key="inertiaTorques">
+                <Dict>
+                    <Float />
+                </Dict>
+            </ObjectChild>
+            
+            <ObjectChild key="gravityTorques">
+                <Dict>
+                    <Float />
+                </Dict>
+            </ObjectChild>
+            
+            <ObjectChild key="inserveDynamicsTorques">
+                <Dict>
+                    <Float />
+                </Dict>
+            </ObjectChild>
+            
+        </Object>
+
+        
+        <Object name="armarx::armem::prop::arondto::Platform">
+            
+            <ObjectChild key="absolutePosition">
+                <EigenMatrix rows="3" cols="1" type="float" />
+            </ObjectChild>
+            
+            <ObjectChild key="relativePosition">
+                <EigenMatrix rows="3" cols="1" type="float" />
+            </ObjectChild>
+            
+            <ObjectChild key="velocity">
+                <EigenMatrix rows="3" cols="1" type="float" />
+            </ObjectChild>
+            
+            <ObjectChild key="accelleration">
+                <EigenMatrix rows="3" cols="1" type="float" />
+            </ObjectChild>
+            
+        </Object>
+        
+        
+        
+        <Object name="armarx::armem::prop::arondto::ForceTorque">
+            
+            <ObjectChild key="force">
+                <EigenMatrix rows="3" cols="1" type="float" />
+            </ObjectChild>
+            
+            <ObjectChild key="torque">
+                <EigenMatrix rows="3" cols="1" type="float" />
+            </ObjectChild>
+            
+            <ObjectChild key="gravityCompensationForce">
+                <EigenMatrix rows="3" cols="1" type="float" />
+            </ObjectChild>
+            
+            <ObjectChild key="gravityCompensationTorque">
+                <EigenMatrix rows="3" cols="1" type="float" />
+            </ObjectChild>
+            
+        </Object>
+
+        
+        
+        <Object name="armarx::armem::prop::arondto::Proprioception">
+            
+            <ObjectChild key="joints">
+                <armarx::armem::prop::arondto::Joints/>
+            </ObjectChild>
+            
+            <ObjectChild key="platform">
+                <armarx::armem::prop::arondto::Platform/>
+            </ObjectChild>
+            
+            <ObjectChild key="forceTorque">
+                <Dict>
+                    <armarx::armem::prop::arondto::ForceTorque/>
+                </Dict>
+            </ObjectChild>
+            
+        </Object>
+
+            
+    </GenerateTypes>
+</AronTypeDefinition>
diff --git a/source/RobotAPI/libraries/armem_robot_state/client/common/RobotReader.h b/source/RobotAPI/libraries/armem_robot_state/client/common/RobotReader.h
index 13b5572d382059bcff17ce2bb5bfb04cc819b04b..b3f71e59ac2b33c19ff97fd0c238f5540503b6ee 100644
--- a/source/RobotAPI/libraries/armem_robot_state/client/common/RobotReader.h
+++ b/source/RobotAPI/libraries/armem_robot_state/client/common/RobotReader.h
@@ -82,7 +82,7 @@ namespace armarx::armem::robot_state
 
         struct Properties
         {
-            std::string memoryName                = "RobotStateMemory";
+            std::string memoryName                = "RobotState";
             std::string descriptionCoreSegment    = "Description";
             std::string localizationCoreSegment   = "Localization";
             std::string proprioceptionCoreSegment = "Proprioception";
diff --git a/source/RobotAPI/libraries/armem_robot_state/client/localization/TransformWriter.cpp b/source/RobotAPI/libraries/armem_robot_state/client/localization/TransformWriter.cpp
index 47660fc439e597f4c8f59bbcff666223c5964e18..4230394aa823c96e2382fd73af68d9663513b989 100644
--- a/source/RobotAPI/libraries/armem_robot_state/client/localization/TransformWriter.cpp
+++ b/source/RobotAPI/libraries/armem_robot_state/client/localization/TransformWriter.cpp
@@ -63,22 +63,21 @@ namespace armarx::armem::client::robot_state::localization
     {
         ARMARX_DEBUG << "TransformWriter: registerPropertyDefinitions";
 
-        def->optional(properties.localizationSegment,
-                      propertyPrefix + "localizationSegment",
+        def->optional(properties.coreSegmentID.memoryName, propertyPrefix + "MemoryName");
+        def->optional(properties.coreSegmentID.coreSegmentName,
+                      propertyPrefix + "LocalizationSegmentName",
                       "Name of the localization memory core segment to use.");
-
-        def->optional(properties.memoryName, propertyPrefix + "Memory");
     }
 
     void TransformWriter::connect()
     {
         // Wait for the memory to become available and add it as dependency.
-        ARMARX_IMPORTANT << "TransformWriter: Waiting for memory '" << properties.memoryName
+        ARMARX_IMPORTANT << "TransformWriter: Waiting for memory '" << properties.coreSegmentID.memoryName
                          << "' ...";
         try
         {
-            memoryWriter = memoryNameSystem.useWriter(properties.memoryName);
-            ARMARX_IMPORTANT << "TransformWriter: Connected to memory '" << properties.memoryName << "'";
+            memoryWriter = memoryNameSystem.useWriter(properties.coreSegmentID);
+            ARMARX_IMPORTANT << "TransformWriter: Connected to memory for '" << properties.coreSegmentID << "'";
         }
         catch (const armem::error::CouldNotResolveMemoryServer& e)
         {
@@ -91,50 +90,19 @@ namespace armarx::armem::client::robot_state::localization
     {
         std::lock_guard g{memoryWriterMutex};
 
-        ARMARX_DEBUG << "Trying to create core segment + provider segment";
-
-        const auto providerId = [&]() -> std::optional<armem::MemoryID>
-        {
-            try
-            {
-                const auto result =
-                memoryWriter.addSegment(properties.localizationSegment, transform.header.agent);
-
-                if (not result.success)
-                {
-                    ARMARX_WARNING << "Could not obtain provider id! Reason: " <<  result.errorMessage;
-                    return std::nullopt;
-                }
-
-                return armem::MemoryID(result.segmentID);
-            }
-            catch (...)
-            {
-                ARMARX_WARNING << "Could not obtain provider id!";
-                return std::nullopt;
-            }
-        }();
-
-        if (not providerId)
-        {
-            return false;
-        }
-
+        const MemoryID providerId = properties.coreSegmentID.withProviderSegmentName(transform.header.agent);
         // const auto& timestamp = transform.header.timestamp;
-        const auto timestamp = IceUtil::Time::now(); // FIXME remove
-
-
-        const auto entityID   = providerId->withEntityName(transform.header.parentFrame + "," +
-                                transform.header.frame).withTimestamp(timestamp);
+        const MemoryID entityID = providerId.withEntityName(
+                                      transform.header.parentFrame + "," + transform.header.frame);
+        const Time timestamp = Time::now(); // FIXME remove
 
         armem::EntityUpdate update;
-        update.entityID    = entityID;
+        update.entityID = entityID;
+        update.timeCreated = timestamp;
 
         arondto::Transform aronTransform;
         toAron(aronTransform, transform);
-
         update.instancesData = {aronTransform.toAron()};
-        update.timeCreated = timestamp;
 
         ARMARX_DEBUG << "Committing " << update << " at time " << transform.header.timestamp;
         armem::EntityUpdateResult updateResult = memoryWriter.commit(update);
@@ -149,10 +117,4 @@ namespace armarx::armem::client::robot_state::localization
         return updateResult.success;
     }
 
-    // const std::string& TransformWriter::getPropertyPrefix() const
-    // {
-    //     return propertyPrefix;
-    // }
-
-
 }  // namespace armarx::armem::client::robot_state::localization
diff --git a/source/RobotAPI/libraries/armem_robot_state/client/localization/TransformWriter.h b/source/RobotAPI/libraries/armem_robot_state/client/localization/TransformWriter.h
index 299c79b69222accb8290a7064229a9dfe59e8572..e553b073464e5fcf1444e14a4fef48e2034e808c 100644
--- a/source/RobotAPI/libraries/armem_robot_state/client/localization/TransformWriter.h
+++ b/source/RobotAPI/libraries/armem_robot_state/client/localization/TransformWriter.h
@@ -61,6 +61,7 @@ namespace armarx::armem::client::robot_state::localization
 
         bool commitTransform(const ::armarx::armem::robot_state::Transform& transform) override;
 
+
     private:
 
         armem::client::MemoryNameSystem& memoryNameSystem;
@@ -70,8 +71,7 @@ namespace armarx::armem::client::robot_state::localization
         // Properties
         struct Properties
         {
-            std::string memoryName             = "RobotState";
-            std::string localizationSegment    = "Localization";
+            MemoryID coreSegmentID { "RobotState", "Localization" };
         } properties;
 
         const std::string propertyPrefix = "mem.robot_state.";
diff --git a/source/RobotAPI/libraries/armem_robot_state/common/localization/TransformHelper.cpp b/source/RobotAPI/libraries/armem_robot_state/common/localization/TransformHelper.cpp
index a59aa5a4c6cdd3ebe552522c0ffd532e873da82a..c4d0e05b4a1120b0ba6d256ad646508d7556ab7d 100644
--- a/source/RobotAPI/libraries/armem_robot_state/common/localization/TransformHelper.cpp
+++ b/source/RobotAPI/libraries/armem_robot_state/common/localization/TransformHelper.cpp
@@ -123,7 +123,7 @@ namespace armarx::armem::common::robot_state::localization
             }
             else
             {
-                ARMARX_WARNING << deactivateSpam(1) << "Cannot perform tf lookup '" << parentFrame << " -> " << frame
+                ARMARX_WARNING << deactivateSpam(10) << "Cannot perform tf lookup '" << parentFrame << " -> " << frame
                                << "'";
             }
         };
diff --git a/source/RobotAPI/libraries/armem_robot_state/server/common/Visu.cpp b/source/RobotAPI/libraries/armem_robot_state/server/common/Visu.cpp
index 9762ea0339755892ac79ef62dbfcc88353995b00..d6dcddd7d3fd568216a63657bfe6ae5ca1f10f9c 100644
--- a/source/RobotAPI/libraries/armem_robot_state/server/common/Visu.cpp
+++ b/source/RobotAPI/libraries/armem_robot_state/server/common/Visu.cpp
@@ -1,7 +1,8 @@
 #include "Visu.h"
 
-#include <Eigen/src/Geometry/Transform.h>
 #include <algorithm>
+#include <exception>
+#include <string>
 
 #include <Eigen/Geometry>
 
@@ -10,23 +11,29 @@
 #include <SimoxUtility/algorithm/get_map_keys_values.h>
 #include <SimoxUtility/math/pose.h>
 
-#include "ArmarXCore/core/logging/Logging.h"
-#include "ArmarXCore/core/time/CycleUtil.h"
+#include <ArmarXCore/core/logging/Logging.h>
+#include <ArmarXCore/core/time/CycleUtil.h>
 #include <ArmarXCore/core/time/TimeUtil.h>
 
-#include "RobotAPI/components/ArViz/Client/Elements.h"
-#include "RobotAPI/libraries/armem/core/Time.h"
+#include <RobotAPI/components/ArViz/Client/Elements.h>
+#include <RobotAPI/libraries/armem/core/Time.h>
 #include <RobotAPI/libraries/ArmarXObjects/ObjectFinder.h>
-#include <exception>
-#include <string>
 
 #include "../description/Segment.h"
 #include "../localization/Segment.h"
 #include "../proprioception/Segment.h"
 
+
 namespace armarx::armem::server::robot_state
 {
 
+    Visu::Visu(const description::Segment& descriptionSegment, const proprioception::Segment& proprioceptionSegment, const localization::Segment& localizationSegment)
+        : descriptionSegment(descriptionSegment),
+          proprioceptionSegment(proprioceptionSegment),
+          localizationSegment(localizationSegment)
+    {}
+
+
     void Visu::defineProperties(armarx::PropertyDefinitionsPtr defs, const std::string& prefix)
     {
         defs->optional(
@@ -34,9 +41,31 @@ namespace armarx::armem::server::robot_state
         defs->optional(p.frequencyHz, prefix + "frequenzyHz", "Frequency of visualization.");
     }
 
-    void Visu::visualizeRobots(viz::Layer& layer, const robot::Robots& robots)
+
+    void Visu::init()
     {
+    }
+
+
+    void Visu::connect(const viz::Client& arviz, DebugObserverInterfacePrx debugObserver)
+    {
+        this->arviz = arviz;
+        if (debugObserver)
+        {
+            bool batchMode = true;
+            this->debugObserver = DebugObserverHelper("RobotStateMemory", debugObserver, batchMode);
+        }
+
+        updateTask = new SimpleRunningTask<>([this]()
+        {
+            this->visualizeRun();
+        });
+        updateTask->start();
+    }
 
+
+    void Visu::visualizeRobots(viz::Layer& layer, const robot::Robots& robots)
+    {
         const auto visualizeRobot = [&](const robot::Robot & robot)
         {
             const auto xmlPath = robot.description.xml.serialize();
@@ -57,6 +86,7 @@ namespace armarx::armem::server::robot_state
         std::for_each(robots.begin(), robots.end(), visualizeRobot);
     }
 
+
     void Visu::visualizeFrames(
         viz::Layer& layerFrames,
         const std::unordered_map<std::string, std::vector<Eigen::Affine3f>>& frames)
@@ -69,79 +99,13 @@ namespace armarx::armem::server::robot_state
             for (const auto& frame : robotFrames)
             {
                 Eigen::Affine3f from = pose;
+                Eigen::Affine3f to = pose * frame;
 
-                pose = pose * frame; // to
-
-                Eigen::Affine3f to = pose;
-
-                const auto arr = viz::Arrow(robotName + std::to_string(++i)).fromTo(from.translation(), to.translation());
-                layerFrames.add(arr);
+                layerFrames.add(viz::Arrow(robotName + std::to_string(++i)).fromTo(from.translation(), to.translation()));
             }
         }
     }
 
-    void Visu::init() {}
-
-    void Visu::connect(const viz::Client& arviz)
-    {
-        this->arviz = arviz;
-
-        updateTask = new SimpleRunningTask<>([this]()
-        {
-            this->visualizeRun();
-        });
-        updateTask->start();
-    }
-
-    // void Visu::RemoteGui::setup(const Visu& visu)
-    // {
-    //     using namespace armarx::RemoteGui::Client;
-
-    //     enabled.setValue(visu.enabled);
-    //     inGlobalFrame.setValue(visu.inGlobalFrame);
-    //     alpha.setRange(0, 1.0);
-    //     alpha.setValue(visu.alpha);
-    //     alphaByConfidence.setValue(visu.alphaByConfidence);
-    //     oobbs.setValue(visu.oobbs);
-    //     objectFrames.setValue(visu.objectFrames);
-    //     {
-    //         float max = 10000;
-    //         objectFramesScale.setRange(0, max);
-    //         objectFramesScale.setDecimals(2);
-    //         objectFramesScale.setSteps(int(10 * max));
-    //         objectFramesScale.setValue(visu.objectFramesScale);
-    //     }
-
-    //     GridLayout grid;
-    //     int row = 0;
-    //     grid.add(Label("Enabled"), {row, 0}).add(enabled, {row, 1});
-    //     row++;
-    //     grid.add(Label("Global Frame"), {row, 0}).add(inGlobalFrame, {row, 1});
-    //     row++;
-    //     grid.add(Label("Alpha"), {row, 0}).add(alpha, {row, 1}, {1, 3});
-    //     row++;
-    //     grid.add(Label("Alpha by Confidence"), {row, 0}).add(alphaByConfidence, {row, 1});
-    //     row++;
-    //     grid.add(Label("OOBB"), {row, 0}).add(oobbs, {row, 1});
-    //     row++;
-    //     grid.add(Label("Object Frames"), {row, 0}).add(objectFrames, {row, 1});
-    //     grid.add(Label("Scale:"), {row, 2}).add(objectFramesScale, {row, 3});
-    //     row++;
-
-    //     group.setLabel("Visualization");
-    //     group.addChild(grid);
-    // }
-
-    // void Visu::RemoteGui::update(Visu& visu)
-    // {
-    //     visu.enabled = enabled.getValue();
-    //     visu.inGlobalFrame = inGlobalFrame.getValue();
-    //     visu.alpha = alpha.getValue();
-    //     visu.alphaByConfidence = alphaByConfidence.getValue();
-    //     visu.oobbs = oobbs.getValue();
-    //     visu.objectFrames = objectFrames.getValue();
-    //     visu.objectFramesScale = objectFramesScale.getValue();
-    // }
 
     robot::Robots combine(
         const std::unordered_map<std::string, robot::RobotDescription>& robotDescriptions,
@@ -191,34 +155,52 @@ namespace armarx::armem::server::robot_state
         return robots;
     }
 
+
     void Visu::visualizeRun()
     {
-
         CycleUtil cycle(static_cast<int>(1000 / p.frequencyHz));
         while (updateTask && not updateTask->isStopped())
         {
             {
                 // std::scoped_lock lock(visuMutex);
                 ARMARX_DEBUG << "Update task";
-
                 if (p.enabled)
                 {
-                    TIMING_START(Visu);
+                    TIMING_START(tVisuTotal);
 
                     // TODO(fabian.reister): use timestamp
-
-                    const auto timestamp = IceUtil::Time::now();
+                    const Time timestamp = Time::now();
 
                     try
                     {
-                        const auto robotDescriptions =
-                            descriptionSegment.getRobotDescriptions(timestamp);
+                        // Get data.
+                        TIMING_START(tVisuGetData);
+
+                        TIMING_START(tRobotDescriptions);
+                        const description::Segment::RobotDescriptionMap robotDescriptions =
+                            descriptionSegment.getRobotDescriptionsLocking(timestamp);
+                        TIMING_END_STREAM(tRobotDescriptions, ARMARX_DEBUG);
+
+                        TIMING_START(tGlobalRobotPoseMap);
                         const auto globalRobotPoseMap =
-                            localizationSegment.getRobotGlobalPoses(timestamp);
+                            localizationSegment.getRobotGlobalPosesLocking(timestamp);
+                        TIMING_END_STREAM(tGlobalRobotPoseMap, ARMARX_DEBUG);
+
+                        TIMING_START(tRobotFramePoses);
+                        const auto frames = localizationSegment.getRobotFramePosesLocking(timestamp);
+                        TIMING_END_STREAM(tRobotFramePoses, ARMARX_DEBUG);
+
+                        TIMING_START(tRobotJointPositionMap);
                         const auto robotJointPositionMap =
-                            proprioceptionSegment.getRobotJointPositions(timestamp);
+                            proprioceptionSegment.getRobotJointPositionsLocking(
+                                timestamp, debugObserver ? &*debugObserver : nullptr);
+                        TIMING_END_STREAM(tRobotJointPositionMap, ARMARX_DEBUG);
+
+                        TIMING_END_STREAM(tVisuGetData, ARMARX_DEBUG);
 
-                        const auto frames = localizationSegment.getRobotFramePoses(timestamp);
+
+                        // Build layers.
+                        TIMING_START(tVisuBuildLayers);
 
                         // we need all 3 informations:
                         // - robot description
@@ -228,44 +210,55 @@ namespace armarx::armem::server::robot_state
 
                         const robot::Robots robots =
                             combine(robotDescriptions, globalRobotPoseMap, robotJointPositionMap);
-                        viz::Layer layer = arviz.layer("Robots");
 
-                        ARMARX_DEBUG << "visualizing robots";
+                        ARMARX_DEBUG << "Visualize robots ...";
+                        viz::Layer layer = arviz.layer("Robots");
                         visualizeRobots(layer, robots);
 
-                        ARMARX_DEBUG << "Committing robots";
-
+                        ARMARX_DEBUG << "Visualize frames ...";
                         viz::Layer layerFrames = arviz.layer("Frames");
-
-                        ARMARX_DEBUG << "visualizing frames";
                         visualizeFrames(layerFrames, frames);
 
-                        ARMARX_DEBUG << "Committing frames";
-
-                        arviz.commit({layer, layerFrames});
+                        TIMING_END_STREAM(tVisuBuildLayers, ARMARX_DEBUG);
 
-                        ARMARX_DEBUG << "Done committing";
 
-                        TIMING_END_STREAM(Visu, ARMARX_VERBOSE);
+                        // Commit layers.
 
-                        // if (debugObserver)
-                        // {
-                        //     debugObserver->setDebugChannel(getName(),
-                        //     {
-                        //         { "t Visualize [ms]", new Variant(Visu.toMilliSecondsDouble()) },
-                        //     });
-                        // }
+                        ARMARX_DEBUG << "Commit visualization ...";
+                        TIMING_START(tVisuCommit);
+                        arviz.commit({layer, layerFrames});
+                        TIMING_END_STREAM(tVisuCommit, ARMARX_DEBUG);
+
+                        TIMING_END_STREAM(tVisuTotal, ARMARX_DEBUG);
+
+                        if (debugObserver.has_value())
+                        {
+                            const std::string p = "Visu | ";
+                            debugObserver->setDebugObserverDatafield(p + "t Total (ms)", tVisuTotal.toMilliSecondsDouble());
+                            debugObserver->setDebugObserverDatafield(p + "t 1 Get Data (ms)", tVisuGetData.toMilliSecondsDouble());
+                            debugObserver->setDebugObserverDatafield(p + "t 1.1 Descriptions (ms)", tRobotDescriptions.toMilliSecondsDouble());
+                            debugObserver->setDebugObserverDatafield(p + "t 1.2 Global Pose (ms)", tGlobalRobotPoseMap.toMilliSecondsDouble());
+                            debugObserver->setDebugObserverDatafield(p + "t 1.3 Frames (ms)", tRobotFramePoses.toMilliSecondsDouble());
+                            debugObserver->setDebugObserverDatafield(p + "t 1.4 Joint Positions (ms)", tRobotJointPositionMap.toMilliSecondsDouble());
+                            debugObserver->setDebugObserverDatafield(p + "t 2 Build Layers (ms)", tVisuBuildLayers.toMilliSecondsDouble());
+                            debugObserver->setDebugObserverDatafield(p + "t 3 Commit (ms)", tVisuCommit.toMilliSecondsDouble());
+                        }
                     }
                     catch (const std::exception& ex)
                     {
-                        ARMARX_WARNING << ex.what();
+                        ARMARX_WARNING << "Caught exception while visualizing robots: \n" << ex.what();
                         continue;
                     }
                     catch (...)
                     {
-                        ARMARX_WARNING << "Unknown exception";
+                        ARMARX_WARNING << "Caught unknown exception while visualizing robots.";
                         continue;
                     }
+
+                    if (debugObserver.has_value())
+                    {
+                        debugObserver->sendDebugObserverBatch();
+                    }
                 }
             }
             cycle.waitForCycleDuration();
diff --git a/source/RobotAPI/libraries/armem_robot_state/server/common/Visu.h b/source/RobotAPI/libraries/armem_robot_state/server/common/Visu.h
index 7e4b3814ce3a2c03f4ea8fb38846d4378c3a18c6..95efae41963c63669e4e4bb11b202ba9ef948ec9 100644
--- a/source/RobotAPI/libraries/armem_robot_state/server/common/Visu.h
+++ b/source/RobotAPI/libraries/armem_robot_state/server/common/Visu.h
@@ -21,10 +21,11 @@
 
 #pragma once
 
+#include <optional>
+
 #include <ArmarXCore/core/logging/Logging.h>
 #include <ArmarXCore/core/services/tasks/TaskUtil.h>
-
-// #include <ArmarXGui/libraries/RemoteGui/Client/Widgets.h>
+#include <ArmarXCore/libraries/DebugObserverHelper/DebugObserverHelper.h>
 
 #include <RobotAPI/components/ArViz/Client/Client.h>
 
@@ -42,12 +43,10 @@ namespace armarx::armem::server::robot_state
     {
         class Segment;
     }
-
     namespace proprioception
     {
         class Segment;
     }
-
     namespace description
     {
         class Segment;
@@ -64,17 +63,13 @@ namespace armarx::armem::server::robot_state
 
         Visu(const description::Segment& descriptionSegment,
              const proprioception::Segment& proprioceptionSegment,
-             const localization::Segment& localizationSegment)
-            : descriptionSegment(descriptionSegment),
-              proprioceptionSegment(proprioceptionSegment),
-              localizationSegment(localizationSegment)
-        {}
+             const localization::Segment& localizationSegment);
 
-        void defineProperties(armarx::PropertyDefinitionsPtr defs, const std::string& prefix = "visu.");
 
+        void defineProperties(armarx::PropertyDefinitionsPtr defs, const std::string& prefix = "visu.");
         void init();
+        void connect(const viz::Client& arviz, DebugObserverInterfacePrx debugObserver = nullptr);
 
-        void connect(const viz::Client& arviz);
 
     protected:
 
@@ -89,7 +84,9 @@ namespace armarx::armem::server::robot_state
 
 
     private:
+
         viz::Client arviz;
+        std::optional<DebugObserverHelper> debugObserver;
 
         const description::Segment& descriptionSegment;
         const proprioception::Segment& proprioceptionSegment;
@@ -105,23 +102,6 @@ namespace armarx::armem::server::robot_state
         SimpleRunningTask<>::pointer_type updateTask;
         void visualizeRun();
 
-        // struct RemoteGui
-        // {
-        //     armarx::RemoteGui::Client::GroupBox group;
-
-        //     armarx::RemoteGui::Client::CheckBox enabled;
-
-        //     armarx::RemoteGui::Client::CheckBox inGlobalFrame;
-        //     armarx::RemoteGui::Client::FloatSlider alpha;
-        //     armarx::RemoteGui::Client::CheckBox alphaByConfidence;
-        //     armarx::RemoteGui::Client::CheckBox oobbs;
-        //     armarx::RemoteGui::Client::CheckBox objectFrames;
-        //     armarx::RemoteGui::Client::FloatSpinBox objectFramesScale;
-
-        //     // void setup(const Visu& visu);
-        //     // void update(Visu& visu);
-        // };
-
     };
 
 }  // namespace armarx::armem::server::robot_state
diff --git a/source/RobotAPI/libraries/armem_robot_state/server/description/Segment.cpp b/source/RobotAPI/libraries/armem_robot_state/server/description/Segment.cpp
index d50d965608f7cf4ad8541467d75442303a293211..6f247e9bef4328d2d40dc289d0953cb2a3ddcd55 100644
--- a/source/RobotAPI/libraries/armem_robot_state/server/description/Segment.cpp
+++ b/source/RobotAPI/libraries/armem_robot_state/server/description/Segment.cpp
@@ -1,19 +1,20 @@
 #include "Segment.h"
 
-#include <IceUtil/Time.h>
-#include <RobotAPI/libraries/armem_robot/aron/RobotDescription.aron.generated.h>
 #include <sstream>
+#include <thread>
+
+#include <IceUtil/Time.h>
 
-#include "ArmarXCore/core/exceptions/local/ExpressionException.h"
-#include "ArmarXCore/core/logging/Logging.h"
+#include <ArmarXCore/core/application/properties/PluginAll.h>
+#include <ArmarXCore/core/exceptions/local/ExpressionException.h>
+#include <ArmarXCore/core/system/ArmarXDataPath.h>
+#include <ArmarXCore/core/system/cmake/CMakePackageFinder.h>
 #include <ArmarXCore/core/time/TimeUtil.h>
 
-#include "ArmarXCore/core/system/ArmarXDataPath.h"
-#include "ArmarXCore/core/system/cmake/CMakePackageFinder.h"
-#include "RobotAPI/libraries/armem_robot/types.h"
-#include "RobotAPI/libraries/aron/common/aron_conversions.h"
+#include <RobotAPI/libraries/armem_robot/types.h>
+#include <RobotAPI/libraries/aron/common/aron_conversions.h>
 
-#include "RobotAPI/libraries/armem/core/MemoryID.h"
+#include <RobotAPI/libraries/armem/core/MemoryID.h>
 #include <RobotAPI/libraries/armem/client/Writer.h>
 #include <RobotAPI/libraries/armem/client/query/Builder.h>
 #include <RobotAPI/libraries/armem/client/query/query_fns.h>
@@ -24,51 +25,32 @@
 #include <RobotAPI/libraries/armem_robot/aron/Robot.aron.generated.h>
 #include <RobotAPI/libraries/armem_robot/aron_conversions.h>
 #include <RobotAPI/libraries/armem_robot/robot_conversions.h>
-#include <thread>
+#include <RobotAPI/libraries/armem_robot/aron/RobotDescription.aron.generated.h>
+#include <RobotAPI/libraries/armem_robot_state/aron/Proprioception.aron.generated.h>
+
 
 namespace armarx::armem::server::robot_state::description
 {
 
-    Segment::Segment(armem::server::MemoryToIceAdapter& memoryToIceAdapter,
-                     std::mutex& memoryMutex) :
-        iceMemory(memoryToIceAdapter), memoryMutex(memoryMutex)
+    Segment::Segment(armem::server::MemoryToIceAdapter& memoryToIceAdapter) :
+        SpecializedSegment(memoryToIceAdapter, arondto::RobotDescription::toAronType(),
+                           "Description")
     {
-        Logging::setTag("DescriptionSegment");
     }
 
     Segment::~Segment() = default;
 
-    void Segment::defineProperties(armarx::PropertyDefinitionsPtr defs, const std::string& prefix)
-    {
-        defs->optional(p.coreSegment,
-                       prefix + "seg.description.CoreSegment",
-                       "Name of the robot description core segment.");
-        defs->optional(p.maxHistorySize,
-                       prefix + "seg.description.MaxHistorySize",
-                       "Maximal size of object poses history (-1 for infinite).");
-    }
 
-    void Segment::init()
+    void Segment::connect(const RobotUnitInterfacePrx& robotUnitPrx)
     {
-        ARMARX_CHECK_NOT_NULL(iceMemory.workingMemory);
-
-        ARMARX_INFO << "Adding core segment '" << p.coreSegment << "'";
-
-        coreSegment = &iceMemory.workingMemory->addCoreSegment(
-                          p.coreSegment, arondto::RobotDescription::toAronType());
-        coreSegment->setMaxHistorySize(p.maxHistorySize);
-    }
-
-    void Segment::connect(const viz::Client& arviz, const RobotUnitInterfacePrx& robotUnitPrx)
-    {
-        // this->visu = std::make_unique<Visu>(arviz, *this);
         robotUnit = robotUnitPrx;
 
         // store the robot description linked to the robot unit in this segment
         updateRobotDescription();
     }
 
-    void Segment::storeRobotDescription(const robot::RobotDescription& robotDescription)
+
+    void Segment::commitRobotDescription(const robot::RobotDescription& robotDescription)
     {
         const Time now = TimeUtil::GetTime();
 
@@ -88,139 +70,76 @@ namespace armarx::armem::server::robot_state::description
 
         Commit commit;
         commit.updates.push_back(update);
-
-        {
-            // std::lock_guard g{memoryMutex};
-            iceMemory.commit(commit);
-        }
-
+        iceMemory.commitLocking(commit);
     }
 
+
     void Segment::updateRobotDescription()
     {
         ARMARX_CHECK_NOT_NULL(robotUnit);
-        auto kinematicUnit = robotUnit->getKinematicUnit();
-
-        ARMARX_CHECK_NOT_NULL(kinematicUnit);
+        KinematicUnitInterfacePrx kinematicUnit = robotUnit->getKinematicUnit();
+        if (kinematicUnit)
+        {
+            const std::string robotName = kinematicUnit->getRobotName();
+            const std::string robotFilename = kinematicUnit->getRobotFilename();
 
-        const auto robotName = kinematicUnit->getRobotName();
-        const auto robotFilename = kinematicUnit->getRobotFilename();
+            const std::vector<std::string> packages = armarx::CMakePackageFinder::FindAllArmarXSourcePackages();
+            const std::string package = armarx::ArmarXDataPath::getProject(packages, robotFilename);
 
-        const auto packages = armarx::CMakePackageFinder::FindAllArmarXSourcePackages();
-        const auto package = armarx::ArmarXDataPath::getProject(packages, robotFilename);
+            ARMARX_INFO << "Robot description '" << robotFilename << "' found in package " << package;
 
-        ARMARX_INFO << "Robot description '" << robotFilename << "' found in package " << package;
+            const robot::RobotDescription robotDescription
+            {
+                .name = kinematicUnit->getRobotName(),
+                .xml  = {package, kinematicUnit->getRobotFilename()}
+            }; // FIXME
 
-        const robot::RobotDescription robotDescription
+            commitRobotDescription(robotDescription);
+        }
+        else
         {
-            .name = kinematicUnit->getRobotName(),
-            .xml  = {package, kinematicUnit->getRobotFilename()}}; // FIXME
+            ARMARX_WARNING << "Robot unit '" << robotUnit->ice_getIdentity().name << "' does not have a kinematic unit."
+                           << "\n Cannot commit robot description.";
+        }
+    }
 
-        storeRobotDescription(robotDescription);
+
+    Segment::RobotDescriptionMap Segment::getRobotDescriptionsLocking(const armem::Time& timestamp) const
+    {
+        std::scoped_lock lock(mutex());
+        return getRobotDescriptions(timestamp);
     }
 
+
     Segment::RobotDescriptionMap Segment::getRobotDescriptions(const armem::Time& timestamp) const
     {
+        ARMARX_CHECK_NOT_NULL(coreSegment);
+        (void) timestamp;  // Unused
 
         RobotDescriptionMap robotDescriptions;
-
         {
-            // std::lock_guard g{memoryMutex};
-
-            for (const auto &[_, provSeg] : iceMemory.workingMemory->getCoreSegment(p.coreSegment))
+            for (const auto& [_, provSeg] : *coreSegment)
             {
-                for (const auto &[name, entity] : provSeg.entities())
+                for (const auto& [name, entity] : provSeg.entities())
                 {
                     const auto& entityInstance = entity.getLatestSnapshot().getInstance(0);
                     const auto description     = robot::convertRobotDescription(entityInstance);
 
-                    if (not description)
+                    if (description)
                     {
-                        ARMARX_WARNING << "Could not convert entity instance to "
-                                       "'RobotDescription'";
-                        continue;
+                        ARMARX_DEBUG << "Key is " << armem::MemoryID(entity.id());
+                        robotDescriptions.emplace(description->name, *description);
+                    }
+                    else
+                    {
+                        ARMARX_WARNING << "Could not convert entity instance to 'RobotDescription'";
                     }
-
-                    ARMARX_DEBUG << "Key is " << armem::MemoryID(entity.id());
-
-                    robotDescriptions.emplace(description->name, *description);
                 }
             }
         }
 
-        ARMARX_INFO << deactivateSpam(10) <<  "Number of known robot descriptions: " << robotDescriptions.size();
-
+        ARMARX_INFO << deactivateSpam(60) <<  "Number of known robot descriptions: " << robotDescriptions.size();
         return robotDescriptions;
     }
 
-    // std::unordered_map<armem::MemoryID, ::armarx::armem::articulated_object::ArticulatedObjectDescription> Segment::getKnownObjectClasses() const
-    // {
-    //     std::unordered_map<armem::MemoryID, ::armarx::armem::articulated_object::ArticulatedObjectDescription> objects;
-
-    //     for (const auto& [_, provSeg] : iceMemory.workingMemory->getCoreSegment(p.coreClassSegmentName))
-    //     {
-    //         for (const auto& [name, entity] :  provSeg.entities())
-    //         {
-    //             const auto& entityInstance = entity.getLatestSnapshot().getInstance(0);
-    //             const auto description = articulated_object::convertRobotDescription(entityInstance);
-
-    //             if (not description)
-    //             {
-    //                 ARMARX_WARNING << "Could not convert entity instance to 'RobotDescription'";
-    //                 continue;
-    //             }
-
-    //             ARMARX_INFO << "Key is " << armem::MemoryID(entity.id());
-
-    //             objects.emplace(armem::MemoryID(entity.id()), *description);
-    //         }
-    //     }
-
-    //     ARMARX_IMPORTANT << "Number of known articulated object classes: " << objects.size();
-
-    //     return objects;
-    // }
-
-    // void Segment::RemoteGui::setup(const Segment& data)
-    // {
-    //     using namespace armarx::RemoteGui::Client;
-
-    //     maxHistorySize.setValue(std::max(1, int(data.p.maxHistorySize)));
-    //     maxHistorySize.setRange(1, 1e6);
-    //     infiniteHistory.setValue(data.p.maxHistorySize == -1);
-    //     discardSnapshotsWhileAttached.setValue(data.p.discardSnapshotsWhileAttached);
-
-    //     GridLayout grid;
-    //     int row = 0;
-    //     grid.add(Label("Max History Size"), {row, 0}).add(maxHistorySize, {row, 1});
-    //     row++;
-    //     grid.add(Label("Infinite History Size"), {row, 0}).add(infiniteHistory, {row, 1});
-    //     row++;
-    //     grid.add(Label("Discard Snapshots while Attached"), {row, 0}).add(discardSnapshotsWhileAttached, {row, 1});
-    //     row++;
-
-    //     group.setLabel("Data");
-    //     group.addChild(grid);
-    // }
-
-    // void Segment::RemoteGui::update(Segment& data)
-    // {
-    //     if (infiniteHistory.hasValueChanged() || maxHistorySize.hasValueChanged()
-    //         || discardSnapshotsWhileAttached.hasValueChanged())
-    //     {
-    //         std::scoped_lock lock(data.memoryMutex);
-
-    //         if (infiniteHistory.hasValueChanged() || maxHistorySize.hasValueChanged())
-    //         {
-    //             data.p.maxHistorySize = infiniteHistory.getValue() ? -1 : maxHistorySize.getValue();
-    //             if (data.coreSegment)
-    //             {
-    //                 data.coreSegment->setMaxHistorySize(long(data.p.maxHistorySize));
-    //             }
-    //         }
-
-    //         data.p.discardSnapshotsWhileAttached = discardSnapshotsWhileAttached.getValue();
-    //     }
-    // }
-
 } // namespace armarx::armem::server::robot_state::description
diff --git a/source/RobotAPI/libraries/armem_robot_state/server/description/Segment.h b/source/RobotAPI/libraries/armem_robot_state/server/description/Segment.h
index 2f603cf4961d90342fbd74770a0ef4d0d181c033..d020b5543e2c2f59ff593fc70c753640679b5a2b 100644
--- a/source/RobotAPI/libraries/armem_robot_state/server/description/Segment.h
+++ b/source/RobotAPI/libraries/armem_robot_state/server/description/Segment.h
@@ -21,94 +21,47 @@
 
 #pragma once
 
-#include <RobotAPI/interface/units/RobotUnit/RobotUnitInterface.h>
 #include <string>
 #include <optional>
 #include <mutex>
 #include <unordered_map>
 
-#include <ArmarXCore/core/logging/Logging.h>
-#include "ArmarXCore/core/application/properties/PropertyDefinitionContainer.h"
-
-// #include "ArmarXGui/libraries/RemoteGui/Client/Widgets.h"
-
-#include "RobotAPI/components/ArViz/Client/Client.h"
+#include <ArmarXCore/core/application/properties/PropertyDefinitionContainer.h>
 
-#include "RobotAPI/libraries/armem/core/MemoryID.h"
-#include "RobotAPI/libraries/armem_objects/types.h"
-
-namespace armarx::armem
-{
-    namespace server
-    {
-        class MemoryToIceAdapter;
-    }
+#include <RobotAPI/interface/units/RobotUnit/RobotUnitInterface.h>
+#include <RobotAPI/libraries/armem/core/MemoryID.h>
+#include <RobotAPI/libraries/armem/server/segment/SpecializedSegment.h>
+#include <RobotAPI/libraries/armem_objects/types.h>
 
-    namespace wm
-    {
-        class CoreSegment;
-    }
-}  // namespace armarx::armem
 
 
 namespace armarx::armem::server::robot_state::description
 {
-    class Visu;
-
-    class Segment : public armarx::Logging
+    class Segment : public segment::SpecializedSegment
     {
     public:
-        Segment(server::MemoryToIceAdapter& iceMemory,
-                std::mutex& memoryMutex);
 
-        virtual ~Segment();
+        Segment(server::MemoryToIceAdapter& iceMemory);
+        virtual ~Segment() override;
 
-        void connect(const viz::Client& arviz, const RobotUnitInterfacePrx& robotUnitPrx);
 
-        void defineProperties(armarx::PropertyDefinitionsPtr defs, const std::string& prefix = "");
+        void connect(const RobotUnitInterfacePrx& robotUnitPrx);
 
-        void init();
 
         /// mapping "robot name" -> "robot description"
         using RobotDescriptionMap = std::unordered_map<std::string, robot::RobotDescription>;
 
         RobotDescriptionMap getRobotDescriptions(const armem::Time& timestamp) const;
+        RobotDescriptionMap getRobotDescriptionsLocking(const armem::Time& timestamp) const;
+
 
     private:
 
-        void storeRobotDescription(const robot::RobotDescription& robotDescription);
+        void commitRobotDescription(const robot::RobotDescription& robotDescription);
         void updateRobotDescription();
 
-
-        server::MemoryToIceAdapter& iceMemory;
-        wm::CoreSegment* coreSegment = nullptr;
-        std::mutex& memoryMutex;
-
         RobotUnitInterfacePrx robotUnit;
 
-        struct Properties
-        {
-            std::string coreSegment = "Description";
-            int64_t maxHistorySize = -1;
-        };
-        Properties p;
-
-        // std::unique_ptr<Visu> visu;
-
-    public:
-
-        // struct RemoteGui
-        // {
-        //     armarx::RemoteGui::Client::GroupBox group;
-
-        //     armarx::RemoteGui::Client::IntSpinBox maxHistorySize;
-        //     armarx::RemoteGui::Client::CheckBox infiniteHistory;
-        //     armarx::RemoteGui::Client::CheckBox discardSnapshotsWhileAttached;
-
-        //     void setup(const Segment& data);
-        //     void update(Segment& data);
-        // };
-
     };
 
 }  // namespace armarx::armem::server::robot_state::description
diff --git a/source/RobotAPI/libraries/armem_robot_state/server/localization/Segment.cpp b/source/RobotAPI/libraries/armem_robot_state/server/localization/Segment.cpp
index e0dcf6c2bcd9d86012d98cf5aded6fee585ed866..dd01313495ac922287f36549342feb2575c7d053 100644
--- a/source/RobotAPI/libraries/armem_robot_state/server/localization/Segment.cpp
+++ b/source/RobotAPI/libraries/armem_robot_state/server/localization/Segment.cpp
@@ -1,7 +1,6 @@
 #include "Segment.h"
 
 // STL
-
 #include <iterator>
 #include <sstream>
 
@@ -12,6 +11,8 @@
 #include <Eigen/Core>
 #include <Eigen/Geometry>
 
+#include <ArmarXCore/core/application/properties/PropertyDefinitionContainer.h>
+#include <ArmarXCore/core/application/properties/PluginAll.h>
 #include <ArmarXCore/core/logging/Logging.h>
 #include <ArmarXCore/core/time/TimeUtil.h>
 
@@ -36,66 +37,50 @@
 #include <RobotAPI/libraries/armem_robot_state/common/localization/TransformHelper.h>
 #include <RobotAPI/libraries/armem_robot_state/common/localization/types.h>
 
+
 namespace armarx::armem::server::robot_state::localization
 {
 
-    Segment::Segment(armem::server::MemoryToIceAdapter& memoryToIceAdapter,
-                     std::mutex& memoryMutex) :
-        iceMemory(memoryToIceAdapter), memoryMutex(memoryMutex)
+    Segment::Segment(armem::server::MemoryToIceAdapter& memoryToIceAdapter) :
+        SpecializedSegment(memoryToIceAdapter, arondto::Transform::toAronType(),
+                           "Localization", 1024)
     {
-        Logging::setTag("LocalizationSegment");
     }
 
+
     Segment::~Segment() = default;
 
-    void Segment::defineProperties(armarx::PropertyDefinitionsPtr defs, const std::string& prefix)
-    {
-        defs->optional(p.coreSegment,
-                       prefix + "seg.localization.CoreSegment",
-                       "Name of the object instance core segment.");
-        defs->optional(p.maxHistorySize,
-                       prefix + "seg.localization.MaxHistorySize",
-                       "Maximal size of object poses history (-1 for infinite).");
-    }
 
-    void Segment::init()
+    void Segment::connect()
     {
-        ARMARX_CHECK_NOT_NULL(iceMemory.workingMemory);
-
-        ARMARX_INFO << "Adding core segment '" << p.coreSegment << "'";
-
-        coreSegment = &iceMemory.workingMemory->addCoreSegment(
-                          p.coreSegment, arondto::Transform::toAronType());
-        coreSegment->setMaxHistorySize(p.maxHistorySize);
     }
 
-    void Segment::connect(viz::Client arviz)
+
+    Segment::RobotFramePoseMap
+    Segment::getRobotFramePosesLocking(const armem::Time& timestamp) const
     {
-        // this->visu = std::make_unique<Visu>(arviz, *this);
+        std::scoped_lock lock(mutex());
+        return getRobotFramePoses(timestamp);
     }
 
-    std::unordered_map<std::string, std::vector<Eigen::Affine3f>>
-            Segment::getRobotFramePoses(const armem::Time& timestamp) const
+
+    Segment::RobotFramePoseMap
+    Segment::getRobotFramePoses(const armem::Time& timestamp) const
     {
         using common::robot_state::localization::TransformHelper;
         using common::robot_state::localization::TransformQuery;
 
-        std::unordered_map<std::string, std::vector<Eigen::Affine3f>> frames;
-
-        const auto& localizationCoreSegment =
-            iceMemory.workingMemory->getCoreSegment(p.coreSegment);
-        const auto knownRobots = simox::alg::get_keys(localizationCoreSegment);
+        RobotFramePoseMap frames;
 
+        const auto knownRobots = simox::alg::get_keys(*coreSegment);
         for (const auto& robotName : knownRobots)
         {
-
             TransformQuery query{.header{.parentFrame = GlobalFrame,
                                          .frame       = "root", // TODO, FIXME
                                          .agent       = robotName,
                                          .timestamp   = timestamp}};
 
-            const auto result = TransformHelper::lookupTransformChain(localizationCoreSegment, query);
-
+            const auto result = TransformHelper::lookupTransformChain(*coreSegment, query);
             if (not result)
             {
                 // TODO
@@ -105,26 +90,32 @@ namespace armarx::armem::server::robot_state::localization
             frames.emplace(robotName, result.transforms);
         }
 
-        ARMARX_INFO << deactivateSpam(10)
+        ARMARX_INFO << deactivateSpam(60)
                     << "Number of known robot pose chains: " << frames.size();
 
         return frames;
     }
 
-    std::unordered_map<std::string, Eigen::Affine3f>
-    Segment::getRobotGlobalPoses(const armem::Time& timestamp) const
+
+    Segment::RobotPoseMap
+    Segment::getRobotGlobalPosesLocking(const armem::Time& timestamp) const
     {
+        std::scoped_lock lock(mutex());
+        return getRobotGlobalPoses(timestamp);
+    }
 
+
+    Segment::RobotPoseMap
+    Segment::getRobotGlobalPoses(const armem::Time& timestamp) const
+    {
         using common::robot_state::localization::TransformHelper;
         using common::robot_state::localization::TransformQuery;
 
-        std::unordered_map<std::string, Eigen::Affine3f> robotGlobalPoses;
+        RobotPoseMap robotGlobalPoses;
 
-        const auto& localizationCoreSegment =
-            iceMemory.workingMemory->getCoreSegment(p.coreSegment);
-        const auto knownRobots = simox::alg::get_keys(localizationCoreSegment);
+        const std::vector<std::string> knownRobots = simox::alg::get_keys(*coreSegment);
 
-        for (const auto& robotName : knownRobots)
+        for (const std::string& robotName : knownRobots)
         {
 
             TransformQuery query{.header{.parentFrame = GlobalFrame,
@@ -132,8 +123,7 @@ namespace armarx::armem::server::robot_state::localization
                                          .agent       = robotName,
                                          .timestamp   = timestamp}};
 
-            const auto result = TransformHelper::lookupTransform(localizationCoreSegment, query);
-
+            const auto result = TransformHelper::lookupTransform(*coreSegment, query);
             if (not result)
             {
                 // TODO
@@ -143,106 +133,47 @@ namespace armarx::armem::server::robot_state::localization
             robotGlobalPoses.emplace(robotName, result.transform.transform);
         }
 
-        ARMARX_INFO << deactivateSpam(10)
+        ARMARX_INFO << deactivateSpam(60)
                     << "Number of known robot poses: " << robotGlobalPoses.size();
 
         return robotGlobalPoses;
     }
 
-    bool Segment::storeTransform(const armarx::armem::robot_state::Transform& transform)
+
+    bool Segment::commitTransform(const armarx::armem::robot_state::Transform& transform)
     {
-        const auto& timestamp = transform.header.timestamp;
+        Commit commit;
+        commit.add(makeUpdate(transform));
 
-        const MemoryID providerID =
-            coreSegment->id().withProviderSegmentName(transform.header.agent);
-        if (not coreSegment->hasProviderSegment(providerID.providerSegmentName))
-        {
-            coreSegment->addProviderSegment(providerID.providerSegmentName, arondto::Transform::toAronType());
-        }
+        const armem::CommitResult result = iceMemory.commit(commit);
+        return result.allSuccess();
+    }
 
+
+    bool Segment::commitTransformLocking(const armarx::armem::robot_state::Transform& transform)
+    {
         Commit commit;
+        commit.add(makeUpdate(transform));
 
-        EntityUpdate& update = commit.updates.emplace_back();
-        update.entityID =
-            providerID.withEntityName(transform.header.parentFrame + "," + transform.header.frame);
+        const armem::CommitResult result = iceMemory.commitLocking(commit);
+        return result.allSuccess();
+    }
+
+
+    EntityUpdate Segment::makeUpdate(const armarx::armem::robot_state::Transform& transform) const
+    {
+        const armem::Time& timestamp = transform.header.timestamp;
+        const MemoryID providerID = coreSegment->id().withProviderSegmentName(transform.header.agent);
+
+        EntityUpdate update;
+        update.entityID = providerID.withEntityName(transform.header.parentFrame + "," + transform.header.frame);
         update.timeArrived = update.timeCreated = update.timeSent = timestamp;
 
         arondto::Transform aronTransform;
         toAron(aronTransform, transform);
         update.instancesData = {aronTransform.toAron()};
 
-        const armem::CommitResult result = iceMemory.commit(commit);
-        return result.allSuccess();
+        return update;
     }
 
-    // std::unordered_map<armem::MemoryID, ::armarx::armem::articulated_object::ArticulatedObjectDescription> Segment::getKnownObjectClasses() const
-    // {
-    //     std::unordered_map<armem::MemoryID, ::armarx::armem::articulated_object::ArticulatedObjectDescription> objects;
-
-    //     for (const auto& [_, provSeg] : iceMemory.workingMemory->getCoreSegment(p.coreClassSegmentName))
-    //     {
-    //         for (const auto& [name, entity] :  provSeg.entities())
-    //         {
-    //             const auto& entityInstance = entity.getLatestSnapshot().getInstance(0);
-    //             const auto description = articulated_object::convertRobotDescription(entityInstance);
-
-    //             if (not description)
-    //             {
-    //                 ARMARX_WARNING << "Could not convert entity instance to 'RobotDescription'";
-    //                 continue;
-    //             }
-
-    //             ARMARX_INFO << "Key is " << armem::MemoryID(entity.id());
-
-    //             objects.emplace(armem::MemoryID(entity.id()), *description);
-    //         }
-    //     }
-
-    //     ARMARX_IMPORTANT << "Number of known articulated object classes: " << objects.size();
-
-    //     return objects;
-    // }
-
-    // void Segment::RemoteGui::setup(const Segment& data)
-    // {
-    //     using namespace armarx::RemoteGui::Client;
-
-    //     maxHistorySize.setValue(std::max(1, int(data.p.maxHistorySize)));
-    //     maxHistorySize.setRange(1, 1e6);
-    //     infiniteHistory.setValue(data.p.maxHistorySize == -1);
-    //     discardSnapshotsWhileAttached.setValue(data.p.discardSnapshotsWhileAttached);
-
-    //     GridLayout grid;
-    //     int row = 0;
-    //     grid.add(Label("Max History Size"), {row, 0}).add(maxHistorySize, {row, 1});
-    //     row++;
-    //     grid.add(Label("Infinite History Size"), {row, 0}).add(infiniteHistory, {row, 1});
-    //     row++;
-    //     grid.add(Label("Discard Snapshots while Attached"), {row, 0}).add(discardSnapshotsWhileAttached, {row, 1});
-    //     row++;
-
-    //     group.setLabel("Data");
-    //     group.addChild(grid);
-    // }
-
-    // void Segment::RemoteGui::update(Segment& data)
-    // {
-    //     if (infiniteHistory.hasValueChanged() || maxHistorySize.hasValueChanged()
-    //         || discardSnapshotsWhileAttached.hasValueChanged())
-    //     {
-    //         std::scoped_lock lock(data.memoryMutex);
-
-    //         if (infiniteHistory.hasValueChanged() || maxHistorySize.hasValueChanged())
-    //         {
-    //             data.p.maxHistorySize = infiniteHistory.getValue() ? -1 : maxHistorySize.getValue();
-    //             if (data.coreSegment)
-    //             {
-    //                 data.coreSegment->setMaxHistorySize(long(data.p.maxHistorySize));
-    //             }
-    //         }
-
-    //         data.p.discardSnapshotsWhileAttached = discardSnapshotsWhileAttached.getValue();
-    //     }
-    // }
-
 } // namespace armarx::armem::server::robot_state::localization
diff --git a/source/RobotAPI/libraries/armem_robot_state/server/localization/Segment.h b/source/RobotAPI/libraries/armem_robot_state/server/localization/Segment.h
index 307eaae17babf66aa9d0a1e759cbc348cbb05008..d573c37ec8c90fc25a4de80eed877bc32f825dcd 100644
--- a/source/RobotAPI/libraries/armem_robot_state/server/localization/Segment.h
+++ b/source/RobotAPI/libraries/armem_robot_state/server/localization/Segment.h
@@ -23,86 +23,53 @@
 
 #include <string>
 #include <optional>
-#include <mutex>
 #include <unordered_map>
 
-#include <ArmarXCore/core/logging/Logging.h>
-#include "ArmarXCore/core/application/properties/PropertyDefinitionContainer.h"
-
-// #include "ArmarXGui/libraries/RemoteGui/Client/Widgets.h"
-
-#include "RobotAPI/components/ArViz/Client/Client.h"
-
-#include "RobotAPI/libraries/armem/core/MemoryID.h"
-#include "RobotAPI/libraries/armem_objects/types.h"
+#include <Eigen/Geometry>
 
+#include <RobotAPI/libraries/armem/core/MemoryID.h>
+#include <RobotAPI/libraries/armem/server/segment/SpecializedSegment.h>
+#include <RobotAPI/libraries/armem_objects/types.h>
 #include <RobotAPI/libraries/armem_robot_state/types.h>
 
+
 namespace armarx::armem
 {
-    namespace server
-    {
-        class MemoryToIceAdapter;
-    }
-
-    namespace wm
-    {
-        class CoreSegment;
-    }
+    class EntityUpdate;
 }  // namespace armarx::armem
 
-
 namespace armarx::armem::server::robot_state::localization
 {
-    class Visu;
-
-    class Segment : public armarx::Logging
+    class Segment : public segment::SpecializedSegment
     {
     public:
-        Segment(server::MemoryToIceAdapter& iceMemory,
-                std::mutex& memoryMutex);
 
-        virtual ~Segment();
+        using RobotPoseMap = std::unordered_map<std::string, Eigen::Affine3f>;
+        using RobotFramePoseMap = std::unordered_map<std::string, std::vector<Eigen::Affine3f>>;
 
-        void connect(viz::Client arviz);
 
-        void defineProperties(armarx::PropertyDefinitionsPtr defs, const std::string& prefix = "");
+    public:
 
-        void init();
+        Segment(server::MemoryToIceAdapter& iceMemory);
+        virtual ~Segment() override;
 
-        std::unordered_map<std::string, Eigen::Affine3f> getRobotGlobalPoses(const armem::Time& timestamp) const;
-        std::unordered_map<std::string, std::vector<Eigen::Affine3f>> getRobotFramePoses(const armem::Time& timestamp) const;
 
-        bool storeTransform(const armarx::armem::robot_state::Transform& transform);
+        void connect();
 
-    private:
+        RobotPoseMap getRobotGlobalPoses(const armem::Time& timestamp) const;
+        RobotPoseMap getRobotGlobalPosesLocking(const armem::Time& timestamp) const;
 
-        server::MemoryToIceAdapter& iceMemory;
-        wm::CoreSegment* coreSegment = nullptr;
-        std::mutex& memoryMutex;
+        RobotFramePoseMap getRobotFramePoses(const armem::Time& timestamp) const;
+        RobotFramePoseMap getRobotFramePosesLocking(const armem::Time& timestamp) const;
 
-        struct Properties
-        {
-            std::string coreSegment = "Localization";
-            int64_t maxHistorySize = -1;
-        };
-        Properties p;
+        bool commitTransform(const armarx::armem::robot_state::Transform& transform);
+        bool commitTransformLocking(const armarx::armem::robot_state::Transform& transform);
 
-        // std::unique_ptr<Visu> visu;
 
-    public:
-
-        // struct RemoteGui
-        // {
-        //     armarx::RemoteGui::Client::GroupBox group;
+    private:
 
-        //     armarx::RemoteGui::Client::IntSpinBox maxHistorySize;
-        //     armarx::RemoteGui::Client::CheckBox infiniteHistory;
-        //     armarx::RemoteGui::Client::CheckBox discardSnapshotsWhileAttached;
+        EntityUpdate makeUpdate(const armarx::armem::robot_state::Transform& transform) const;
 
-        //     void setup(const Segment& data);
-        //     void update(Segment& data);
-        // };
 
     };
 
diff --git a/source/RobotAPI/libraries/armem_robot_state/server/proprioception/Segment.cpp b/source/RobotAPI/libraries/armem_robot_state/server/proprioception/Segment.cpp
index ac5e5e1c36e66d47251700ec6565a9fb61ce5430..5e01e84ebc5724f672c7f32d01497624d0759b3e 100644
--- a/source/RobotAPI/libraries/armem_robot_state/server/proprioception/Segment.cpp
+++ b/source/RobotAPI/libraries/armem_robot_state/server/proprioception/Segment.cpp
@@ -1,176 +1,166 @@
 #include "Segment.h"
 
-#include <mutex>
 #include <sstream>
 
+#include <ArmarXCore/core/application/properties/PropertyDefinitionContainer.h>
+#include <ArmarXCore/core/logging/Logging.h>
 #include <ArmarXCore/core/time/TimeUtil.h>
-#include "ArmarXCore/core/logging/Logging.h"
+#include <ArmarXCore/libraries/DebugObserverHelper/DebugObserverHelper.h>
 
-#include "RobotAPI/libraries/armem_robot_state/types.h"
-#include "RobotAPI/libraries/aron/common/aron_conversions.h"
+#include <RobotAPI/libraries/aron/common/aron_conversions.h>
+#include <RobotAPI/libraries/armem_robot_state/types.h>
 
 #include <RobotAPI/libraries/armem/core/aron_conversions.h>
 #include <RobotAPI/libraries/armem/core/workingmemory/visitor.h>
-#include "RobotAPI/libraries/armem/core/MemoryID.h"
+#include <RobotAPI/libraries/armem/core/MemoryID.h>
 #include <RobotAPI/libraries/armem/client/Writer.h>
 #include <RobotAPI/libraries/armem/client/query/Builder.h>
 #include <RobotAPI/libraries/armem/client/query/query_fns.h>
 #include <RobotAPI/libraries/armem/server/MemoryToIceAdapter.h>
+#include <RobotAPI/libraries/armem/util/util.h>
 
-#include "RobotAPI/libraries/armem_robot/robot_conversions.h"
+#include <RobotAPI/libraries/armem_robot/robot_conversions.h>
 #include <RobotAPI/libraries/armem_robot/aron/Robot.aron.generated.h>
-#include <RobotAPI/libraries/armem_robot_state/aron/JointState.aron.generated.h>
+#include <RobotAPI/libraries/armem_robot_state/aron/Proprioception.aron.generated.h>
 
 #include <RobotAPI/libraries/armem_objects/aron_conversions.h>
 
-#include <RobotAPI/libraries/armem/util/util.h>
 
 
 namespace armarx::armem::server::robot_state::proprioception
 {
 
-    Segment::Segment(armem::server::MemoryToIceAdapter& memoryToIceAdapter, std::mutex& memoryMutex) :
-        iceMemory(memoryToIceAdapter),
-        memoryMutex(memoryMutex)
+    Segment::Segment(armem::server::MemoryToIceAdapter& memoryToIceAdapter) :
+        SpecializedSegment(memoryToIceAdapter, prop::arondto::Proprioception::toAronType(),
+                           "Proprioception", 1024)
     {
-        Logging::setTag("ProprioceptionSegment");
     }
 
     Segment::~Segment() = default;
 
-    void Segment::defineProperties(armarx::PropertyDefinitionsPtr defs, const std::string& prefix)
-    {
-        defs->optional(p.coreSegment, prefix + "seg.proprioception.CoreSegment", "Name of the object instance core segment.");
-        defs->optional(p.maxHistorySize, prefix + "seg.proprioception.MaxHistorySize", "Maximal size of object poses history (-1 for infinite).");
-    }
 
-    void Segment::init()
+    void Segment::connect(RobotUnitInterfacePrx robotUnitPrx)
     {
-        ARMARX_CHECK_NOT_NULL(iceMemory.workingMemory);
+        this->robotUnit = robotUnitPrx;
 
-        ARMARX_INFO << "Adding core segment '" <<  p.coreSegment << "'";
-        coreSegment = &iceMemory.workingMemory->addCoreSegment(p.coreSegment);
-        coreSegment->setMaxHistorySize(p.maxHistorySize);
+        std::string providerSegmentName = "Robot";
+        KinematicUnitInterfacePrx kinematicUnit = robotUnit->getKinematicUnit();
+        if (kinematicUnit)
+        {
+            providerSegmentName = kinematicUnit->getRobotName();
+        }
+        else
+        {
+            ARMARX_WARNING << "Robot unit '" << robotUnit->ice_getIdentity().name << "' does not have a kinematic unit."
+                           << "\n Falling back to provider segment name '" << providerSegmentName << "'.";
+        }
+        this->robotUnitProviderID = coreSegment->id().withProviderSegmentName(providerSegmentName);
     }
 
-    void Segment::connect(viz::Client arviz, RobotUnitInterfacePrx robotUnitPrx)
-    {
-        robotUnit = robotUnitPrx;
-
-        auto kinematicUnit = robotUnit->getKinematicUnit();
-        const auto providerSegmentName = kinematicUnit->getRobotName();
-
-        // TODO what is the purpose?
-        auto encoderEntryType = std::make_shared<aron::typenavigator::ObjectNavigator>("RobotUnitEncoderEntry");
-        auto encoderNameType = std::make_shared<aron::typenavigator::StringNavigator>();
-        auto encoderIterationIDType = std::make_shared<aron::typenavigator::LongNavigator>();
-        encoderEntryType->addMemberType("EncoderGroupName", encoderNameType);
-        encoderEntryType->addMemberType("IterationId", encoderIterationIDType);
-        //auto encoderValueType = std::make_shared<aron::typenavigator::AnyType>();
-        //encoderEntryType->addMemberType("value", encoderValueType);
 
-        ARMARX_INFO << "Adding provider segment " << p.coreSegment << "/" << providerSegmentName;
-        armem::data::AddSegmentInput input;
-        input.coreSegmentName = p.coreSegment;
-        input.providerSegmentName = providerSegmentName;
 
+    Segment::RobotJointPositionMap Segment::getRobotJointPositionsLocking(
+        const armem::Time& timestamp,
+        DebugObserverHelper* debugObserver) const
+    {
+        TIMING_START(tRobotJointPositionsLock);
+        std::scoped_lock lock(mutex());
+        TIMING_END_STREAM(tRobotJointPositionsLock, ARMARX_DEBUG);
+        if (debugObserver)
         {
-            std::lock_guard g{memoryMutex};
-            auto result = iceMemory.addSegments({input})[0];
-
-            if (!result.success)
-            {
-                ARMARX_ERROR << "Could not add segment " << p.coreSegment << "/" << providerSegmentName << ". The error message is: " << result.errorMessage;
-            }
+            debugObserver->setDebugObserverDatafield(dp + "t 0 Lock Core Segment (ms)", tRobotJointPositionsLock.toMilliSecondsDouble());
         }
-
-        robotUnitProviderID.memoryName = iceMemory.workingMemory->id().memoryName;
-        robotUnitProviderID.coreSegmentName = p.coreSegment;
-        robotUnitProviderID.providerSegmentName = providerSegmentName;
+        return getRobotJointPositions(timestamp, debugObserver);
     }
 
-    std::unordered_map<std::string, std::map<std::string, float>> Segment::getRobotJointPositions(const armem::Time& timestamp) const
+
+    Segment::RobotJointPositionMap Segment::getRobotJointPositions(
+        const armem::Time& timestamp,
+        DebugObserverHelper* debugObserver) const
     {
-        std::unordered_map<std::string, std::map<std::string, float>> jointMap;
+        namespace adn = aron::datanavigator;
+        ARMARX_CHECK_NOT_NULL(coreSegment);
 
-        std::lock_guard g{memoryMutex};
+        RobotJointPositionMap jointMap;
 
-        for (const auto& [robotName, provSeg] : iceMemory.workingMemory->getCoreSegment(p.coreSegment))
+        TIMING_START(tProcessProviders);
+        for (const auto& [robotName, provSeg] : *coreSegment)
         {
+            TIMING_START(tProcessEntities);
+            int i = 0;
             for (const auto& [name, entity] :  provSeg.entities())
             {
-                try
+                TIMING_START(tProcessEntity);
+
+                TIMING_START(tGetLatestInstance);
+                if (entity.empty())
                 {
-                    const auto& entityInstance = entity.getLatestSnapshot().getInstance(0);
-                    const auto jointState = tryCast<armarx::armem::arondto::JointState>(entityInstance);
+                    continue;
+                }
+                const wm::EntitySnapshot& snapshot = entity.getLatestSnapshot();
+                if (snapshot.empty())
+                {
+                    continue;
+                }
+                const wm::EntityInstance& entityInstance = snapshot.getInstance(0);
+                TIMING_END_COMMENT_STREAM(tGetLatestInstance, "tGetLatestInstance " + std::to_string(i), ARMARX_DEBUG);
 
-                    if (not jointState)
-                    {
-                        // ARMARX_WARNING << "Could not convert entity instance to 'JointState'";
-                        continue;
-                    }
-                    jointMap[robotName].emplace(jointState->name, jointState->position);
+                TIMING_START(tCastJointState);
+                aron::datanavigator::DictNavigatorPtr data = entityInstance.data();
+                // Avoid throwing an exception.
+                if (!(data->hasElement("name") && data->hasElement("position")))
+                {
+                    continue;
+                }
+                const std::string jointName = adn::StringNavigator::DynamicCastAndCheck(data->getElement("name"))->getValue();
+                const float jointPosition = adn::FloatNavigator::DynamicCastAndCheck(data->getElement("position"))->getValue();
+                TIMING_END_COMMENT_STREAM(tCastJointState, "tCastJointState " + std::to_string(i), ARMARX_DEBUG);
 
+                TIMING_START(tEmplace);
+                if (not jointName.empty())
+                {
+                    jointMap[robotName].emplace(jointName, jointPosition);
                 }
-                catch (...) // empty history etc
+                else
                 {
+                    // This may happen, just ignore it.
+                    // ARMARX_WARNING << "Could not convert entity instance to 'JointState'";
+                }
+                TIMING_END_COMMENT_STREAM(tEmplace, "tEmplace " + std::to_string(i), ARMARX_DEBUG);
 
+                TIMING_END_COMMENT_STREAM(tProcessEntity, "tProcessEntity " + std::to_string(i), ARMARX_DEBUG);
+
+                if (debugObserver)
+                {
+                    debugObserver->setDebugObserverDatafield(dp + "t 1.1.1.1 GetLatestInstance (ms)", tGetLatestInstance.toMilliSecondsDouble());
+                    debugObserver->setDebugObserverDatafield(dp + "t 1.1.1.2 CastJointState (ms)", tCastJointState.toMilliSecondsDouble());
+                    debugObserver->setDebugObserverDatafield(dp + "t 1.1.1.3 Emplace (ms)", tEmplace.toMilliSecondsDouble());
+                    debugObserver->setDebugObserverDatafield(dp + "t 1.1.1.T Process Entity (ms)", tProcessEntity.toMilliSecondsDouble());
                 }
+                ++i;
+            }
+            TIMING_END_STREAM(tProcessEntities, ARMARX_DEBUG);
+            if (debugObserver)
+            {
+                debugObserver->setDebugObserverDatafield(dp + "t 1.1 Process Entities (ms)", tProcessEntities.toMilliSecondsDouble());
             }
         }
+        TIMING_END_STREAM(tProcessProviders, ARMARX_DEBUG);
+
+        ARMARX_INFO << deactivateSpam(60) <<  "Number of known robot joint maps: " << jointMap.size();
 
-        ARMARX_INFO << deactivateSpam(10) <<  "Number of known robot joint maps: " << jointMap.size();
+        if (debugObserver)
+        {
+            debugObserver->setDebugObserverDatafield(dp + "t 1 Process Providers (ms)", tProcessProviders.toMilliSecondsDouble());
+        }
 
         return jointMap;
     }
 
+
     const armem::MemoryID& Segment::getRobotUnitProviderID() const
     {
         return robotUnitProviderID;
     }
 
-
-
-    // void Segment::RemoteGui::setup(const Segment& data)
-    // {
-    //     using namespace armarx::RemoteGui::Client;
-
-    //     maxHistorySize.setValue(std::max(1, int(data.p.maxHistorySize)));
-    //     maxHistorySize.setRange(1, 1e6);
-    //     infiniteHistory.setValue(data.p.maxHistorySize == -1);
-    //     discardSnapshotsWhileAttached.setValue(data.p.discardSnapshotsWhileAttached);
-
-    //     GridLayout grid;
-    //     int row = 0;
-    //     grid.add(Label("Max History Size"), {row, 0}).add(maxHistorySize, {row, 1});
-    //     row++;
-    //     grid.add(Label("Infinite History Size"), {row, 0}).add(infiniteHistory, {row, 1});
-    //     row++;
-    //     grid.add(Label("Discard Snapshots while Attached"), {row, 0}).add(discardSnapshotsWhileAttached, {row, 1});
-    //     row++;
-
-    //     group.setLabel("Data");
-    //     group.addChild(grid);
-    // }
-
-    // void Segment::RemoteGui::update(Segment& data)
-    // {
-    //     if (infiniteHistory.hasValueChanged() || maxHistorySize.hasValueChanged()
-    //         || discardSnapshotsWhileAttached.hasValueChanged())
-    //     {
-    //         std::scoped_lock lock(data.memoryMutex);
-
-    //         if (infiniteHistory.hasValueChanged() || maxHistorySize.hasValueChanged())
-    //         {
-    //             data.p.maxHistorySize = infiniteHistory.getValue() ? -1 : maxHistorySize.getValue();
-    //             if (data.coreSegment)
-    //             {
-    //                 data.coreSegment->setMaxHistorySize(long(data.p.maxHistorySize));
-    //             }
-    //         }
-
-    //         data.p.discardSnapshotsWhileAttached = discardSnapshotsWhileAttached.getValue();
-    //     }
-    // }
-
 }  // namespace armarx::armem::server::robot_state::proprioception
diff --git a/source/RobotAPI/libraries/armem_robot_state/server/proprioception/Segment.h b/source/RobotAPI/libraries/armem_robot_state/server/proprioception/Segment.h
index bc83a946bcadafbc85a15d55cff79c3a18af970f..87ef6a4e2b7937f3196a2ee0ce4610b22fd1e1cb 100644
--- a/source/RobotAPI/libraries/armem_robot_state/server/proprioception/Segment.h
+++ b/source/RobotAPI/libraries/armem_robot_state/server/proprioception/Segment.h
@@ -21,89 +21,53 @@
 
 #pragma once
 
-#include <RobotAPI/interface/units/RobotUnit/RobotUnitInterface.h>
 #include <string>
 #include <optional>
-#include <mutex>
 #include <unordered_map>
 
-#include <ArmarXCore/core/logging/Logging.h>
-#include "ArmarXCore/core/application/properties/PropertyDefinitionContainer.h"
-
-// #include "ArmarXGui/libraries/RemoteGui/Client/Widgets.h"
+#include <RobotAPI/interface/units/RobotUnit/RobotUnitInterface.h>
 
-#include "RobotAPI/components/ArViz/Client/Client.h"
+#include <RobotAPI/components/ArViz/Client/Client.h>
+#include <RobotAPI/libraries/armem/core/MemoryID.h>
+#include <RobotAPI/libraries/armem/server/segment/SpecializedSegment.h>
+#include <RobotAPI/libraries/armem_objects/types.h>
 
-#include "RobotAPI/libraries/armem/core/MemoryID.h"
-#include "RobotAPI/libraries/armem_objects/types.h"
 
-namespace armarx::armem
+namespace armarx
 {
-    namespace server
-    {
-        class MemoryToIceAdapter;
-    }
-
-    namespace wm
-    {
-        class CoreSegment;
-    }
-}  // namespace armarx::armem
-
-
+    class DebugObserverHelper;
+}
 namespace armarx::armem::server::robot_state::proprioception
 {
-    class Visu;
-
-    class Segment : public armarx::Logging
+    class Segment : public segment::SpecializedSegment
     {
     public:
-        Segment(server::MemoryToIceAdapter& iceMemory, std::mutex& memoryMutex);
 
-        virtual ~Segment();
+        using RobotJointPositionMap = std::unordered_map<std::string, std::map<std::string, float>>;
+
+    public:
 
-        void connect(viz::Client arviz, RobotUnitInterfacePrx robotUnitPrx);
+        Segment(server::MemoryToIceAdapter& iceMemory);
+        virtual ~Segment() override;
 
-        void defineProperties(armarx::PropertyDefinitionsPtr defs, const std::string& prefix = "");
+        void connect(RobotUnitInterfacePrx robotUnitPrx);
 
-        void init();
 
-        std::unordered_map<std::string, std::map<std::string, float>> getRobotJointPositions(const armem::Time& timestamp) const;
+        RobotJointPositionMap getRobotJointPositions(
+            const armem::Time& timestamp, DebugObserverHelper* debugObserver = nullptr) const;
+        RobotJointPositionMap getRobotJointPositionsLocking(
+            const armem::Time& timestamp, DebugObserverHelper* debugObserver = nullptr) const;
 
         const armem::MemoryID& getRobotUnitProviderID() const;
 
-    private:
 
-        server::MemoryToIceAdapter& iceMemory;
-        wm::CoreSegment* coreSegment = nullptr;
-        std::mutex& memoryMutex;
+    private:
 
         RobotUnitInterfacePrx robotUnit;
-
         armem::MemoryID robotUnitProviderID;
 
-        struct Properties
-        {
-            std::string coreSegment = "Proprioception";
-            int64_t maxHistorySize = -1;
-        };
-        Properties p;
-
-        // std::unique_ptr<Visu> visu;
-
-    public:
-
-        // struct RemoteGui
-        // {
-        //     armarx::RemoteGui::Client::GroupBox group;
-
-        //     armarx::RemoteGui::Client::IntSpinBox maxHistorySize;
-        //     armarx::RemoteGui::Client::CheckBox infiniteHistory;
-        //     armarx::RemoteGui::Client::CheckBox discardSnapshotsWhileAttached;
-
-        //     void setup(const Segment& data);
-        //     void update(Segment& data);
-        // };
+        // Debug Observer prefix
+        const std::string dp = "Proprioception::getRobotJointPositions() | ";
 
     };
 
diff --git a/source/RobotAPI/libraries/aron/core/Randomizer.h b/source/RobotAPI/libraries/aron/core/Randomizer.h
index bdc05099f108f0abaecb8db68cc58f47b8688a6c..00f355baa9c01e66792a886b027ad4186b808016 100644
--- a/source/RobotAPI/libraries/aron/core/Randomizer.h
+++ b/source/RobotAPI/libraries/aron/core/Randomizer.h
@@ -55,6 +55,7 @@ namespace armarx::aron
             {
                 nextMaybeType = getRandomElement(type::ALL_MAYBE_TYPES);
             }
+            (void) nextMaybeType;  // Unused
 
             switch (nextType)
             {