diff --git a/source/RobotAPI/components/armem/server/RobotStateMemory/CMakeLists.txt b/source/RobotAPI/components/armem/server/RobotStateMemory/CMakeLists.txt
index 86d1123051adb3bde67b885c6ba04a4d76736ea3..137453970c1a97f0f3bd9653c067e959db21b4a5 100644
--- a/source/RobotAPI/components/armem/server/RobotStateMemory/CMakeLists.txt
+++ b/source/RobotAPI/components/armem/server/RobotStateMemory/CMakeLists.txt
@@ -4,8 +4,11 @@ armarx_component_set_name("RobotStateMemory")
 set(COMPONENT_LIBS
     ArmarXCore ArmarXCoreInterfaces  # for DebugObserverInterface
     ArmarXGuiComponentPlugins
-    RobotAPICore RobotAPIInterfaces RobotAPIComponentPlugins armem
-    # RobotAPIComponentPlugins  # for ArViz and other plugins
+    RobotAPICore
+    RobotAPIInterfaces 
+    RobotAPIComponentPlugins 
+    armem
+    armem_robot_state
 )
 
 set(SOURCES
diff --git a/source/RobotAPI/components/armem/server/RobotStateMemory/RobotStateMemory.cpp b/source/RobotAPI/components/armem/server/RobotStateMemory/RobotStateMemory.cpp
index 3c45114cacec2e232507add552b5e69a41d4236a..6d6981ff5c6076279d52b20d32bd0d956cbf7ec8 100644
--- a/source/RobotAPI/components/armem/server/RobotStateMemory/RobotStateMemory.cpp
+++ b/source/RobotAPI/components/armem/server/RobotStateMemory/RobotStateMemory.cpp
@@ -21,11 +21,14 @@
  */
 
 // STD
+#include <RobotAPI/interface/units/RobotUnit/RobotUnitInterface.h>
 #include <algorithm>
 #include <iostream>
 #include <fstream>
 
 // Header
+#include "ArmarXCore/core/logging/Logging.h"
+#include "RobotAPI/libraries/core/Pose.h"
 #include "RobotStateMemory.h"
 
 // Simox
@@ -43,6 +46,12 @@
 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)
     {
     }
 
@@ -54,6 +63,10 @@ namespace armarx::armem::server::robot_state
         defs->optional(robotUnitPollFrequency, "RobotUnitUpdateFrequency", "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, "robotUnitConfigPath", "Specify a configuration file to group the sensor values specifically.");
 
+        descriptionSegment.defineProperties(defs);
+        proprioceptionSegment.defineProperties(defs);
+        localizationSegment.defineProperties(defs);
+
         return defs;
     }
 
@@ -66,10 +79,14 @@ namespace armarx::armem::server::robot_state
 
     void RobotStateMemory::onInitComponent()
     {
+
+        descriptionSegment.init();
+        proprioceptionSegment.init();
+        localizationSegment.init();
+
         robotUnitMemoryBatchSize = std::max((unsigned int) 1, robotUnitMemoryBatchSize);
         robotUnitPollFrequency = std::clamp(robotUnitPollFrequency, 1, ROBOT_UNIT_MAXIMUM_FREQUENCY);
 
-
         Ice::StringSeq includePaths;
         auto packages = armarx::Application::GetProjectDependencies();
         packages.push_back(Application::GetProjectName());
@@ -95,9 +112,12 @@ namespace armarx::armem::server::robot_state
 
     void RobotStateMemory::onConnectComponent()
     {
-        setupRobotUnitSegment();
+        descriptionSegment.connect(getArvizClient(), getRobotUnit());
+
+        proprioceptionSegment.connect(getArvizClient(), getRobotUnit());
+        toIce(robotUnitProviderID, proprioceptionSegment.getRobotUnitProviderID());
 
-        setupLocalizationCoreSegment();
+        localizationSegment.connect(getArvizClient());
 
         cfg.loggingNames.emplace_back(robotUnitSensorPrefix);
         handler = make_shared<RobotUnitDataStreamingReceiver>(this, getRobotUnit(), cfg);
@@ -124,45 +144,6 @@ namespace armarx::armem::server::robot_state
     /*************************************************************/
     // RobotUnit Streaming functions
     /*************************************************************/
-    void RobotStateMemory::setupLocalizationCoreSegment()
-    {
-        ARMARX_INFO << "Adding core segment " << localizationCoreSegmentName;
-        workingMemory.addCoreSegments({localizationCoreSegmentName});
-    }
-
-    /*************************************************************/
-    // RobotUnit Streaming functions
-    /*************************************************************/
-    void RobotStateMemory::setupRobotUnitSegment()
-    {
-        ARMARX_INFO << "Adding core segment " << proprioceptionCoreSegmentName;
-        workingMemory.addCoreSegments({proprioceptionCoreSegmentName});
-
-        ARMARX_INFO << "Adding provider segment " << proprioceptionCoreSegmentName << "/" << robotUnitProviderSegmentName;
-        armem::data::AddSegmentInput input;
-        input.coreSegmentName = proprioceptionCoreSegmentName;
-        input.providerSegmentName = robotUnitProviderSegmentName;
-
-        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);
-
-        auto result = addSegments({input})[0];
-
-        if (!result.success)
-        {
-            ARMARX_ERROR << "Could not add segment " << proprioceptionCoreSegmentName << "/" << robotUnitProviderSegmentName << ". The error message is: " << result.errorMessage;
-        }
-
-        robotUnitProviderID.memoryName = workingMemoryName;
-        robotUnitProviderID.coreSegmentName = proprioceptionCoreSegmentName;
-        robotUnitProviderID.providerSegmentName = robotUnitProviderSegmentName;
-    }
-
     void RobotStateMemory::convertRobotUnitStreamingDataToAron()
     {
         auto& data = handler->getDataBuffer();
diff --git a/source/RobotAPI/components/armem/server/RobotStateMemory/RobotStateMemory.h b/source/RobotAPI/components/armem/server/RobotStateMemory/RobotStateMemory.h
index 015c7bd5510cd35dabccdb1c15b0b6a39bdc8081..6917665b57c26444fb383eee501b06e7fcad13e2 100644
--- a/source/RobotAPI/components/armem/server/RobotStateMemory/RobotStateMemory.h
+++ b/source/RobotAPI/components/armem/server/RobotStateMemory/RobotStateMemory.h
@@ -30,15 +30,20 @@
 // Simox
 #include <SimoxUtility/meta/enum/adapt_enum.h>
 
-// BaseClass
+// 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/RobotUnitDataStreamingReceiver/RobotUnitDataStreamingReceiver.h>
 #include <RobotAPI/libraries/armem/server/ComponentPlugin.h>
 
-// ArmarX
-#include <ArmarXCore/core/services/tasks/PeriodicTask.h>
-
+#include <RobotAPI/libraries/armem_robot_state/server/description/Segment.h>
+#include <RobotAPI/libraries/armem_robot_state/server/proprioception/Segment.h>
+#include <RobotAPI/libraries/armem_robot_state/server/localization/Segment.h>
 
 namespace armarx::armem::server::robot_state
 {
@@ -56,8 +61,8 @@ namespace armarx::armem::server::robot_state
     class RobotStateMemory :
         virtual public armarx::Component,
         virtual public armem::server::ComponentPluginUser,
-        virtual public RobotUnitComponentPluginUser
-
+        virtual public RobotUnitComponentPluginUser,
+        virtual public armarx::ArVizComponentPluginUser
     {
     public:
         RobotStateMemory();
@@ -83,32 +88,29 @@ namespace armarx::armem::server::robot_state
 
     private:
         // RobotUnit Streaming
-        void setupRobotUnitSegment();
-
         void convertRobotUnitStreamingDataToAron();
         void storeConvertedRobotUnitDataInMemory();
 
         void startRobotUnitStream();
         void stopRobotUnitStream();
 
-        // localization segment
-        void setupLocalizationCoreSegment();
-
     private:
         std::string workingMemoryName = "RobotStateMemory";
         bool addCoreSegmentOnUsage = false;
 
         mutable std::recursive_mutex startStopMutex;
 
-        // Memory IDs
+        // Core segments
+
+        // - description
+        description::Segment descriptionSegment;
 
         // - proprioception
-        std::string proprioceptionCoreSegmentName = "Proprioception";
-        std::string robotUnitProviderSegmentName = "RobotUnit"; // get robot name?
+        proprioception::Segment proprioceptionSegment;
         armem::data::MemoryID robotUnitProviderID;
 
         // - localization
-        std::string localizationCoreSegmentName = "Localization";
+        localization::Segment localizationSegment;
 
         // RobotUnit stuff
         RobotUnitDataStreaming::DataStreamingDescription keys;
diff --git a/source/RobotAPI/libraries/CMakeLists.txt b/source/RobotAPI/libraries/CMakeLists.txt
index 1778ba42d2c67c1d6967485ee5fbcaa05241488a..ace5dff8c0498522fd979a2b6a371c8dd160ecd9 100644
--- a/source/RobotAPI/libraries/CMakeLists.txt
+++ b/source/RobotAPI/libraries/CMakeLists.txt
@@ -20,7 +20,8 @@ add_subdirectory(natik)
 add_subdirectory(armem)
 add_subdirectory(armem_gui)
 add_subdirectory(armem_objects)
-add_subdirectory(armem_robot_localization)
+add_subdirectory(armem_robot)
+add_subdirectory(armem_robot_state)
 add_subdirectory(armem_robot_mapping)
 add_subdirectory(aron)
 
diff --git a/source/RobotAPI/libraries/armem/CMakeLists.txt b/source/RobotAPI/libraries/armem/CMakeLists.txt
index 03f509ce8d6cd2ddcce5c2800e14a8cafb25dfa1..dbb5033f19cd3661131ff12e092d2894ab3c2e2d 100644
--- a/source/RobotAPI/libraries/armem/CMakeLists.txt
+++ b/source/RobotAPI/libraries/armem/CMakeLists.txt
@@ -217,7 +217,7 @@ armarx_enable_aron_file_generation_for_target(
 )
 
 
-add_library(RobotAPI::libraries::armem ALIAS "${LIB_NAME}")
+add_library(RobotAPI::armem ALIAS "${LIB_NAME}")
 
 
 # add unit tests
diff --git a/source/RobotAPI/libraries/armem_objects/CMakeLists.txt b/source/RobotAPI/libraries/armem_objects/CMakeLists.txt
index b491f16ce361bb4c5ca46b1f46104b6cb302711e..ed02a9adf315ef755af2c8da64d4a37c3d4817b6 100644
--- a/source/RobotAPI/libraries/armem_objects/CMakeLists.txt
+++ b/source/RobotAPI/libraries/armem_objects/CMakeLists.txt
@@ -14,7 +14,8 @@ armarx_add_library(
         RobotAPI::ArViz
         RobotAPI::ComponentPlugins
         RobotAPI::Core
-        RobotAPI::libraries::armem
+        RobotAPI::armem
+        RobotAPI::armem_robot
     HEADERS
         aron_conversions.h
         aron_forward_declarations.h
@@ -36,9 +37,6 @@ armarx_add_library(
         client/articulated_object/Reader.cpp
         client/articulated_object/Writer.cpp
 
-        articulated_object_conversions.cpp
-
-
     SOURCES
         aron_conversions.cpp
 
@@ -61,8 +59,6 @@ armarx_add_library(
         client/articulated_object/Writer.h
         client/articulated_object/interfaces.h
 
-        articulated_object_conversions.h
-
 )
 
 
@@ -75,9 +71,6 @@ armarx_enable_aron_file_generation_for_target(
         aron/ObjectInstance.xml
 
         # aron/Attachment.xml
-        aron/RobotDescription.xml
-        aron/RobotState.xml
-        aron/Robot.xml
         aron/Constraint.xml
 )
 
diff --git a/source/RobotAPI/libraries/armem_objects/aron_conversions.cpp b/source/RobotAPI/libraries/armem_objects/aron_conversions.cpp
index 12066bc173c19dac13850db7fc61b07aed22ec8b..001f69f9890a27067871dc893fcdc42675618990 100644
--- a/source/RobotAPI/libraries/armem_objects/aron_conversions.cpp
+++ b/source/RobotAPI/libraries/armem_objects/aron_conversions.cpp
@@ -30,61 +30,4 @@ namespace armarx::armem
         objpose::toAron(dto.pose, bo);
     }
 
-
-    /* to be moved */
-    void fromAron(const long& dto, IceUtil::Time& time)
-    {
-        time = IceUtil::Time::microSeconds(dto);
-    }
-
-    void toAron(long& dto, const IceUtil::Time& time)
-    {
-        dto = time.toMicroSeconds();
-    }
-
-
-    /* Robot */
-
-    void fromAron(const arondto::Robot& dto, Robot& bo)
-    {
-        // fromAron(dto.description, bo.description);
-        fromAron(dto.state, bo.config);
-    }
-
-    void toAron(arondto::Robot& dto, const Robot& bo)
-    {
-        // toAron(dto.description, bo.description);
-        toAron(dto.state, bo.config);
-    }
-
-    /* RobotDescription */
-
-    void fromAron(const arondto::RobotDescription& dto, RobotDescription& bo)
-    {
-        aron::fromAron(dto.name, bo.name);
-        fromAron(dto.xml, bo.xml);
-    }
-
-    void toAron(arondto::RobotDescription& dto, const RobotDescription& bo)
-    {
-        aron::toAron(dto.name, bo.name);
-        toAron(dto.xml, bo.xml);
-    }
-
-    /* RobotState */
-
-    void fromAron(const arondto::RobotState& dto, RobotState& bo)
-    {
-        fromAron(dto.timestamp, bo.timestamp);
-        bo.globalPose.matrix() = dto.globalPose;
-        bo.jointMap            = dto.jointMap;
-    }
-
-    void toAron(arondto::RobotState& dto, const RobotState& bo)
-    {
-        toAron(dto.timestamp, bo.timestamp);
-        dto.globalPose = bo.globalPose.matrix();
-        dto.jointMap   = bo.jointMap;
-    }
-
 }  // namespace armarx::armem
diff --git a/source/RobotAPI/libraries/armem_objects/aron_conversions.h b/source/RobotAPI/libraries/armem_objects/aron_conversions.h
index 64dd1ac67e944867927ba4e51a25dbaf6c6c428d..735c9a481f60ae4bb37624bcba99a22103780cf1 100644
--- a/source/RobotAPI/libraries/armem_objects/aron_conversions.h
+++ b/source/RobotAPI/libraries/armem_objects/aron_conversions.h
@@ -3,14 +3,8 @@
 #include <RobotAPI/libraries/ArmarXObjects/ObjectPose.h>
 
 #include <RobotAPI/libraries/armem_objects/aron/ObjectInstance.aron.generated.h>
-
-
 #include <RobotAPI/libraries/armem_objects/types.h>
 
-#include <RobotAPI/libraries/armem_objects/aron/RobotDescription.aron.generated.h>
-#include <RobotAPI/libraries/armem_objects/aron/RobotState.aron.generated.h>
-#include <RobotAPI/libraries/armem_objects/aron/Robot.aron.generated.h>
-
 namespace armarx::armem
 {
     void fromAron(const arondto::ObjectInstance& dto, objpose::arondto::ObjectPose& bo);
@@ -19,20 +13,4 @@ namespace armarx::armem
     void fromAron(const arondto::ObjectInstance& dto, objpose::ObjectPose& bo);
     void toAron(arondto::ObjectInstance& dto, const objpose::ObjectPose& bo);
 
-
-    // TODO move the following
-    void fromAron(const long& dto, IceUtil::Time& time);
-    void toAron(long& dto, const IceUtil::Time& time);
-    // end TODO
-
-
-    void fromAron(const arondto::Robot& dto, Robot& bo);
-    void toAron(arondto::Robot& dto, const Robot& bo);
-
-    void fromAron(const arondto::RobotDescription& dto, RobotDescription& bo);
-    void toAron(arondto::RobotDescription& dto, const RobotDescription& bo);
-
-    void fromAron(const arondto::RobotState& dto, RobotState& bo);
-    void toAron(arondto::RobotState& dto, const RobotState& bo);
-
 }  // namespace armarx::armem
diff --git a/source/RobotAPI/libraries/armem_objects/client/articulated_object/Reader.cpp b/source/RobotAPI/libraries/armem_objects/client/articulated_object/Reader.cpp
index 19359fabc2dfd68c475b31241cd8f2b24b2b9fa0..03173cf876b1c77a4c68dcff4e7962a21d784164 100644
--- a/source/RobotAPI/libraries/armem_objects/client/articulated_object/Reader.cpp
+++ b/source/RobotAPI/libraries/armem_objects/client/articulated_object/Reader.cpp
@@ -8,10 +8,10 @@
 
 #include "RobotAPI/libraries/armem/core/Time.h"
 #include "RobotAPI/libraries/armem/client/query/Builder.h"
-#include "RobotAPI/libraries/armem_objects/aron_conversions.h"
-#include <RobotAPI/libraries/armem_objects/aron/Robot.aron.generated.h>
+#include "RobotAPI/libraries/armem_robot/robot_conversions.h"
+#include "RobotAPI/libraries/armem_robot/aron_conversions.h"
+#include <RobotAPI/libraries/armem_robot/aron/Robot.aron.generated.h>
 
-#include "RobotAPI/libraries/armem_objects/articulated_object_conversions.h"
 
 namespace fs = ::std::filesystem;
 
@@ -63,7 +63,7 @@ namespace armarx::armem::articulated_object
         obj.config = std::move(*state);
     }
 
-    std::optional<RobotDescription> Reader::queryDescription(const std::string& name, const armem::Time& timestamp)
+    std::optional<robot::RobotDescription> Reader::queryDescription(const std::string& name, const armem::Time& timestamp)
     {
         // Query all entities from provider.
         armem::client::query::Builder qb;
@@ -88,7 +88,7 @@ namespace armarx::armem::articulated_object
         return getRobotDescription(qResult.memory);
     }
 
-    std::optional<RobotState> Reader::queryState(const RobotDescription& description, const armem::Time& timestamp)
+    std::optional<robot::RobotState> Reader::queryState(const robot::RobotDescription& description, const armem::Time& timestamp)
     {
         // TODO(fabian.reister): how to deal with multiple providers?
 
@@ -116,7 +116,7 @@ namespace armarx::armem::articulated_object
     }
 
 
-    std::optional<RobotState> Reader::getRobotState(const armarx::armem::wm::Memory& memory) const
+    std::optional<robot::RobotState> Reader::getRobotState(const armarx::armem::wm::Memory& memory) const
     {
         // clang-format off
         const armem::wm::ProviderSegment& providerSegment = memory
@@ -142,12 +142,12 @@ namespace armarx::armem::articulated_object
         // TODO(fabian.reister): check if 0 available
         const armem::wm::EntityInstance& instance = entitySnapshots.front().getInstance(0);
 
-        return convertRobotState(instance);
+        return robot::convertRobotState(instance);
     }
 
 
 
-    std::optional<RobotDescription> Reader::getRobotDescription(const armarx::armem::wm::Memory& memory) const
+    std::optional<robot::RobotDescription> Reader::getRobotDescription(const armarx::armem::wm::Memory& memory) const
     {
         // clang-format off
         const armem::wm::ProviderSegment& providerSegment = memory
@@ -173,7 +173,7 @@ namespace armarx::armem::articulated_object
         // TODO(fabian.reister): check if 0 available
         const armem::wm::EntityInstance& instance = entitySnapshots.front().getInstance(0);
 
-        return convertRobotDescription(instance);
+        return robot::convertRobotDescription(instance);
     }
 
 } // namespace armarx::armem::articulated_object
\ No newline at end of file
diff --git a/source/RobotAPI/libraries/armem_objects/client/articulated_object/Reader.h b/source/RobotAPI/libraries/armem_objects/client/articulated_object/Reader.h
index cd047cf6cc81dca29061f679537d787935ebfa75..2ad108d0f300109e42be4041b199655a46d18703 100644
--- a/source/RobotAPI/libraries/armem_objects/client/articulated_object/Reader.h
+++ b/source/RobotAPI/libraries/armem_objects/client/articulated_object/Reader.h
@@ -44,15 +44,15 @@ namespace armarx::armem::articulated_object
         std::optional<ArticulatedObject> get(const std::string& name, const armem::Time& timestamp) override;
         ArticulatedObject get(const ArticulatedObjectDescription& description, const armem::Time& timestamp) override;
 
-        std::optional<RobotState> queryState(const RobotDescription& description, const armem::Time& timestamp);
-        std::optional<RobotDescription> queryDescription(const std::string& name, const armem::Time& timestamp);
+        std::optional<robot::RobotState> queryState(const robot::RobotDescription& description, const armem::Time& timestamp);
+        std::optional<robot::RobotDescription> queryDescription(const std::string& name, const armem::Time& timestamp);
 
 
         // TODO(fabian.reister): register property defs
 
     protected:
-        std::optional<RobotState> getRobotState(const armarx::armem::wm::Memory& memory) const;
-        std::optional<RobotDescription> getRobotDescription(const armarx::armem::wm::Memory& memory) const;
+        std::optional<robot::RobotState> getRobotState(const armarx::armem::wm::Memory& memory) const;
+        std::optional<robot::RobotDescription> getRobotDescription(const armarx::armem::wm::Memory& memory) const;
 
     private:
 
diff --git a/source/RobotAPI/libraries/armem_objects/client/articulated_object/Writer.cpp b/source/RobotAPI/libraries/armem_objects/client/articulated_object/Writer.cpp
index cf057be299a48eb3e289a03886bd39c9a16046a3..53e5f925adc52aad31444071d7a7b6ded605c84f 100644
--- a/source/RobotAPI/libraries/armem_objects/client/articulated_object/Writer.cpp
+++ b/source/RobotAPI/libraries/armem_objects/client/articulated_object/Writer.cpp
@@ -7,8 +7,9 @@
 
 #include "RobotAPI/libraries/armem/core/MemoryID.h"
 #include "RobotAPI/libraries/armem_objects/aron_conversions.h"
-#include <RobotAPI/libraries/armem_objects/aron/RobotDescription.aron.generated.h>
-#include <RobotAPI/libraries/armem_objects/aron/Robot.aron.generated.h>
+#include "RobotAPI/libraries/armem_robot/aron_conversions.h"
+#include <RobotAPI/libraries/armem_robot/aron/RobotDescription.aron.generated.h>
+#include <RobotAPI/libraries/armem_robot/aron/Robot.aron.generated.h>
 #include <RobotAPI/libraries/armem/core/aron_conversions.h>
 
 
@@ -173,7 +174,7 @@ namespace armarx::armem::articulated_object
         update.entityID = entityID;
 
         arondto::Robot aronArticulatedObject;
-        toAron(aronArticulatedObject, obj);
+        robot::toAron(aronArticulatedObject, obj);
 
         const auto descriptionId = storeOrGetClass(obj);
 
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
index e2babe5079ff5a0e00d07317d163c089644db77b..51375ca0709d44c0c0407b7a9ac08025fa642237 100644
--- a/source/RobotAPI/libraries/armem_objects/server/articulated_object_class/Segment.cpp
+++ b/source/RobotAPI/libraries/armem_objects/server/articulated_object_class/Segment.cpp
@@ -15,9 +15,9 @@
 #include <RobotAPI/libraries/armem/client/query/query_fns.h>
 #include <RobotAPI/libraries/armem/server/MemoryToIceAdapter.h>
 
-#include <RobotAPI/libraries/armem_objects/aron/Robot.aron.generated.h>
-#include <RobotAPI/libraries/armem_objects/aron_conversions.h>
-#include "RobotAPI/libraries/armem_objects/articulated_object_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/aron_conversions.h>
 
 
 namespace armarx::armem::server::obj::articulated_object_class
@@ -61,7 +61,7 @@ namespace armarx::armem::server::obj::articulated_object_class
             for (const auto& [name, entity] :  provSeg.entities())
             {
                 const auto& entityInstance = entity.getLatestSnapshot().getInstance(0);
-                const auto description = articulated_object::convertRobotDescription(entityInstance);
+                const auto description = robot::convertRobotDescription(entityInstance);
 
                 if (not description)
                 {
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
index 9418254fff97b79fdca0c5abc55b53378c33ae8b..8932734ec4eb10ea99976786ec9e3504182f3f12 100644
--- a/source/RobotAPI/libraries/armem_objects/server/articulated_object_instance/Segment.cpp
+++ b/source/RobotAPI/libraries/armem_objects/server/articulated_object_instance/Segment.cpp
@@ -17,34 +17,16 @@
 #include <RobotAPI/libraries/armem/client/query/query_fns.h>
 #include <RobotAPI/libraries/armem/aron/MemoryID.aron.generated.h>
 
-#include <RobotAPI/libraries/armem_objects/aron/Robot.aron.generated.h>
-#include <RobotAPI/libraries/armem_objects/aron/RobotDescription.aron.generated.h>
-#include <RobotAPI/libraries/armem_objects/aron_conversions.h>
-#include <RobotAPI/libraries/armem_objects/articulated_object_conversions.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 simox::alg
-{
-    /// Get the keys of `map` in a vector.
-    template <class K, class V, template<class...> class MapT = std::unordered_map, class...Ts>
-    std::vector<K> get_keys2(const MapT<K, V, Ts...>& map)
-    {
-        std::vector<K> keys;
-        if constexpr(std::is_same_v<std::unordered_map<K, V, Ts...>, MapT<K, V, Ts...>>)
-        {
-            keys.reserve(map.size());
-        }
-        for (const auto& [k, v] : map)
-        {
-            keys.emplace_back(k);
-        }
-        return keys;
-    }
-}
-
 namespace armarx::armem::server::obj::articulated_object_instance
 {
 
@@ -94,7 +76,7 @@ namespace armarx::armem::server::obj::articulated_object_instance
             fromAron(aronDescriptionLink, descriptionLink);
 
             ARMARX_DEBUG << "Lookup key is " << descriptionLink;
-            
+
             // const auto keys = simox::alg::get_keys(knownObjectClasses);
             // ARMARX_DEBUG << "Known keys " << keys;
 
diff --git a/source/RobotAPI/libraries/armem_objects/types.h b/source/RobotAPI/libraries/armem_objects/types.h
index 5d2b4f76c83fa5ed3e823cc2d1528d941dcad6f5..cb348cd3a9731b36f2b18b7b7f366daa9b2b1f89 100644
--- a/source/RobotAPI/libraries/armem_objects/types.h
+++ b/source/RobotAPI/libraries/armem_objects/types.h
@@ -1,54 +1,13 @@
 #pragma once
 
-// these types should be core types
-
-#include <map>
 #include <vector>
-#include <filesystem>
-
-#include <Eigen/Geometry>
 
-#include <IceUtil/Time.h>
+#include <RobotAPI/libraries/armem_robot/types.h>
 
-#include <ArmarXCore/core/PackagePath.h>
-
-namespace armarx::armem
+namespace armarx::armem::articulated_object
 {
+    using ArticulatedObjectDescription = armarx::armem::robot::RobotDescription;
 
-    struct RobotDescription
-    {
-        // IceUtil::Time timestamp;
-
-        std::string name;
-        PackagePath xml{"", std::filesystem::path("")};
-
-    };
-
-
-    struct RobotState
-    {
-        IceUtil::Time timestamp;
-
-        Eigen::Affine3f globalPose;
-        std::map<std::string, float> jointMap;
-    };
-
-    struct Robot
-    {
-        RobotDescription description;
-        std::string instance;
-
-        RobotState config;
-
-        IceUtil::Time timestamp;
-    };
-
-    namespace articulated_object
-    {
-        using ArticulatedObjectDescription = RobotDescription;
-
-        using ArticulatedObject = Robot;
-        using ArticulatedObjects = std::vector<ArticulatedObject>;
-    }
-
-}  // namespace armarx::armem
\ No newline at end of file
+    using ArticulatedObject  = armarx::armem::robot::Robot;
+    using ArticulatedObjects = armarx::armem::robot::Robots;
+} // namespace armarx::armem::articulated_object
\ No newline at end of file
diff --git a/source/RobotAPI/libraries/armem_robot/CMakeLists.txt b/source/RobotAPI/libraries/armem_robot/CMakeLists.txt
new file mode 100644
index 0000000000000000000000000000000000000000..eb0c4fb7d37a4bb43830f224d3a81714f1175f39
--- /dev/null
+++ b/source/RobotAPI/libraries/armem_robot/CMakeLists.txt
@@ -0,0 +1,43 @@
+set(LIB_NAME    armem_robot)
+
+armarx_component_set_name("${LIB_NAME}")
+armarx_set_target("Library: ${LIB_NAME}")
+
+
+armarx_add_library(
+    LIBS
+        # ArmarXCore
+        ArmarXCore
+        # ArmarXGui
+        ArmarXGuiComponentPlugins
+        # RobotAPI
+        RobotAPI::ArViz
+        RobotAPI::ComponentPlugins
+        RobotAPI::Core
+        RobotAPI::armem
+    HEADERS
+        types.h
+
+        aron_conversions.h
+        robot_conversions.h
+
+    SOURCES
+        
+        aron_conversions.cpp
+        robot_conversions.cpp
+)
+
+
+armarx_enable_aron_file_generation_for_target(
+    TARGET_NAME
+        "${LIB_NAME}"
+    ARON_FILES
+        aron/RobotDescription.xml
+        aron/RobotState.xml
+        aron/Robot.xml
+)
+
+add_library(${PROJECT_NAME}::armem_robot ALIAS armem_robot)
+
+# add unit tests
+# add_subdirectory(test)
diff --git a/source/RobotAPI/libraries/armem_objects/aron/Robot.xml b/source/RobotAPI/libraries/armem_robot/aron/Robot.xml
similarity index 78%
rename from source/RobotAPI/libraries/armem_objects/aron/Robot.xml
rename to source/RobotAPI/libraries/armem_robot/aron/Robot.xml
index cc005ec0521c2b6f9dcb5334a14e61337ece5cf1..63e87ab3c4ba7193a8b7800ed4c24881c09e1b45 100644
--- a/source/RobotAPI/libraries/armem_objects/aron/Robot.xml
+++ b/source/RobotAPI/libraries/armem_robot/aron/Robot.xml
@@ -2,13 +2,13 @@
 <?xml version="1.0" encoding="UTF-8" ?>
 <AronTypeDefinition>
     <CodeIncludes>
-        <Include include="<RobotAPI/libraries/armem_objects/aron/RobotDescription.aron.generated.h>" />
-        <Include include="<RobotAPI/libraries/armem_objects/aron/RobotState.aron.generated.h>" />
+        <Include include="<RobotAPI/libraries/armem_robot/aron/RobotDescription.aron.generated.h>" />
+        <Include include="<RobotAPI/libraries/armem_robot/aron/RobotState.aron.generated.h>" />
         <Include include="<RobotAPI/libraries/armem/aron/MemoryID.aron.generated.h>" />
     </CodeIncludes>
      <AronIncludes>
         <!-- <Include include="<RobotAPI/libraries/armem_objects/aron/RobotDescription.xml>" /> -->
-        <Include include="<RobotAPI/libraries/armem_objects/aron/RobotState.xml>" />
+        <Include include="<RobotAPI/libraries/armem_robot/aron/RobotState.xml>" />
         <Include include="<RobotAPI/libraries/armem/aron/MemoryID.xml>" />
     </AronIncludes>
     <GenerateTypes>
diff --git a/source/RobotAPI/libraries/armem_objects/aron/RobotDescription.xml b/source/RobotAPI/libraries/armem_robot/aron/RobotDescription.xml
similarity index 100%
rename from source/RobotAPI/libraries/armem_objects/aron/RobotDescription.xml
rename to source/RobotAPI/libraries/armem_robot/aron/RobotDescription.xml
diff --git a/source/RobotAPI/libraries/armem_objects/aron/RobotState.xml b/source/RobotAPI/libraries/armem_robot/aron/RobotState.xml
similarity index 100%
rename from source/RobotAPI/libraries/armem_objects/aron/RobotState.xml
rename to source/RobotAPI/libraries/armem_robot/aron/RobotState.xml
diff --git a/source/RobotAPI/libraries/armem_robot/aron_conversions.cpp b/source/RobotAPI/libraries/armem_robot/aron_conversions.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..6a56d19f385af667974269c72c0de37af406da9f
--- /dev/null
+++ b/source/RobotAPI/libraries/armem_robot/aron_conversions.cpp
@@ -0,0 +1,66 @@
+#include "aron_conversions.h"
+
+#include <RobotAPI/libraries/aron/common/aron_conversions/core.h>
+#include <RobotAPI/libraries/aron/common/aron_conversions/stl.h>
+#include <RobotAPI/libraries/aron/common/aron_conversions/armarx.h>
+
+namespace armarx::armem::robot
+{
+
+    /* to be moved */
+    void fromAron(const long& dto, IceUtil::Time& time)
+    {
+        time = IceUtil::Time::microSeconds(dto);
+    }
+
+    void toAron(long& dto, const IceUtil::Time& time)
+    {
+        dto = time.toMicroSeconds();
+    }
+
+
+    /* Robot */
+
+    void fromAron(const arondto::Robot& dto, Robot& bo)
+    {
+        // fromAron(dto.description, bo.description);
+        fromAron(dto.state, bo.config);
+    }
+
+    void toAron(arondto::Robot& dto, const Robot& bo)
+    {
+        // toAron(dto.description, bo.description);
+        toAron(dto.state, bo.config);
+    }
+
+    /* RobotDescription */
+
+    void fromAron(const arondto::RobotDescription& dto, RobotDescription& bo)
+    {
+        aron::fromAron(dto.name, bo.name);
+        fromAron(dto.xml, bo.xml);
+    }
+
+    void toAron(arondto::RobotDescription& dto, const RobotDescription& bo)
+    {
+        aron::toAron(dto.name, bo.name);
+        toAron(dto.xml, bo.xml);
+    }
+
+    /* RobotState */
+
+    void fromAron(const arondto::RobotState& dto, RobotState& bo)
+    {
+        fromAron(dto.timestamp, bo.timestamp);
+        bo.globalPose.matrix() = dto.globalPose;
+        bo.jointMap            = dto.jointMap;
+    }
+
+    void toAron(arondto::RobotState& dto, const RobotState& bo)
+    {
+        toAron(dto.timestamp, bo.timestamp);
+        dto.globalPose = bo.globalPose.matrix();
+        dto.jointMap   = bo.jointMap;
+    }
+
+}  // namespace armarx::armem::robot
diff --git a/source/RobotAPI/libraries/armem_robot/aron_conversions.h b/source/RobotAPI/libraries/armem_robot/aron_conversions.h
new file mode 100644
index 0000000000000000000000000000000000000000..70e06ce8eedb7de9538f5249b3eedf797aec6060
--- /dev/null
+++ b/source/RobotAPI/libraries/armem_robot/aron_conversions.h
@@ -0,0 +1,25 @@
+#pragma once
+
+#include <RobotAPI/libraries/armem_robot/types.h>
+
+#include <RobotAPI/libraries/armem_robot/aron/RobotDescription.aron.generated.h>
+#include <RobotAPI/libraries/armem_robot/aron/RobotState.aron.generated.h>
+#include <RobotAPI/libraries/armem_robot/aron/Robot.aron.generated.h>
+
+namespace armarx::armem::robot
+{
+    // TODO move the following
+    void fromAron(const long& dto, IceUtil::Time& time);
+    void toAron(long& dto, const IceUtil::Time& time);
+    // end TODO
+
+    void fromAron(const arondto::Robot& dto, Robot& bo);
+    void toAron(arondto::Robot& dto, const Robot& bo);
+
+    void fromAron(const arondto::RobotDescription& dto, RobotDescription& bo);
+    void toAron(arondto::RobotDescription& dto, const RobotDescription& bo);
+
+    void fromAron(const arondto::RobotState& dto, RobotState& bo);
+    void toAron(arondto::RobotState& dto, const RobotState& bo);
+
+}  // namespace armarx::armem::robot
diff --git a/source/RobotAPI/libraries/armem_objects/articulated_object_conversions.cpp b/source/RobotAPI/libraries/armem_robot/robot_conversions.cpp
similarity index 85%
rename from source/RobotAPI/libraries/armem_objects/articulated_object_conversions.cpp
rename to source/RobotAPI/libraries/armem_robot/robot_conversions.cpp
index 03cac43717941e8da1a3a738d6c15aad1aa8987d..6c05e89e038c6f80f61e3e9c47f25bf8b2f1335f 100644
--- a/source/RobotAPI/libraries/armem_objects/articulated_object_conversions.cpp
+++ b/source/RobotAPI/libraries/armem_robot/robot_conversions.cpp
@@ -1,4 +1,4 @@
-#include "articulated_object_conversions.h"
+#include "robot_conversions.h"
 
 #include <filesystem>
 
@@ -7,14 +7,13 @@
 #include "RobotAPI/libraries/armem/core/workingmemory/EntityInstance.h"
 #include <RobotAPI/libraries/armem/core/aron_conversions.h>
 
-#include <RobotAPI/libraries/armem_objects/aron_conversions.h>
-
-#include <RobotAPI/libraries/ArmarXObjects/aron_conversions.h>
+#include <RobotAPI/libraries/armem_robot/aron/RobotDescription.aron.generated.h>
+#include <RobotAPI/libraries/armem_robot/aron_conversions.h>
 
 
 namespace fs = ::std::filesystem;
 
-namespace armarx::armem::articulated_object
+namespace armarx::armem::robot
 {
 
     std::optional<RobotDescription> convertRobotDescription(const armem::wm::EntityInstance& instance)
@@ -30,7 +29,6 @@ namespace armarx::armem::articulated_object
             return std::nullopt;
         }
 
-
         RobotDescription robotDescription
         {
             .name = "",
@@ -62,4 +60,4 @@ namespace armarx::armem::articulated_object
         return robotState;
     }
 
-}
+}  // namespace armarx::armem::robot
diff --git a/source/RobotAPI/libraries/armem_objects/articulated_object_conversions.h b/source/RobotAPI/libraries/armem_robot/robot_conversions.h
similarity index 89%
rename from source/RobotAPI/libraries/armem_objects/articulated_object_conversions.h
rename to source/RobotAPI/libraries/armem_robot/robot_conversions.h
index ab29163c347bca6cfa78aa1b10581955140a3fc1..3692ae048dacb94d2f24469f5265e998ab23fb34 100644
--- a/source/RobotAPI/libraries/armem_objects/articulated_object_conversions.h
+++ b/source/RobotAPI/libraries/armem_robot/robot_conversions.h
@@ -9,7 +9,7 @@ namespace armarx::armem::wm
     class EntityInstance;
 }
 
-namespace armarx::armem::articulated_object
+namespace armarx::armem::robot
 {
     std::optional<RobotDescription> convertRobotDescription(const armem::wm::EntityInstance& instance);
     std::optional<RobotState> convertRobotState(const armem::wm::EntityInstance& instance);
diff --git a/source/RobotAPI/libraries/armem_robot/types.h b/source/RobotAPI/libraries/armem_robot/types.h
new file mode 100644
index 0000000000000000000000000000000000000000..03c8ae1bfed67fb900f50905caeee18ca668a835
--- /dev/null
+++ b/source/RobotAPI/libraries/armem_robot/types.h
@@ -0,0 +1,45 @@
+#pragma once
+
+#include <map>
+#include <vector>
+#include <filesystem>
+
+#include <Eigen/Geometry>
+
+#include <IceUtil/Time.h>
+
+#include <ArmarXCore/core/PackagePath.h>
+
+namespace armarx::armem::robot
+{
+    struct RobotDescription
+    {
+        // IceUtil::Time timestamp;
+
+        std::string name;
+        PackagePath xml{"", std::filesystem::path("")};
+    };
+
+    struct RobotState
+    {
+        IceUtil::Time timestamp;
+
+        Eigen::Affine3f globalPose;
+        std::map<std::string, float> jointMap;
+    };
+
+    struct Robot
+    {
+        RobotDescription description;
+        std::string instance;
+
+        RobotState config;
+
+        IceUtil::Time timestamp;
+    };
+
+    using Robots = std::vector<Robot>;
+    using RobotDescriptions = std::vector<RobotDescription>;
+    using RobotStates = std::vector<RobotState>;
+
+}  // namespace armarx::armem::robot
\ No newline at end of file
diff --git a/source/RobotAPI/libraries/armem_robot_localization/CMakeLists.txt b/source/RobotAPI/libraries/armem_robot_localization/CMakeLists.txt
deleted file mode 100644
index 24caa9df3f797dc1e259f2709a995d50e1a584a7..0000000000000000000000000000000000000000
--- a/source/RobotAPI/libraries/armem_robot_localization/CMakeLists.txt
+++ /dev/null
@@ -1,42 +0,0 @@
-set(LIB_NAME armem_robot_localization)
-
-armarx_component_set_name("${LIB_NAME}")
-armarx_set_target("Library: ${LIB_NAME}")
-
-find_package(Eigen3 QUIET)
-armarx_build_if(Eigen3_FOUND "Eigen3 not available")
-
-armarx_add_library(
-    LIBS 
-        # ArmarX
-        ArmarXCore 
-        ArmarXCoreInterfaces
-        ArmarXGuiComponentPlugins
-        # This package
-        RobotAPICore 
-        RobotAPIInterfaces 
-        RobotAPI::libraries::armem
-        # System / External
-        Eigen3::Eigen
-    HEADERS
-        ./TransformInterfaces.h
-        ./TransformReader.h
-        ./TransformWriter.h
-        ./aron_conversions.h
-    SOURCES
-        ./TransformReader.cpp
-        ./TransformWriter.cpp
-        ./aron_conversions.cpp
-)
-
-
-armarx_enable_aron_file_generation_for_target(
-    TARGET_NAME
-        "${LIB_NAME}"
-    ARON_FILES
-        aron/TransformHeader.xml
-        aron/Transform.xml
-)
-
-
-add_library(RobotAPI::armem_robot_localization ALIAS armem_robot_localization)
diff --git a/source/RobotAPI/libraries/armem_robot_localization/TransformInterfaces.h b/source/RobotAPI/libraries/armem_robot_localization/TransformInterfaces.h
deleted file mode 100644
index 6962593814414267635efc425637266c7fbcd34a..0000000000000000000000000000000000000000
--- a/source/RobotAPI/libraries/armem_robot_localization/TransformInterfaces.h
+++ /dev/null
@@ -1,111 +0,0 @@
-/*
- * This file is part of ArmarX.
- *
- * ArmarX is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- *
- * ArmarX is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- *
- * @package    RobotAPI::ArmarXObjects::
- * @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 <Eigen/Geometry>
-
-#include <ArmarXCore/core/application/properties/PropertyDefinitionContainer.h>
-
-namespace armarx
-{
-
-    struct TransformHeader
-    {
-        std::string parentFrame;
-        std::string frame;
-
-        std::string agent;
-
-        std::int64_t timestamp; // [µs]
-    };
-
-    struct Transform
-    {
-        TransformHeader header;
-
-        Eigen::Affine3f transform = Eigen::Affine3f::Identity();
-    };
-
-    namespace armem
-    {
-
-        struct TransformResult
-        {
-            Transform transform;
-
-            enum class Status
-            {
-                Success,
-                ErrorLookupIntoFuture,
-                ErrorFrameNotAvailable
-            } status;
-
-            explicit operator bool() const
-            {
-                return status == Status::Success;
-            }
-
-            std::string errorMessage = "";
-        };
-
-        struct TransformQuery
-        {
-            TransformHeader header;
-
-            // bool exact;
-        };
-
-        class TransformInterface
-        {
-        public:
-            virtual ~TransformInterface() = default;
-
-            virtual void registerPropertyDefinitions(PropertyDefinitionsPtr& def) = 0;
-            virtual void connect() = 0;
-        };
-
-        class TransformReaderInterface : virtual public TransformInterface
-        {
-        public:
-            virtual ~TransformReaderInterface() = default;
-
-            virtual TransformResult
-            getGlobalPose(const std::string& agentName, const std::string& robotRootFrame,
-                          const std::int64_t& timestamp) const = 0;
-
-            virtual TransformResult
-            lookupTransform(const TransformQuery& query) const = 0;
-            // waitForTransform()
-        };
-
-        class TransformWriterInterface : virtual public TransformInterface
-        {
-        public:
-            ~TransformWriterInterface() override = default;
-
-            virtual bool commitTransform(const Transform& transform) = 0;
-        };
-
-    } // namespace armem
-
-} // namespace armarx
\ No newline at end of file
diff --git a/source/RobotAPI/libraries/armem_robot_localization/aron_conversions.cpp b/source/RobotAPI/libraries/armem_robot_localization/aron_conversions.cpp
deleted file mode 100644
index 40832ae90e2686d76a1d2256b8e427c2cafc88a2..0000000000000000000000000000000000000000
--- a/source/RobotAPI/libraries/armem_robot_localization/aron_conversions.cpp
+++ /dev/null
@@ -1,55 +0,0 @@
-#include "aron_conversions.h"
-
-// STL
-#include <string>
-
-// Ice
-#include <IceUtil/Time.h>
-
-// RobotAPI
-#include <RobotAPI/libraries/armem_robot_localization/TransformInterfaces.h>
-#include <RobotAPI/libraries/armem_robot_localization/aron/Transform.aron.generated.h>
-
-
-namespace armarx
-{
-
-    TransformHeader fromAron(const aron::TransformHeader& aronHeader)
-    {
-        TransformHeader header;
-
-        header.parentFrame = aronHeader.parentFrame;
-        header.frame = aronHeader.frame;
-        header.agent = aronHeader.agent;
-        header.timestamp = aronHeader.timestamp;
-
-        return header;
-    }
-
-
-    void fromAron(const aron::Transform& aronTransform, Transform& transform)
-    {
-        transform.header = fromAron(aronTransform.header);
-        transform.transform = aronTransform.transform;
-    }
-
-
-    aron::TransformHeader toAron(const TransformHeader& header)
-    {
-        aron::TransformHeader aronHeader;
-
-        aronHeader.parentFrame = header.parentFrame;
-        aronHeader.frame = header.frame;
-        aronHeader.agent = header.agent;
-        aronHeader.timestamp = header.timestamp;
-
-        return aronHeader;
-    }
-
-    void toAron(const Transform& transform, aron::Transform& aronTransform)
-    {
-        aronTransform.header = toAron(transform.header);
-        aronTransform.transform = transform.transform.matrix();
-    }
-
-}  // namespace armarx
diff --git a/source/RobotAPI/libraries/armem_robot_localization/aron_conversions.h b/source/RobotAPI/libraries/armem_robot_localization/aron_conversions.h
deleted file mode 100644
index 6a5379fe759f73fd03ad7e274a9a2211ba89d846..0000000000000000000000000000000000000000
--- a/source/RobotAPI/libraries/armem_robot_localization/aron_conversions.h
+++ /dev/null
@@ -1,16 +0,0 @@
-#pragma once
-
-
-namespace armarx
-{
-    struct Transform;
-
-    namespace aron
-    {
-        struct Transform;
-    } // namespace aron
-
-    void fromAron(const aron::Transform& aronTransform, Transform& transform);
-    void toAron(const Transform& transform, aron::Transform& aronTransform);
-
-}  // namespace armarx
\ No newline at end of file
diff --git a/source/RobotAPI/libraries/armem_robot_mapping/CMakeLists.txt b/source/RobotAPI/libraries/armem_robot_mapping/CMakeLists.txt
index 28e32f85f987b88246265ae4fc165c7bd68968de..145ced819b68db659a92e232747c645c24037ce5 100644
--- a/source/RobotAPI/libraries/armem_robot_mapping/CMakeLists.txt
+++ b/source/RobotAPI/libraries/armem_robot_mapping/CMakeLists.txt
@@ -9,7 +9,7 @@ armarx_add_library(
         ArmarXCore 
         # This package
         RobotAPICore 
-        RobotAPI::libraries::armem
+        RobotAPI::armem
         # System / External
         Eigen3::Eigen
     HEADERS
diff --git a/source/RobotAPI/libraries/armem_robot_state/CMakeLists.txt b/source/RobotAPI/libraries/armem_robot_state/CMakeLists.txt
new file mode 100644
index 0000000000000000000000000000000000000000..595bae1a9be089978e681f4dce4dfbd53b8e5ecc
--- /dev/null
+++ b/source/RobotAPI/libraries/armem_robot_state/CMakeLists.txt
@@ -0,0 +1,68 @@
+set(LIB_NAME armem_robot_state)
+
+armarx_component_set_name("${LIB_NAME}")
+armarx_set_target("Library: ${LIB_NAME}")
+
+find_package(Eigen3 QUIET)
+armarx_build_if(Eigen3_FOUND "Eigen3 not available")
+
+armarx_add_library(
+    LIBS 
+        # ArmarX
+        ArmarXCore 
+        ArmarXCoreInterfaces
+        ArmarXGuiComponentPlugins
+        # This package
+        RobotAPICore 
+        RobotAPIInterfaces 
+        RobotAPI::armem
+        RobotAPI::armem_robot
+        # System / External
+        Eigen3::Eigen
+        aroncommon
+    HEADERS
+        
+        ./client/localization/interfaces.h
+        ./client/localization/TransformReader.h
+        ./client/localization/TransformWriter.h
+
+        ./server/common/Visu.h
+
+        ./server/localization/Segment.h
+        # ./server/localization/Visu.h
+
+        ./server/proprioception/Segment.h
+        # ./server/proprioception/Visu.h
+
+        ./server/description/Segment.h
+
+
+        ./aron_conversions.h
+    SOURCES
+        ./client/localization/TransformReader.cpp
+        ./client/localization/TransformWriter.cpp
+
+        ./server/common/Visu.cpp
+
+        ./server/localization/Segment.cpp
+        # ./server/localization/Visu.cpp
+
+        ./server/proprioception/Segment.cpp
+        # ./server/proprioception/Visu.cpp
+
+        ./server/description/Segment.cpp
+
+        ./aron_conversions.cpp
+)
+
+
+armarx_enable_aron_file_generation_for_target(
+    TARGET_NAME
+        "${LIB_NAME}"
+    ARON_FILES
+        aron/TransformHeader.xml
+        aron/Transform.xml
+)
+
+
+add_library(RobotAPI::armem_robot_state ALIAS armem_robot_state)
diff --git a/source/RobotAPI/libraries/armem_robot_localization/aron/Transform.xml b/source/RobotAPI/libraries/armem_robot_state/aron/Transform.xml
similarity index 60%
rename from source/RobotAPI/libraries/armem_robot_localization/aron/Transform.xml
rename to source/RobotAPI/libraries/armem_robot_state/aron/Transform.xml
index afdd4fafdbd74b08c19bbb98cbc1dd326ee6244e..02ebe91b35094809953de6cfd0252c8a2048cf98 100644
--- a/source/RobotAPI/libraries/armem_robot_localization/aron/Transform.xml
+++ b/source/RobotAPI/libraries/armem_robot_state/aron/Transform.xml
@@ -3,15 +3,15 @@
 <AronTypeDefinition>
     <CodeIncludes>
         <Include include="<Eigen/Core>" />
-        <Include include="<RobotAPI/libraries/armem_robot_localization/aron/TransformHeader.aron.generated.h>" />
+        <Include include="<RobotAPI/libraries/armem_robot_state/aron/TransformHeader.aron.generated.h>" />
     </CodeIncludes>
     <AronIncludes>
-        <Include include="<RobotAPI/libraries/armem_robot_localization/aron/TransformHeader.xml>" />
+        <Include include="<RobotAPI/libraries/armem_robot_state/aron/TransformHeader.xml>" />
     </AronIncludes>
     <GenerateTypes>
-        <Object name="armarx::aron::Transform">
+        <Object name="armarx::armem::arondto::Transform">
             <ObjectChild key='header'>
-                <armarx::aron::TransformHeader />
+                <armarx::armem::arondto::TransformHeader />
             </ObjectChild>
             <ObjectChild key='transform'>
                 <Pose />
diff --git a/source/RobotAPI/libraries/armem_robot_localization/aron/TransformHeader.xml b/source/RobotAPI/libraries/armem_robot_state/aron/TransformHeader.xml
similarity index 91%
rename from source/RobotAPI/libraries/armem_robot_localization/aron/TransformHeader.xml
rename to source/RobotAPI/libraries/armem_robot_state/aron/TransformHeader.xml
index 85add64bec4441b3e203a2d798322629521ea4fe..c6bd5b94f93fa10e0638c75d17e8dbed0ad5bc60 100644
--- a/source/RobotAPI/libraries/armem_robot_localization/aron/TransformHeader.xml
+++ b/source/RobotAPI/libraries/armem_robot_state/aron/TransformHeader.xml
@@ -5,7 +5,7 @@
         <Include include="<Eigen/Core>" />
     </CodeIncludes>
     <GenerateTypes>
-        <Object name="armarx::aron::TransformHeader">
+        <Object name="armarx::armem::arondto::TransformHeader">
             <ObjectChild key='parentFrame'>
                 <string />
             </ObjectChild>
diff --git a/source/RobotAPI/libraries/armem_robot_state/aron_conversions.cpp b/source/RobotAPI/libraries/armem_robot_state/aron_conversions.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..fbca6711774de97e3d137901338fde776e6f2285
--- /dev/null
+++ b/source/RobotAPI/libraries/armem_robot_state/aron_conversions.cpp
@@ -0,0 +1,47 @@
+#include "aron_conversions.h"
+
+// STL
+#include <string>
+
+// Ice
+#include <IceUtil/Time.h>
+
+// RobotAPI
+#include <RobotAPI/libraries/armem_robot_state/aron/Transform.aron.generated.h>
+
+#include <RobotAPI/libraries/aron/common/aron_conversions.h>
+
+#include "RobotAPI/libraries/armem_robot_state/types.h"
+
+namespace armarx::armem
+{
+
+    void fromAron(const arondto::Transform& dto, robot_state::Transform& bo)
+    {
+        fromAron(dto.header, bo.header);
+        aron::fromAron(dto.transform, bo.transform);
+    }
+
+    void toAron(arondto::Transform& dto, const robot_state::Transform& bo)
+    {
+        toAron(dto.header, bo.header);
+        aron::toAron(dto.transform, bo.transform);
+    }
+
+    void toAron(arondto::TransformHeader& dto, const robot_state::TransformHeader& bo)
+    {
+        aron::toAron(dto.parentFrame, bo.parentFrame);
+        aron::toAron(dto.frame, bo.frame);
+        aron::toAron(dto.agent, bo.agent);
+        aron::toAron(dto.timestamp, bo.timestamp);
+    }
+
+    void fromAron(const arondto::TransformHeader& dto, robot_state::TransformHeader& bo)
+    {
+        aron::fromAron(dto.parentFrame, bo.parentFrame);
+        aron::fromAron(dto.frame, bo.frame);
+        aron::fromAron(dto.agent, bo.agent);
+        aron::fromAron(dto.timestamp, bo.timestamp);
+    }
+
+}  // namespace armarx::armem
diff --git a/source/RobotAPI/libraries/armem_robot_state/aron_conversions.h b/source/RobotAPI/libraries/armem_robot_state/aron_conversions.h
new file mode 100644
index 0000000000000000000000000000000000000000..d266717dc729e8a09e4f96c3469eb96af38f347d
--- /dev/null
+++ b/source/RobotAPI/libraries/armem_robot_state/aron_conversions.h
@@ -0,0 +1,24 @@
+#pragma once
+
+
+namespace armarx::armem
+{
+    namespace robot_state
+    {
+        struct Transform;
+        struct TransformHeader;
+    } // namespace robot_state
+
+    namespace arondto
+    {
+        struct Transform;
+        struct TransformHeader;
+    } // namespace arondto
+
+    void fromAron(const arondto::Transform& dto, robot_state::Transform& bo);
+    void toAron(arondto::Transform& dto, const robot_state::Transform& bo);
+
+    void fromAron(const arondto::TransformHeader& dto, robot_state::TransformHeader& bo);
+    void toAron(arondto::TransformHeader& dto, const robot_state::TransformHeader& bo);
+
+}  // namespace armarx::armem
\ No newline at end of file
diff --git a/source/RobotAPI/libraries/armem_robot_localization/TransformReader.cpp b/source/RobotAPI/libraries/armem_robot_state/client/localization/TransformReader.cpp
similarity index 94%
rename from source/RobotAPI/libraries/armem_robot_localization/TransformReader.cpp
rename to source/RobotAPI/libraries/armem_robot_state/client/localization/TransformReader.cpp
index c3b24c4895328e951bc4950339639200206a9daf..f82bed097130b9b51608ce022424ad99d1481046 100644
--- a/source/RobotAPI/libraries/armem_robot_localization/TransformReader.cpp
+++ b/source/RobotAPI/libraries/armem_robot_state/client/localization/TransformReader.cpp
@@ -53,10 +53,10 @@
 #include <RobotAPI/libraries/armem/server/MemoryRemoteGui.h>
 #include <RobotAPI/libraries/aron/core/navigator/type/NavigatorFactory.h>
 #include <RobotAPI/libraries/core/FramedPose.h>
-#include <RobotAPI/libraries/armem_robot_localization/aron_conversions.h>
-#include <RobotAPI/libraries/armem_robot_localization/aron/Transform.aron.generated.h>
+#include <RobotAPI/libraries/armem_robot_state/aron_conversions.h>
+#include <RobotAPI/libraries/armem_robot_state/aron/Transform.aron.generated.h>
 
-namespace armarx::armem
+namespace armarx::armem::client::robot_state::localization
 {
 
     TransformReader::TransformReader(ManagedIceObject& component) : MemoryConnector(component) {}
@@ -202,21 +202,21 @@ namespace armarx::armem
         return chain;
     }
 
-    inline Transform convertEntityToTransform(const armem::wm::EntityInstance& item)
+    inline ::armarx::armem::robot_state::Transform convertEntityToTransform(const armem::wm::EntityInstance& item)
     {
-        aron::Transform aronTransform;
+        arondto::Transform aronTransform;
         aronTransform.fromAron(item.data());
 
-        Transform transform;
+        ::armarx::armem::robot_state::Transform transform;
         fromAron(aronTransform, transform);
 
         return transform;
     }
 
-    decltype(auto) findFirstElementAfter(const std::vector<Transform>& transforms,
+    auto findFirstElementAfter(const std::vector<::armarx::armem::robot_state::Transform>& transforms,
                                          const int64_t timestamp)
     {
-        auto timestampBeyond = [timestamp](const Transform & transform)
+        auto timestampBeyond = [timestamp](const ::armarx::armem::robot_state::Transform & transform)
         {
             return transform.header.timestamp > timestamp;
         };
@@ -225,7 +225,7 @@ namespace armarx::armem
         return poseNextIt;
     }
 
-    Eigen::Affine3f interpolateTransform(const std::vector<Transform>& queue, int64_t timestamp)
+    Eigen::Affine3f interpolateTransform(const std::vector<::armarx::armem::robot_state::Transform>& queue, int64_t timestamp)
     {
         ARMARX_TRACE;
 
@@ -288,7 +288,7 @@ namespace armarx::armem
         // }
 
 
-        std::vector<Transform> transforms;
+        std::vector<::armarx::armem::robot_state::Transform> transforms;
         transforms.reserve(entity.history().size());
 
         const auto entitySnapshots = simox::alg::get_values(entity.history());
diff --git a/source/RobotAPI/libraries/armem_robot_localization/TransformReader.h b/source/RobotAPI/libraries/armem_robot_state/client/localization/TransformReader.h
similarity index 86%
rename from source/RobotAPI/libraries/armem_robot_localization/TransformReader.h
rename to source/RobotAPI/libraries/armem_robot_state/client/localization/TransformReader.h
index 4107ed61fcc108737049f6fb063929012575a898..0bad1527d3240e5c0e3f53dbd76f323d67785d03 100644
--- a/source/RobotAPI/libraries/armem_robot_localization/TransformReader.h
+++ b/source/RobotAPI/libraries/armem_robot_state/client/localization/TransformReader.h
@@ -25,9 +25,9 @@
 #include <RobotAPI/libraries/armem/client/Reader.h>
 #include <RobotAPI/libraries/armem/client/MemoryConnector.h>
 
-#include "TransformInterfaces.h"
+#include "interfaces.h"
 
-namespace armarx::armem
+namespace armarx::armem::client::robot_state::localization
 {
     /**
     * @defgroup Component-ExampleClient ExampleClient
@@ -41,7 +41,7 @@ namespace armarx::armem
     * Detailed description of class ExampleClient.
     */
     class TransformReader :
-        virtual public ::armarx::armem::TransformReaderInterface,
+        virtual public TransformReaderInterface,
         virtual public ::armarx::armem::MemoryConnector
     {
     public:
@@ -54,6 +54,7 @@ namespace armarx::armem
         TransformResult getGlobalPose(const std::string& agentName,
                                       const std::string& robotRootFrame,
                                       const std::int64_t& timestamp) const override;
+                                      
         TransformResult lookupTransform(const TransformQuery& query) const override;
 
         void registerPropertyDefinitions(::armarx::PropertyDefinitionsPtr& def) override;
@@ -71,7 +72,11 @@ namespace armarx::armem
                 const std::vector<std::string>& tfChain,
                 const std::string& agent, const std::int64_t& timestamp) const;
 
-        Eigen::Affine3f obtainTransform(const std::string& entityName, const armem::wm::ProviderSegment& agentProviderSegment, int64_t timestamp) const;
+        Eigen::Affine3f obtainTransform(
+            const std::string& entityName, 
+            const armem::wm::ProviderSegment& agentProviderSegment, 
+            int64_t timestamp) 
+        const;
 
 
         armem::client::Reader memoryReader;
@@ -86,4 +91,4 @@ namespace armarx::armem
 
         const std::string propertyPrefix = "mem.localization.read.";
     };
-} // namespace armarx::armem
+}  // namespace armarx::armem::client::robot_state::localization
diff --git a/source/RobotAPI/libraries/armem_robot_localization/TransformWriter.cpp b/source/RobotAPI/libraries/armem_robot_state/client/localization/TransformWriter.cpp
similarity index 90%
rename from source/RobotAPI/libraries/armem_robot_localization/TransformWriter.cpp
rename to source/RobotAPI/libraries/armem_robot_state/client/localization/TransformWriter.cpp
index 7a9bcd1f4825c6d775201fb862e5a21f0af70cbf..02f567ef0691796c1afd6b69bb2085e861c3022c 100644
--- a/source/RobotAPI/libraries/armem_robot_localization/TransformWriter.cpp
+++ b/source/RobotAPI/libraries/armem_robot_state/client/localization/TransformWriter.cpp
@@ -44,12 +44,11 @@
 #include <RobotAPI/libraries/aron/core/navigator/type/NavigatorFactory.h>
 #include <RobotAPI/libraries/core/FramedPose.h>
 
-#include <RobotAPI/libraries/armem_robot_localization/aron/Transform.aron.generated.h>
+#include <RobotAPI/libraries/armem_robot_state/aron/Transform.aron.generated.h>
+#include <RobotAPI/libraries/armem_robot_state/aron_conversions.h>
 
-#include "aron_conversions.h"
 
-
-namespace armarx::armem
+namespace armarx::armem::client::robot_state::localization
 {
 
     TransformWriter::TransformWriter(ManagedIceObject& component) : MemoryConnector(component) {}
@@ -88,7 +87,7 @@ namespace armarx::armem
         memoryWriter.setWritingMemory(result.proxy);
     }
 
-    bool TransformWriter::commitTransform(const Transform& transform)
+    bool TransformWriter::commitTransform(const ::armarx::armem::robot_state::Transform& transform)
     {
         std::lock_guard g{memoryWriterMutex};
 
@@ -114,8 +113,8 @@ namespace armarx::armem
         armem::EntityUpdate update;
         update.entityID    = entityID;
 
-        aron::Transform aronTransform;
-        toAron(transform, aronTransform);
+        arondto::Transform aronTransform;
+        toAron(aronTransform, transform);
 
         update.instancesData = {aronTransform.toAron()};
         update.timeCreated = IceUtil::Time::microSeconds(aronTransform.header.timestamp);
@@ -139,4 +138,4 @@ namespace armarx::armem
     }
 
 
-} // namespace armarx::armem
+}  // namespace armarx::armem::client::robot_state::localization
diff --git a/source/RobotAPI/libraries/armem_robot_localization/TransformWriter.h b/source/RobotAPI/libraries/armem_robot_state/client/localization/TransformWriter.h
similarity index 88%
rename from source/RobotAPI/libraries/armem_robot_localization/TransformWriter.h
rename to source/RobotAPI/libraries/armem_robot_state/client/localization/TransformWriter.h
index 7d1ee2acbac7739ea73f92ca2a5205068cf0e5fa..1ea4a3f159da6237965fd5e274d17c9cfeac6561 100644
--- a/source/RobotAPI/libraries/armem_robot_localization/TransformWriter.h
+++ b/source/RobotAPI/libraries/armem_robot_state/client/localization/TransformWriter.h
@@ -27,9 +27,9 @@
 #include <RobotAPI/libraries/armem/client/Writer.h>
 #include <RobotAPI/libraries/armem/client/MemoryConnector.h>
 
-#include "TransformInterfaces.h"
+#include "interfaces.h"
 
-namespace armarx::armem
+namespace armarx::armem::client::robot_state::localization
 {
 
     /**
@@ -44,7 +44,7 @@ namespace armarx::armem
     * Detailed description of class ExampleClient.
     */
     class TransformWriter :
-        virtual public ::armarx::armem::TransformWriterInterface,
+        virtual public TransformWriterInterface,
         virtual public ::armarx::armem::MemoryConnector
     {
     public:
@@ -59,7 +59,7 @@ namespace armarx::armem
         /// to be called in Component::addPropertyDefinitions
         void registerPropertyDefinitions(armarx::PropertyDefinitionsPtr& def) override;
 
-        bool commitTransform(const Transform& transform) override;
+        bool commitTransform(const ::armarx::armem::robot_state::Transform& transform) override;
 
         const std::string& getPropertyPrefix() const override;
 
@@ -77,4 +77,5 @@ namespace armarx::armem
 
         const std::string propertyPrefix = "mem.localization.write.";
     };
-} // namespace armarx::armem
+
+}  // namespace armarx::armem::client::robot_state::localization
diff --git a/source/RobotAPI/libraries/armem_robot_state/client/localization/interfaces.h b/source/RobotAPI/libraries/armem_robot_state/client/localization/interfaces.h
new file mode 100644
index 0000000000000000000000000000000000000000..a1989d6f6c3289db0f731cebcfede34556153821
--- /dev/null
+++ b/source/RobotAPI/libraries/armem_robot_state/client/localization/interfaces.h
@@ -0,0 +1,86 @@
+/*
+ * 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::
+ * @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 <Eigen/Geometry>
+
+#include <ArmarXCore/core/application/properties/PropertyDefinitionContainer.h>
+
+#include <RobotAPI/libraries/armem_robot_state/types.h>
+
+namespace armarx::armem::client::robot_state::localization
+{
+    struct TransformResult
+    {
+        ::armarx::armem::robot_state::Transform transform;
+
+        enum class Status
+        {
+            Success,
+            ErrorLookupIntoFuture,
+            ErrorFrameNotAvailable
+        } status;
+
+        explicit operator bool() const { return status == Status::Success; }
+
+        std::string errorMessage = "";
+    };
+
+    struct TransformQuery
+    {
+        ::armarx::armem::robot_state::TransformHeader header;
+
+        // bool exact;
+    };
+
+    class TransformInterface
+    {
+      public:
+        virtual ~TransformInterface() = default;
+
+        virtual void registerPropertyDefinitions(PropertyDefinitionsPtr &def) = 0;
+        virtual void connect()                                                = 0;
+    };
+
+    class TransformReaderInterface : virtual public TransformInterface
+    {
+      public:
+        virtual ~TransformReaderInterface() = default;
+
+        virtual TransformResult getGlobalPose(const std::string &agentName,
+                                              const std::string &robotRootFrame,
+                                              const std::int64_t &timestamp) const = 0;
+
+        virtual TransformResult lookupTransform(const TransformQuery &query) const = 0;
+        // waitForTransform()
+    };
+
+    class TransformWriterInterface : virtual public TransformInterface
+    {
+      public:
+        ~TransformWriterInterface() override = default;
+
+        virtual bool commitTransform(const ::armarx::armem::robot_state::Transform &transform) = 0;
+    };
+
+} // namespace armarx::armem::client::robot_state::localization
\ No newline at end of file
diff --git a/source/RobotAPI/libraries/armem_robot_state/server/common/Visu.cpp b/source/RobotAPI/libraries/armem_robot_state/server/common/Visu.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..2171928dc1c7675b5dc2596b70560feac98ee3a0
--- /dev/null
+++ b/source/RobotAPI/libraries/armem_robot_state/server/common/Visu.cpp
@@ -0,0 +1,232 @@
+#include "Visu.h"
+#include "ArmarXCore/core/logging/Logging.h"
+#include "ArmarXCore/core/time/CycleUtil.h"
+
+#include <Eigen/src/Geometry/Transform.h>
+#include <IceUtil/Time.h>
+#include <algorithm>
+
+#include <SimoxUtility/math/pose.h>
+
+#include <ArmarXCore/core/time/TimeUtil.h>
+
+#include <RobotAPI/libraries/ArmarXObjects/ObjectFinder.h>
+
+#include "RobotAPI/libraries/armem/core/Time.h"
+
+#include "../localization/Segment.h"
+#include "../proprioception/Segment.h"
+
+namespace armarx::armem::server::robot_state
+{
+
+    void Visu::defineProperties(armarx::PropertyDefinitionsPtr defs, const std::string& prefix)
+    {
+        defs->optional(p.enabled, prefix + "enabled",
+                       "Enable or disable visualization of objects.");
+        defs->optional(p.frequencyHz, prefix + "frequenzyHz",
+                       "Frequency of visualization.");
+    }
+
+    void Visu::visualizeRobots(
+            viz::Layer& layer,
+            const robot::Robots& robots
+        ) const
+        {
+           
+        ARMARX_INFO << "Entering visualizeObjects";
+        const auto visualizeRobot = [&](const robot::Robot & robot)
+        {
+
+            const auto xmlPath = robot.description.xml.serialize();
+
+            // clang-format off
+            auto robotVisu = viz::Robot(robot.description.name)
+                         //  .file(xmlPath.package, xmlPath.path)
+                         .file("ArmarXObjects", "./data/ArmarXObjects/Environment/mobile-kitchen/dishwasher-only/dishwasher.xml")
+                         .joints(robot.config.jointMap)
+                         .pose(robot.config.globalPose);
+
+            robotVisu.useFullModel();
+            // clang-format on
+
+            layer.add(robotVisu);
+        };
+
+        std::for_each(robots.begin(), robots.end(), visualizeRobot);
+        ARMARX_INFO << "Done visualizeRobots";
+
+    }
+
+    void Visu::init()
+    {
+        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 robot::RobotDescriptions& robotDescriptions, 
+                            const std::unordered_map<std::string, Eigen::Affine3f>& globalRobotPoseMap, 
+                            const std::unordered_map<std::string, std::map<std::string, float>>& robotJointPositionMap)
+    {
+
+        robot::Robots robots;
+
+        for(const auto& robotDescription: robotDescriptions)
+        {
+            const auto& robotName = robotDescription.name;
+
+            const auto& globalPose = globalRobotPoseMap.find(robotName);
+            if(globalPose == globalRobotPoseMap.end())
+            {
+                ARMARX_WARNING << "No global pose for robot '" << robotName << "'";
+                continue;
+            }
+            
+            const auto& jointMap = robotJointPositionMap.find(robotName);
+            if(jointMap == robotJointPositionMap.end())
+            {
+                ARMARX_WARNING << "No joint positions for robot '" << robotName << "'";
+                continue;
+            }
+
+            // TODO(fabian.reister): based on data
+            const armem::Time timestamp = IceUtil::Time::now(); 
+
+            robots.emplace_back(
+                robot::Robot{
+                    .description = robotDescription,
+                    .instance = "", // TODO(fabian.reister): set this properly
+                    .config = {
+                        .timestamp = timestamp,
+                        .globalPose = globalPose->second,
+                        .jointMap = jointMap->second
+                    },
+                    .timestamp = timestamp,
+                }
+            );
+        }
+
+        return robots;
+
+    }
+
+
+    void Visu::visualizeRun()
+    {
+
+        // TODO need another core segment
+        const robot::RobotDescriptions robotDescriptions 
+        {
+            {
+                robot::RobotDescription{
+                    .name = "Armar6",
+                    .xml = {"Armar6RT", "./Armar6RT/robotmodel/Armar6-SH/Armar6-SH.xml"}
+                }
+            }
+        };
+
+        CycleUtil cycle(static_cast<int>(1000 / p.frequencyHz));
+        while (updateTask && not updateTask->isStopped())
+        {
+            {
+                // std::scoped_lock lock(visuMutex);
+                ARMARX_IMPORTANT << "Update task";
+
+                if (p.enabled)
+                {
+                    // TIMING_START(Visu);
+
+                    const auto globalRobotPoseMap = localizationSegment.getRobotGlobalPoses();
+                    const auto robotJointPositionMap = proprioceptionSegment.getRobotJointPositions();
+
+                    // we need all 3 informations:
+                    // - robot description
+                    // - global pose
+                    // - joint positions
+                    // => this is nothing but a armem::Robot
+
+                    const robot::Robots robots = combine(robotDescriptions, globalRobotPoseMap, robotJointPositionMap);
+                    viz::Layer layer = arviz.layer("Robots");
+
+                    ARMARX_INFO << "visualizing robots";
+                    visualizeRobots(layer, robots);
+
+                    ARMARX_INFO << "Committing robots";
+
+                    arviz.commit({layer});
+
+                    ARMARX_INFO << "Done committing";
+
+
+                    // TIMING_END_STREAM(Visu, ARMARX_VERBOSE);
+
+                    // if (debugObserver)
+                    // {
+                    //     debugObserver->setDebugChannel(getName(),
+                    //     {
+                    //         { "t Visualize [ms]", new Variant(Visu.toMilliSecondsDouble()) },
+                    //     });
+                    // }
+                }
+            }
+            cycle.waitForCycleDuration();
+        }
+    }
+
+
+
+}  // namespace armarx::armem::server::robot_state
diff --git a/source/RobotAPI/libraries/armem_robot_state/server/common/Visu.h b/source/RobotAPI/libraries/armem_robot_state/server/common/Visu.h
new file mode 100644
index 0000000000000000000000000000000000000000..4297b9ccfd865805ea99b972c5db540872a73702
--- /dev/null
+++ b/source/RobotAPI/libraries/armem_robot_state/server/common/Visu.h
@@ -0,0 +1,115 @@
+/*
+ * 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 <ArmarXCore/core/logging/Logging.h>
+#include <ArmarXCore/core/services/tasks/TaskUtil.h>
+
+// #include <ArmarXGui/libraries/RemoteGui/Client/Widgets.h>
+
+#include <RobotAPI/components/ArViz/Client/Client.h>
+
+#include <RobotAPI/libraries/armem_objects/types.h>
+
+
+namespace armarx
+{
+    class ObjectFinder;
+}
+
+namespace armarx::armem::server::robot_state
+{
+    namespace localization
+    {
+        class Segment;
+    }
+
+    namespace proprioception
+    {
+        class Segment;
+    }
+
+
+    /**
+     * @brief Models decay of object localizations by decreasing the confidence
+     * the longer the object was not localized.
+     */
+    class Visu : public armarx::Logging
+    {
+    public:
+
+        Visu(const viz::Client& arviz, 
+            const proprioception::Segment& proprioceptionSegment,
+            const localization::Segment& localizationSegment)
+        : arviz(arviz), 
+          proprioceptionSegment(proprioceptionSegment), 
+          localizationSegment(localizationSegment) 
+        {}
+
+        void defineProperties(armarx::PropertyDefinitionsPtr defs, const std::string& prefix = "visu.");
+
+        void init();
+
+    protected:
+
+        void visualizeRobots(
+            viz::Layer& layer,
+            const robot::Robots& robots
+        ) const;
+
+
+    private:
+        viz::Client arviz;
+
+        const proprioception::Segment& proprioceptionSegment;
+        const localization::Segment& localizationSegment;
+
+        struct Properties
+        {
+            bool enabled = true;
+            float frequencyHz = 25;
+        } p;
+
+
+        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
new file mode 100644
index 0000000000000000000000000000000000000000..20c3a1ec239367eb7606e1ca0e43f12895fdfff0
--- /dev/null
+++ b/source/RobotAPI/libraries/armem_robot_state/server/description/Segment.cpp
@@ -0,0 +1,199 @@
+#include "Segment.h"
+
+#include <RobotAPI/libraries/armem_robot/aron/RobotDescription.aron.generated.h>
+#include <sstream>
+
+#include "ArmarXCore/core/logging/Logging.h"
+#include <ArmarXCore/core/time/TimeUtil.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/client/Writer.h>
+#include <RobotAPI/libraries/armem/client/query/Builder.h>
+#include <RobotAPI/libraries/armem/client/query/query_fns.h>
+#include <RobotAPI/libraries/armem/core/aron_conversions.h>
+#include <RobotAPI/libraries/armem/core/workingmemory/Visitor.h>
+#include <RobotAPI/libraries/armem/server/MemoryToIceAdapter.h>
+
+#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>
+
+namespace armarx::armem::server::robot_state::description
+{
+
+    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.coreSegment,
+                       prefix + "CoreSegment",
+                       "Name of the robot description 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);
+
+        ARMARX_INFO << "Adding core segment '" << p.coreSegment << "'";
+
+        coreSegment = &iceMemory.workingMemory->addCoreSegment(
+                p.coreSegment, arondto::RobotDescription::toInitialAronType());
+        coreSegment->setMaxHistorySize(p.maxHistorySize);
+    }
+
+    void Segment::connect(const viz::Client &arviz, const RobotUnitInterfacePrx &robotUnitPrx)
+    {
+        // this->visu = std::make_unique<Visu>(arviz, *this);
+        robotUnit = robotUnitPrx;
+    }
+
+    void Segment::storeRobotDescription(const robot::RobotDescription& robotDescription)
+    {
+        const Time now = TimeUtil::GetTime();
+
+        const MemoryID providerID = coreSegment->id().withProviderSegmentName(robotDescription.name);
+        coreSegment->addProviderSegment(providerID.providerSegmentName);
+
+        EntityUpdate update; 
+        // update.entityID = providerID.withEntityName(info.id().str());
+        update.timeArrived = update.timeCreated = update.timeSent = now;
+
+        arondto::RobotDescription dto;
+        robot::toAron(dto, robotDescription);
+        update.instancesData =
+        {
+            dto.toAron()
+        };
+
+        Commit commit;
+        commit.updates.push_back(std::move(update));
+        
+        iceMemory.commit(commit);
+    }
+
+    void Segment::updateRobotDescription()
+    {
+        auto kinematicUnit = robotUnit->getKinematicUnit();
+
+        const auto robotName = kinematicUnit->getRobotName();
+
+        const robot::RobotDescription robotDescription{
+                .name = kinematicUnit->getRobotName(),
+                .xml  = {"Armar6RT", kinematicUnit->getRobotFilename()}};
+        
+        storeRobotDescription(robotDescription);
+    }
+
+    Segment::RobotDescriptionMap Segment::getRobotDescriptions() const
+    {
+        RobotDescriptionMap robotDescriptions;
+
+        for (const auto &[_, provSeg] : iceMemory.workingMemory->getCoreSegment(p.coreSegment))
+            {
+                for (const auto &[name, entity] : provSeg.entities())
+                    {
+                        const auto &entityInstance = entity.getLatestSnapshot().getInstance(0);
+                        const auto description     = robot::convertRobotDescription(entityInstance);
+
+                        if (not description)
+                            {
+                                ARMARX_WARNING << "Could not convert entity instance to "
+                                                  "'RobotDescription'";
+                                continue;
+                            }
+
+                        ARMARX_INFO << "Key is " << armem::MemoryID(entity.id());
+
+                        robotDescriptions.emplace(description->name, *description);
+                    }
+            }
+
+        ARMARX_IMPORTANT << "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
new file mode 100644
index 0000000000000000000000000000000000000000..8bb9ec017b006c1ad9dc5334688d04aa472e9ee1
--- /dev/null
+++ b/source/RobotAPI/libraries/armem_robot_state/server/description/Segment.h
@@ -0,0 +1,114 @@
+/*
+ * 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 <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 "RobotAPI/libraries/armem/core/MemoryID.h"
+#include "RobotAPI/libraries/armem_objects/types.h"
+
+namespace armarx::armem
+{
+    namespace server
+    {
+        class MemoryToIceAdapter;
+    }
+
+    namespace wm
+    {
+        class CoreSegment;
+    }
+}  // namespace armarx::armem
+
+
+namespace armarx::armem::server::robot_state::description
+{
+    class Visu;
+
+    class Segment : public armarx::Logging
+    {
+    public:
+        Segment(server::MemoryToIceAdapter& iceMemory,
+                std::mutex& memoryMutex);
+
+        virtual ~Segment();
+
+        void connect(const viz::Client& arviz, const RobotUnitInterfacePrx& robotUnitPrx);
+
+        void defineProperties(armarx::PropertyDefinitionsPtr defs, const std::string& prefix = "");
+
+        void init();
+
+        /// mapping "robot name" -> "robot description"
+        using RobotDescriptionMap = std::unordered_map<std::string, robot::RobotDescription>;
+
+        RobotDescriptionMap getRobotDescriptions() const;
+
+    private:
+
+        void storeRobotDescription(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::localization
diff --git a/source/RobotAPI/libraries/armem_robot_state/server/localization/Segment.cpp b/source/RobotAPI/libraries/armem_robot_state/server/localization/Segment.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..180b9aece6de2e1ef39e5c58e5202d0999f05e72
--- /dev/null
+++ b/source/RobotAPI/libraries/armem_robot_state/server/localization/Segment.cpp
@@ -0,0 +1,139 @@
+#include "Segment.h"
+
+#include <RobotAPI/libraries/armem_robot_state/aron/Transform.aron.generated.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/aron/Robot.aron.generated.h>
+#include <RobotAPI/libraries/armem_robot/aron_conversions.h>
+
+
+namespace armarx::armem::server::robot_state::localization
+{
+
+    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.coreSegment, 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);
+
+        ARMARX_INFO << "Adding core segment '" <<  p.coreSegment << "'";
+
+        coreSegment = &iceMemory.workingMemory->addCoreSegment(p.coreSegment, arondto::Transform::toInitialAronType());
+        coreSegment->setMaxHistorySize(p.maxHistorySize);
+    }
+
+    void Segment::connect(viz::Client arviz)
+    {
+        // this->visu = std::make_unique<Visu>(arviz, *this);
+    }
+
+    std::unordered_map<std::string, Eigen::Affine3f> Segment::getRobotGlobalPoses() const
+    {
+        std::unordered_map<std::string, Eigen::Affine3f> robotGlobalPoses;
+
+        // TODO(fabian.reister): implement
+
+        return robotGlobalPoses;
+    }
+
+
+
+    // 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
new file mode 100644
index 0000000000000000000000000000000000000000..465ba2d8bba58bb7408f06abf13120b0a6727bc2
--- /dev/null
+++ b/source/RobotAPI/libraries/armem_robot_state/server/localization/Segment.h
@@ -0,0 +1,104 @@
+/*
+ * 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"
+
+namespace armarx::armem
+{
+    namespace server
+    {
+        class MemoryToIceAdapter;
+    }
+
+    namespace wm
+    {
+        class CoreSegment;
+    }
+}  // namespace armarx::armem
+
+
+namespace armarx::armem::server::robot_state::localization
+{
+    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<std::string, Eigen::Affine3f> getRobotGlobalPoses() const;
+
+    private:
+
+        server::MemoryToIceAdapter& iceMemory;
+        wm::CoreSegment* coreSegment = nullptr;
+        std::mutex& memoryMutex;
+
+        struct Properties
+        {
+            std::string coreSegment = "Localization";
+            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::localization
diff --git a/source/RobotAPI/libraries/armem_robot_state/server/localization/Visu.cpp b/source/RobotAPI/libraries/armem_robot_state/server/localization/Visu.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..29bd6d31db98b2779369858717aa87c5a72711aa
--- /dev/null
+++ b/source/RobotAPI/libraries/armem_robot_state/server/localization/Visu.cpp
@@ -0,0 +1,172 @@
+#include "Visu.h"
+#include "ArmarXCore/core/logging/Logging.h"
+#include "ArmarXCore/core/time/CycleUtil.h"
+
+#include <algorithm>
+
+#include <SimoxUtility/math/pose.h>
+
+#include <ArmarXCore/core/time/TimeUtil.h>
+
+#include <RobotAPI/libraries/ArmarXObjects/ObjectFinder.h>
+
+#include "Segment.h"
+
+namespace armarx::armem::server::obj::articulated_object_instance
+{
+
+    void Visu::defineProperties(armarx::PropertyDefinitionsPtr defs, const std::string& prefix)
+    {
+        defs->optional(p.enabled, prefix + "enabled",
+                       "Enable or disable visualization of objects.");
+        defs->optional(p.frequencyHz, prefix + "frequenzyHz",
+                       "Frequency of visualization.");
+    }
+
+
+    viz::Layer Visu::visualizeProvider(
+        const std::string& providerName,
+        const armarx::armem::articulated_object::ArticulatedObjects& objects) const
+    {
+        viz::Layer layer = arviz.layer(providerName);
+
+        visualizeRobots(layer, objects);
+
+        return layer;
+    }
+
+
+    void Visu::visualizeR(viz::Layer& layer, const armarx::armem::articulated_object::ArticulatedObjects& objects) const
+    {
+        ARMARX_INFO << "Entering visualizeObjects";
+        const auto visualizeObject = [&](const armarx::armem::articulated_object::ArticulatedObject & obj)
+        {
+
+            const auto xmlPath = obj.description.xml.serialize();
+
+            // clang-format off
+            auto robot = viz::Robot(obj.description.name)
+                         //  .file(xmlPath.package, xmlPath.path)
+                         .file("ArmarXObjects", "./data/ArmarXObjects/Environment/mobile-kitchen/dishwasher-only/dishwasher.xml")
+                         .joints(obj.config.jointMap)
+                         .pose(obj.config.globalPose);
+
+            robot.useFullModel();
+            // clang-format on
+
+            layer.add(robot);
+        };
+
+        std::for_each(objects.begin(), objects.end(), visualizeObject);
+        ARMARX_INFO << "Done visualizeObjects";
+
+    }
+
+    void Visu::init()
+    {
+        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();
+    // }
+
+
+    void Visu::visualizeRun()
+    {
+        CycleUtil cycle(static_cast<int>(1000 / p.frequencyHz));
+        while (updateTask && not updateTask->isStopped())
+        {
+            {
+                // std::scoped_lock lock(visuMutex);
+                ARMARX_IMPORTANT << "Update task";
+
+                if (p.enabled)
+                {
+                    // TIMING_START(Visu);
+
+                    const auto articulatedObjects = segment.getArticulatedObjects();
+
+                    ARMARX_INFO << "Found " << articulatedObjects.size() << " articulated objects";
+
+                    viz::Layer layer = arviz.layer("ArticulatedObjectInstances");
+
+                    ARMARX_INFO << "visualizing objects";
+                    visualizeObjects(layer, articulatedObjects);
+
+                    ARMARX_INFO << "Committing objects";
+
+                    arviz.commit({layer});
+
+                    ARMARX_INFO << "Done committing";
+
+
+                    // TIMING_END_STREAM(Visu, ARMARX_VERBOSE);
+
+                    // if (debugObserver)
+                    // {
+                    //     debugObserver->setDebugChannel(getName(),
+                    //     {
+                    //         { "t Visualize [ms]", new Variant(Visu.toMilliSecondsDouble()) },
+                    //     });
+                    // }
+                }
+            }
+            cycle.waitForCycleDuration();
+        }
+    }
+
+
+
+}  // namespace armarx::armem::server::obj::articulated_object_instance
diff --git a/source/RobotAPI/libraries/armem_robot_state/server/localization/Visu.h b/source/RobotAPI/libraries/armem_robot_state/server/localization/Visu.h
new file mode 100644
index 0000000000000000000000000000000000000000..54aea5e09f0d3000596c83d2eb8ffbafcbf8b81e
--- /dev/null
+++ b/source/RobotAPI/libraries/armem_robot_state/server/localization/Visu.h
@@ -0,0 +1,101 @@
+/*
+ * 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 <ArmarXCore/core/logging/Logging.h>
+#include <ArmarXCore/core/services/tasks/TaskUtil.h>
+
+// #include <ArmarXGui/libraries/RemoteGui/Client/Widgets.h>
+
+#include <RobotAPI/components/ArViz/Client/Client.h>
+
+#include <RobotAPI/libraries/armem_objects/types.h>
+
+
+namespace armarx
+{
+    class ObjectFinder;
+}
+namespace armarx::armem::server::obj::articulated_object_instance
+{
+    class Segment;
+
+    /**
+     * @brief Models decay of object localizations by decreasing the confidence
+     * the longer the object was not localized.
+     */
+    class Visu : public armarx::Logging
+    {
+    public:
+
+        Visu(const viz::Client& arviz, const Segment& segment): arviz(arviz), segment(segment) {}
+
+        void defineProperties(armarx::PropertyDefinitionsPtr defs, const std::string& prefix = "visu.");
+
+        void init();
+
+    protected:
+        viz::Layer visualizeProvider(
+            const std::string& providerName,
+            const armarx::armem::articulated_object::ArticulatedObjects& objects
+        ) const;
+
+        void visualizeObjects(
+            viz::Layer& layer,
+            const armarx::armem::articulated_object::ArticulatedObjects& objects
+        ) const;
+
+
+    private:
+        viz::Client arviz;
+        const Segment& segment;
+
+        struct Properties
+        {
+            bool enabled = true;
+            float frequencyHz = 25;
+        } p;
+
+
+        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::obj::articulated_object_instance
diff --git a/source/RobotAPI/libraries/armem_robot_state/server/proprioception/Segment.cpp b/source/RobotAPI/libraries/armem_robot_state/server/proprioception/Segment.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..efedbbe42eeaf740a87a43dff5c86364a8797a27
--- /dev/null
+++ b/source/RobotAPI/libraries/armem_robot_state/server/proprioception/Segment.cpp
@@ -0,0 +1,165 @@
+#include "Segment.h"
+
+#include <mutex>
+#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_objects/aron_conversions.h>
+
+
+namespace armarx::armem::server::robot_state::proprioception
+{
+
+    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.coreSegment, 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);
+
+        ARMARX_INFO << "Adding core segment '" <<  p.coreSegment << "'";
+        coreSegment = &iceMemory.workingMemory->addCoreSegment(p.coreSegment); // TODO , arondto::Robot::toInitialAronType());
+        coreSegment->setMaxHistorySize(p.maxHistorySize);
+    }
+
+    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;
+
+        {
+            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;
+            }
+        }
+        
+        robotUnitProviderID.memoryName = iceMemory.workingMemory->id().memoryName;
+        robotUnitProviderID.coreSegmentName = p.coreSegment;
+        robotUnitProviderID.providerSegmentName = providerSegmentName;
+
+        // this->visu = std::make_unique<Visu>(arviz, *this);
+    }
+
+    std::unordered_map<std::string, std::map<std::string, float>> Segment::getRobotJointPositions() const
+    {
+        std::unordered_map<std::string, std::map<std::string, float>> jointMap;
+        
+        // for (const auto& [provName, provSeg] : iceMemory.workingMemory->getCoreSegment(p.coreClassSegmentName))
+        // {
+        //     for (const auto& [entityName, 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);
+        //     }
+        // }
+
+        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
new file mode 100644
index 0000000000000000000000000000000000000000..09bae1077a76757fcce175ec34dff212f6c4d2f3
--- /dev/null
+++ b/source/RobotAPI/libraries/armem_robot_state/server/proprioception/Segment.h
@@ -0,0 +1,110 @@
+/*
+ * 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 <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 "RobotAPI/libraries/armem/core/MemoryID.h"
+#include "RobotAPI/libraries/armem_objects/types.h"
+
+namespace armarx::armem
+{
+    namespace server
+    {
+        class MemoryToIceAdapter;
+    }
+
+    namespace wm
+    {
+        class CoreSegment;
+    }
+}  // namespace armarx::armem
+
+
+namespace armarx::armem::server::robot_state::proprioception
+{
+    class Visu;
+
+    class Segment : public armarx::Logging
+    {
+    public:
+        Segment(server::MemoryToIceAdapter& iceMemory, std::mutex& memoryMutex);
+
+        virtual ~Segment();
+
+        void connect(viz::Client arviz, RobotUnitInterfacePrx robotUnitPrx);
+
+        void defineProperties(armarx::PropertyDefinitionsPtr defs, const std::string& prefix = "");
+
+        void init();
+
+        std::unordered_map<std::string, std::map<std::string, float>> getRobotJointPositions() const;
+
+        const armem::MemoryID& getRobotUnitProviderID() const;
+
+    private:
+
+        server::MemoryToIceAdapter& iceMemory;
+        wm::CoreSegment* coreSegment = nullptr;
+        std::mutex& memoryMutex;
+
+        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);
+        // };
+
+    };
+
+}  // namespace armarx::armem::server::robot_state::proprioception
diff --git a/source/RobotAPI/libraries/armem_robot_state/types.h b/source/RobotAPI/libraries/armem_robot_state/types.h
new file mode 100644
index 0000000000000000000000000000000000000000..3edaee80f8696d844f1f5c90b299c0a54c503f93
--- /dev/null
+++ b/source/RobotAPI/libraries/armem_robot_state/types.h
@@ -0,0 +1,26 @@
+#pragma once
+
+#include <Eigen/Geometry>
+
+namespace armarx::armem::robot_state
+{
+    struct TransformHeader
+    {
+        std::string parentFrame;
+        std::string frame;
+
+        std::string agent;
+
+        std::int64_t timestamp; // [µs]
+    };
+
+    struct Transform
+    {
+        TransformHeader header;
+
+        Eigen::Affine3f transform = Eigen::Affine3f::Identity();
+
+        EIGEN_MAKE_ALIGNED_OPERATOR_NEW
+    };
+
+}  // namespace armarx::armem::robot_state
diff --git a/source/RobotAPI/libraries/aron/common/CMakeLists.txt b/source/RobotAPI/libraries/aron/common/CMakeLists.txt
index 6fc9fa463f3f037c38f6e0142c934678775d9aaa..ec6c74d9e669f9effb5825afda1cc1645aadf547 100644
--- a/source/RobotAPI/libraries/aron/common/CMakeLists.txt
+++ b/source/RobotAPI/libraries/aron/common/CMakeLists.txt
@@ -17,12 +17,14 @@ armarx_add_library(
         aron_conversions/armarx.h
         aron_conversions/simox.h
         aron_conversions/stl.h
+        aron_conversions/eigen.h
 
     SOURCES
         aron_conversions/core.cpp
         aron_conversions/armarx.cpp
         aron_conversions/simox.cpp
         aron_conversions/stl.cpp
+        aron_conversions/eigen.cpp
 )
 
 
diff --git a/source/RobotAPI/libraries/aron/common/aron_conversions.h b/source/RobotAPI/libraries/aron/common/aron_conversions.h
index 2f96d0285b9fb4dbd96abdb92c12fe9518ee88b6..b771ef362aaf0a886aaabcc19027e74a9dfbeb9b 100644
--- a/source/RobotAPI/libraries/aron/common/aron_conversions.h
+++ b/source/RobotAPI/libraries/aron/common/aron_conversions.h
@@ -5,3 +5,4 @@
 #include "aron_conversions/armarx.h"
 #include "aron_conversions/simox.h"
 #include "aron_conversions/stl.h"
+#include "aron_conversions/eigen.h"
diff --git a/source/RobotAPI/libraries/aron/common/aron_conversions/eigen.cpp b/source/RobotAPI/libraries/aron/common/aron_conversions/eigen.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..0bf14ec90439e50a4869234b81449adaf068d173
--- /dev/null
+++ b/source/RobotAPI/libraries/aron/common/aron_conversions/eigen.cpp
@@ -0,0 +1,17 @@
+#include "eigen.h"
+
+namespace armarx::aron
+{
+    using AronPose = Eigen::Matrix<float, 4, 4>;
+
+    void fromAron(const AronPose& dto, Eigen::Affine3f& bo)
+    {
+        bo.matrix() = dto;
+    }
+
+    void toAron(AronPose& dto, const Eigen::Affine3f& bo)
+    {
+        dto = bo.matrix();
+    }
+
+}  // namespace armarx::aron
diff --git a/source/RobotAPI/libraries/aron/common/aron_conversions/eigen.h b/source/RobotAPI/libraries/aron/common/aron_conversions/eigen.h
new file mode 100644
index 0000000000000000000000000000000000000000..3f091dbfc40ee8e91b8d2922687273269ce790a8
--- /dev/null
+++ b/source/RobotAPI/libraries/aron/common/aron_conversions/eigen.h
@@ -0,0 +1,12 @@
+#pragma once
+
+#include <Eigen/Geometry>
+
+namespace armarx::aron
+{
+    using AronPose = Eigen::Matrix<float, 4, 4>;
+
+    void fromAron(const AronPose& dto, Eigen::Affine3f& bo);
+    void toAron(AronPose& dto, const Eigen::Affine3f& bo);
+
+}  // namespace armarx