diff --git a/source/RobotAPI/components/RobotHealth/RobotHealth.cpp b/source/RobotAPI/components/RobotHealth/RobotHealth.cpp
index 0b67edc552c9bd77aa0f8ca78d95c2f2a5659282..8c14b9de7a9d80bcf2b09d45ae3253b94a2c8b5b 100644
--- a/source/RobotAPI/components/RobotHealth/RobotHealth.cpp
+++ b/source/RobotAPI/components/RobotHealth/RobotHealth.cpp
@@ -35,6 +35,7 @@
 
 #include <ArmarXCore/core/time/ice_conversions.h>
 #include <ArmarXCore/util/CPPUtility/trace.h>
+#include <mutex>
 #include <optional>
 
 namespace armarx
@@ -71,17 +72,15 @@ namespace armarx
     void
     RobotHealth::monitorHealthUpdateTaskClb()
     {
-        std::shared_lock lock(updateMutex);
+        const std::scoped_lock lock(updateMutex);
 
         ARMARX_TRACE;
         auto now = armarx::core::time::DateTime::Now();
 
-        for (size_t i = 0; i < updateEntries.size(); i++)
+        for (auto & e : updateEntries)
         {
             ARMARX_TRACE;
-            UpdateEntry& e = updateEntries.at(i);
-
-            std::unique_lock elock(e.mutex);
+            const std::scoped_lock elock(e.mutex);
 
             if (!e.enabled)
             {
@@ -129,12 +128,10 @@ namespace armarx
 
 
         // get aggregated status
-        for (size_t i = 0; i < updateEntries.size(); i++)
+        for (auto & e : updateEntries)
         {
             ARMARX_TRACE;
-            UpdateEntry& e = updateEntries.at(i);
-
-            std::shared_lock elock(e.mutex);
+             std::scoped_lock elock(e.mutex);
 
             // trim history
             while (e.history.size() > 20)
@@ -218,11 +215,11 @@ namespace armarx
     {
         ARMARX_TRACE;
 
-        for (size_t i = 0; i < updateEntries.size(); i++)
+        for (auto & updateEntrie : updateEntries)
         {
-            if (updateEntries.at(i).name == name)
+            if (updateEntrie.name == name)
             {
-                return &updateEntries.at(i);
+                return &updateEntrie;
             }
         }
 
@@ -234,11 +231,11 @@ namespace armarx
     {
         ARMARX_TRACE;
         {
-            for (size_t i = 0; i < updateEntries.size(); i++)
+            for (auto & updateEntrie : updateEntries)
             {
-                if (updateEntries.at(i).name == name)
+                if (updateEntrie.name == name)
                 {
-                    return {false, updateEntries.at(i)};
+                    return {false, updateEntrie};
                 }
             }
         }
@@ -254,12 +251,12 @@ namespace armarx
     RobotHealth::signUp(const RobotHealthHeartbeatArgs& args, const Ice::Current& current)
     {
         ARMARX_TRACE;
-        std::unique_lock lockU(updateMutex);
+        std::scoped_lock lockU(updateMutex);
 
         auto e = findOrCreateUpdateEntry(args.identifier);
 
         {
-            std::unique_lock lock(e.second.mutex);
+            std::scoped_lock lock(e.second.mutex);
 
             if (e.first)
             {
@@ -294,7 +291,7 @@ namespace armarx
 
         // We hold a reference to 'o' which is an element in a vector.
         // If we don't lock until the end of this scope, the vector size might change and 'o' will be invalidated. 
-        std::shared_lock lockU(updateMutex);  
+        std::scoped_lock lockU(updateMutex);  
         auto* const entry = findUpdateEntry(identifier);
 
         if (entry == nullptr)
@@ -306,7 +303,7 @@ namespace armarx
 
         ARMARX_CHECK_NOT_NULL(entry);
 
-        std::unique_lock lock(entry->mutex);
+        std::scoped_lock lock(entry->mutex);
 
         if (not entry->enabled)
         {
@@ -325,21 +322,18 @@ namespace armarx
     }
 
     void
-    armarx::RobotHealth::unregister(const std::string& componentName, const Ice::Current&)
+    armarx::RobotHealth::unregister(const std::string& identifier, const Ice::Current&)
     {
         ARMARX_TRACE;
-        std::shared_lock lock(updateMutex);
+        std::scoped_lock lock(updateMutex);
 
         bool found = false;
         {
-            std::shared_lock lock(updateMutex);
-
-            for (size_t i = 0; i < updateEntries.size(); i++)
+            for (auto & e : updateEntries)
             {
-                auto& e = updateEntries.at(i);
-                if (e.name == componentName)
+                if (e.name == identifier)
                 {
-                    std::unique_lock elock(e.mutex);
+                    std::scoped_lock elock(e.mutex);
                     e.required = false;
                     e.enabled = false;
                     found = true;
@@ -351,11 +345,11 @@ namespace armarx
 
         if (found)
         {
-            ARMARX_INFO << "Component " << componentName << " disabled from heartbeat";
+            ARMARX_INFO << "Component " << identifier << " disabled from heartbeat";
         }
         else
         {
-            ARMARX_INFO << "Could not unregister component " << componentName << ". Not found.";
+            ARMARX_INFO << "Could not unregister component " << identifier << ". Not found.";
         }
 
         updateRequiredElements();
@@ -366,7 +360,7 @@ namespace armarx
                      const std::vector<std::string>& tags,
                      const Ice::Current& current)
     {
-        std::shared_lock lock(updateMutex);
+        std::scoped_lock lock(updateMutex);
 
         // add newly requested tags
         for(const auto& tag : tags)
@@ -429,7 +423,7 @@ namespace armarx
                        const std::vector<std::string>& tags,
                        const Ice::Current& current)
     {
-        std::shared_lock lock(updateMutex);
+        std::scoped_lock lock(updateMutex);
 
         // update the required tags list / map
         for(const auto& tag : tags)
@@ -443,7 +437,7 @@ namespace armarx
     void
     armarx::RobotHealth::resetRequiredTags(const Ice::Current& current)
     {
-        std::shared_lock lock(updateMutex);
+        std::scoped_lock lock(updateMutex);
 
         // treat the special provider (see onInitComponent()) appropriately  
         ARMARX_CHECK(tagsPerRequester.count(PROPERTY_REQUESTER_ID) > 0);
@@ -457,7 +451,7 @@ namespace armarx
     RobotHealthInfo
     RobotHealth::getSummary(const Ice::Current&)
     {
-        std::shared_lock lock(updateMutex);
+        std::scoped_lock lock(updateMutex);
 
         ARMARX_TRACE;
         RobotHealthInfo ret;
diff --git a/source/RobotAPI/components/RobotHealth/RobotHealth.h b/source/RobotAPI/components/RobotHealth/RobotHealth.h
index a27f864e8f639983650ece96ac8d101f709b8618..1e45f31116382a9761b879eaffb80375541fdaf7 100644
--- a/source/RobotAPI/components/RobotHealth/RobotHealth.h
+++ b/source/RobotAPI/components/RobotHealth/RobotHealth.h
@@ -70,6 +70,29 @@ namespace armarx
             return "RobotHealth";
         }
 
+        // RobotHealthInterface interface
+        void signUp(const RobotHealthHeartbeatArgs& args, const Ice::Current& current) override;
+        void unregister(const std::string& identifier, const Ice::Current&) override;
+        
+
+        void addRequiredTags(const std::string& requesterIdentifier,
+                     const std::vector<std::string>& tags,
+                     const Ice::Current& current) override;
+        void removeRequiredTags(const std::string& requesterIdentifier,
+                       const std::vector<std::string>& tags,
+                       const Ice::Current& current) override;
+        void resetRequiredTags(const Ice::Current& current) override;
+
+
+        void heartbeat(const std::string& identifier,
+                       const core::time::dto::DateTime& referenceTime,
+                       const Ice::Current& current) override;
+
+        std::string getTopicName(const Ice::Current& current) override;
+
+        RobotHealthInfo getSummary(const Ice::Current& current) override;
+
+
     protected:
         /**
          * @see armarx::ManagedIceObject::onInitComponent()
@@ -116,7 +139,7 @@ namespace armarx
             bool required = false;
             bool enabled = false;
 
-            mutable std::shared_mutex mutex;
+            mutable std::mutex mutex;
 
             struct TimeInfo
             {
@@ -140,36 +163,13 @@ namespace armarx
 
         void reportDebugObserver();
 
-        // RobotHealthInterface interface
-    public:
-        void signUp(const RobotHealthHeartbeatArgs& args, const Ice::Current& current) override;
-        void unregister(const std::string& identifier, const Ice::Current&) override;
-        
-
-        void addRequiredTags(const std::string& requesterIdentifier,
-                     const std::vector<std::string>& tags,
-                     const Ice::Current& current) override;
-        void removeRequiredTags(const std::string& requesterIdentifier,
-                       const std::vector<std::string>& tags,
-                       const Ice::Current& current) override;
-        void resetRequiredTags(const Ice::Current& current) override;
-
-
-        void heartbeat(const std::string& identifier,
-                       const core::time::dto::DateTime& referenceTime,
-                       const Ice::Current& current) override;
-
-        std::string getTopicName(const Ice::Current& current) override;
-
-        // RobotHealthComponentInterface interface
-    public:
-        RobotHealthInfo getSummary(const Ice::Current& current) override;
-
-    private:
+   
         void updateRequiredElements();
         std::set<std::string> requestedTags() const;
 
-        mutable std::shared_mutex updateMutex;
+        // Mutex to restrict access to all interface / public methods. This ensures that all requests are
+        // handled sequentially. 
+        mutable std::mutex updateMutex;
 
         std::deque<UpdateEntry> updateEntries;
 
diff --git a/source/RobotAPI/components/units/RobotUnit/Units/KinematicSubUnit.cpp b/source/RobotAPI/components/units/RobotUnit/Units/KinematicSubUnit.cpp
index 1b7f92ef951ef1b1223489b3e80fb09a84efa981..87ce13bc529cbc44c114171337e43192b83bd503 100644
--- a/source/RobotAPI/components/units/RobotUnit/Units/KinematicSubUnit.cpp
+++ b/source/RobotAPI/components/units/RobotUnit/Units/KinematicSubUnit.cpp
@@ -67,8 +67,7 @@ armarx::KinematicSubUnit::setupData(
     auto nodes = robot->getRobotNodes();
     for (auto& node : nodes)
     {
-        if ((node->isRotationalJoint() || node->isTranslationalJoint()) &&
-            !devs.count(node->getName()))
+        if (node->isJoint() && !devs.count(node->getName()))
         {
             sensorLessJoints.push_back(node);
         }
diff --git a/source/RobotAPI/drivers/HokuyoLaserUnit/HokuyoLaserUnit.cpp b/source/RobotAPI/drivers/HokuyoLaserUnit/HokuyoLaserUnit.cpp
index 2a1f02718bb8b1fa9465445086238a4e04ba92dd..a89af6168a5f66f366a4df3a36b59c01906a0695 100644
--- a/source/RobotAPI/drivers/HokuyoLaserUnit/HokuyoLaserUnit.cpp
+++ b/source/RobotAPI/drivers/HokuyoLaserUnit/HokuyoLaserUnit.cpp
@@ -24,6 +24,7 @@
 
 #include <SimoxUtility/algorithm/string/string_tools.h>
 
+#include "ArmarXCore/core/time/Clock.h"
 #include <ArmarXCore/core/time/DateTime.h>
 #include <ArmarXCore/core/time/Duration.h>
 #include <ArmarXCore/core/time/ice_conversions.h>
@@ -45,9 +46,9 @@ HokuyoLaserUnit::onInitComponent()
     offeringTopicFromProperty("RobotHealthTopicName");
     offeringTopicFromProperty("DebugObserverName");
 
-    topicName = getProperty<std::string>("LaserScannerTopicName").getValue();
-    offeringTopic(topicName);
-    ARMARX_INFO << "Going to report on topic " << topicName;
+    laserScannerListenerProxyName = getProperty<std::string>("LaserScannerListenerName").getValue();
+    usingProxyFromProperty("LaserScannerListenerName");
+    ARMARX_INFO << "Going to report to listener " << laserScannerListenerProxyName;
     updatePeriod = getProperty<int>("UpdatePeriod").getValue();
     angleOffset = getProperty<float>("AngleOffset").getValue();
 
@@ -92,7 +93,7 @@ HokuyoLaserUnit::onConnectComponent()
 {
     ARMARX_TRACE;
 
-    topic = getTopic<LaserScannerUnitListenerPrx>(topicName);
+    getProxyFromProperty(listenerPrx, "LaserScannerListenerName");
     debugObserver = getTopic<DebugObserverInterfacePrx>(
         getProperty<std::string>("DebugObserverName").getValue());
 
@@ -133,7 +134,7 @@ HokuyoLaserUnit::onConnectComponent()
         info.stepSize = (info.maxAngle - info.minAngle) / (maxStep - minStep);
         device.lengthData.resize(lengthDataSize);
 
-        device.scanTopic = topic;
+        device.listenerPrx = listenerPrx;
         device.robotHealthPlugin = heartbeat;
         device.debugObserver = debugObserver;
 
@@ -181,7 +182,7 @@ HokuyoLaserUnit::createPropertyDefinitions()
 std::string
 HokuyoLaserUnit::getReportTopicName(const Ice::Current&) const
 {
-    return topicName;
+    return laserScannerListenerProxyName;
 }
 
 LaserScannerInfoSeq
@@ -230,6 +231,8 @@ HokuyoLaserScanDevice::run()
     ARMARX_TRACE;
     while (!task->isStopped())
     {
+        ARMARX_INFO << deactivateSpam() << "Running update loop for laserscanner device " << ip;
+
         IceUtil::Time time_start = TimeUtil::GetTime();
 
         if (errorCounter > 10)
@@ -272,15 +275,16 @@ HokuyoLaserScanDevice::run()
 
             errorCounter = 0;
 
-            if (scanTopic)
+            if (listenerPrx)
             {
-                scanTopic->reportSensorValues(ip, frame, scan, now);
+
+                listenerPrx->reportSensorValues(ip, frame, scan, now);
             }
             else
             {
-                ARMARX_WARNING << "No scan topic available: IP: " << ip << ", Port: " << port;
+                ARMARX_WARNING << "No proxy available: IP: " << ip << ", Port: " << port;
             }
-            IceUtil::Time time_topicSensor = TimeUtil::GetTime();
+            IceUtil::Time time_proxyReport = TimeUtil::GetTime();
 
             if (robotHealthPlugin != nullptr)
             {
@@ -302,10 +306,10 @@ HokuyoLaserScanDevice::run()
                 new Variant((time_measure - time_start).toMilliSecondsDouble());
             durations["update_ms"] =
                 new Variant((time_update - time_measure).toMilliSecondsDouble());
-            durations["topic_sensor_ms"] =
-                new Variant((time_topicSensor - time_update).toMilliSecondsDouble());
+            durations["proxy_report_ms"] =
+                new Variant((time_proxyReport - time_update).toMilliSecondsDouble());
             durations["topic_health_ms"] =
-                new Variant((time_topicHeartbeat - time_topicSensor).toMilliSecondsDouble());
+                new Variant((time_topicHeartbeat - time_proxyReport).toMilliSecondsDouble());
             debugObserver->setDebugChannel(
                 "LaserScannerDuration_" + simox::alg::replace_all(ip, ".", "_"), durations);
 
@@ -318,9 +322,9 @@ HokuyoLaserScanDevice::run()
                                << "Update:    "
                                << (time_update - time_measure).toMilliSecondsDouble() << "ms\n"
                                << "TopicSensor: "
-                               << (time_topicSensor - time_update).toMilliSecondsDouble() << "ms\n"
+                               << (time_proxyReport - time_update).toMilliSecondsDouble() << "ms\n"
                                << "TopicHeart:  "
-                               << (time_topicHeartbeat - time_topicSensor).toMilliSecondsDouble()
+                               << (time_topicHeartbeat - time_proxyReport).toMilliSecondsDouble()
                                << "ms\n";
             }
         }
diff --git a/source/RobotAPI/drivers/HokuyoLaserUnit/HokuyoLaserUnit.h b/source/RobotAPI/drivers/HokuyoLaserUnit/HokuyoLaserUnit.h
index 0b8ad3985e9e3b1825054fe1339cb41a5c59f4cd..98da02fce21736694803272e4e76e046080d2cd4 100644
--- a/source/RobotAPI/drivers/HokuyoLaserUnit/HokuyoLaserUnit.h
+++ b/source/RobotAPI/drivers/HokuyoLaserUnit/HokuyoLaserUnit.h
@@ -47,7 +47,7 @@ namespace armarx
             armarx::ComponentPropertyDefinitions(prefix)
         {
             defineOptionalProperty<std::string>(
-                "LaserScannerTopicName", "LaserScans", "Name of the laser scan topic.");
+                "LaserScannerListenerName", "CartographerMappingAndLocalization", "Name of the laser scan listener.");
             defineOptionalProperty<int>("UpdatePeriod", 25, "Update period for laser scans");
             defineOptionalProperty<float>("AngleOffset",
                                           -2.3561944902,
@@ -87,7 +87,7 @@ namespace armarx
         LaserScan scan;
 
         std::string componentName;
-        LaserScannerUnitListenerPrx scanTopic;
+        LaserScannerUnitListenerPrx listenerPrx;
         armarx::plugins::HeartbeatComponentPlugin* robotHealthPlugin;
         DebugObserverInterfacePrx debugObserver;
     };
@@ -150,8 +150,8 @@ namespace armarx
         LaserScannerInfoSeq getConnectedDevices(const Ice::Current& c) const override;
 
     private:
-        std::string topicName;
-        LaserScannerUnitListenerPrx topic;
+        std::string laserScannerListenerProxyName;
+        LaserScannerUnitListenerPrx listenerPrx;
         int updatePeriod = 25;
         float angleOffset = 0.0f;
         std::vector<HokuyoLaserScanDevice> devices;
diff --git a/source/RobotAPI/gui-plugins/ObjectPoseGui/ObjectPoseGuiWidget.ui b/source/RobotAPI/gui-plugins/ObjectPoseGui/ObjectPoseGuiWidget.ui
index e201caac70e9cce63d98578373084921c80f14e0..03b15fc4513ab5765b393c82007a7a6cc413714f 100644
--- a/source/RobotAPI/gui-plugins/ObjectPoseGui/ObjectPoseGuiWidget.ui
+++ b/source/RobotAPI/gui-plugins/ObjectPoseGui/ObjectPoseGuiWidget.ui
@@ -43,6 +43,29 @@
        </property>
       </spacer>
      </item>
+     <item>
+      <widget class="QPushButton" name="detchAllButton">
+       <property name="text">
+        <string>Detach All Objects</string>
+       </property>
+      </widget>
+     </item>
+     <item>
+      <widget class="QCheckBox" name="detchAllCommitAttachedCheckBox">
+       <property name="toolTip">
+        <string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;If checked, the object's pose according to the attachment will be committed as a new snapshot when the object is detached.&lt;/p&gt;&lt;p&gt;If unchecked, no new snapshot will be created, and the object's pose will return to where it was before the attachment. &lt;/p&gt;&lt;p&gt;In both cases, new snapshots to the object ID will overwrite the previous/committed snapshot.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
+       </property>
+       <property name="text">
+        <string>Commit Attached Pose</string>
+       </property>
+       <property name="checked">
+        <bool>true</bool>
+       </property>
+       <property name="tristate">
+        <bool>false</bool>
+       </property>
+      </widget>
+     </item>
     </layout>
    </item>
    <item>
diff --git a/source/RobotAPI/gui-plugins/ObjectPoseGui/ObjectPoseGuiWidgetController.cpp b/source/RobotAPI/gui-plugins/ObjectPoseGui/ObjectPoseGuiWidgetController.cpp
index 705f0f7584a84aff9354cf2986505436491f98ff..c337382c781ffe407403468e48b66a9c36c65054 100644
--- a/source/RobotAPI/gui-plugins/ObjectPoseGui/ObjectPoseGuiWidgetController.cpp
+++ b/source/RobotAPI/gui-plugins/ObjectPoseGui/ObjectPoseGuiWidgetController.cpp
@@ -24,17 +24,15 @@
 
 #include <string>
 
-#include <QTimer>
 #include <QMenu>
+#include <QTimer>
 
 #include <ArmarXCore/core/time/TimeUtil.h>
 
-#include <RobotAPI/libraries/ArmarXObjects/ice_conversions.h>
 #include <RobotAPI/libraries/ArmarXObjects/ObjectPose.h>
-
+#include <RobotAPI/libraries/ArmarXObjects/ice_conversions.h>
 #include <RobotAPI/libraries/armem_gui/TreeWidgetBuilder.h>
 
-
 namespace armarx
 {
 
@@ -56,101 +54,126 @@ namespace armarx
 
         connect(widget.updateButton, &QPushButton::pressed, this, &This::updateTab);
         connect(widget.tabWidget, &QTabWidget::currentChanged, this, &This::updateTab);
+        connect(widget.detchAllButton,
+                &QPushButton::pressed,
+                [this]() {
+                    this->detachAllObjectsFromRobotNodes(
+                        widget.detchAllCommitAttachedCheckBox->isChecked());
+                });
 
-        connect(widget.objectsTree, &QTreeWidget::customContextMenuRequested,
-                this, &This::prepareObjectContextMenu);
+        connect(widget.objectsTree,
+                &QTreeWidget::customContextMenuRequested,
+                this,
+                &This::prepareObjectContextMenu);
 
         connect(widget.requestButton, &QPushButton::pressed, this, &This::requestSelectedObjects);
 
         QTimer* timer = new QTimer(this);
         timer->setInterval(500);
         connect(timer, &QTimer::timeout, this, &This::updateTab);
-        connect(widget.autoUpdateCheckBox, &QCheckBox::toggled, this, [timer](bool checked)
-        {
-            if (checked)
-            {
-                timer->start();
-            }
-            else
-            {
-                timer->stop();
-            }
-        });
+        connect(widget.autoUpdateCheckBox,
+                &QCheckBox::toggled,
+                this,
+                [timer](bool checked)
+                {
+                    if (checked)
+                    {
+                        timer->start();
+                    }
+                    else
+                    {
+                        timer->stop();
+                    }
+                });
     }
 
-
     ObjectPoseGuiWidgetController::~ObjectPoseGuiWidgetController()
     {
     }
 
-
-    void ObjectPoseGuiWidgetController::loadSettings(QSettings* settings)
+    void
+    ObjectPoseGuiWidgetController::loadSettings(QSettings* settings)
     {
-        (void) settings;
+        (void)settings;
     }
 
-    void ObjectPoseGuiWidgetController::saveSettings(QSettings* settings)
+    void
+    ObjectPoseGuiWidgetController::saveSettings(QSettings* settings)
     {
-        (void) settings;
+        (void)settings;
     }
 
-    QString ObjectPoseGuiWidgetController::GetWidgetName()
+    QString
+    ObjectPoseGuiWidgetController::GetWidgetName()
     {
-        return "MemoryX.ObjectPoseGui";
+        return "ArMem.ObjectPoseGui";
     }
 
-    static const std::string CONFIG_KEY_OBJECT_POSE_OBSERVER = "ObjectPoseStorage";
+    static const std::string CONFIG_KEY_OBJECT_POSE_STORAGE = "ObjectPoseStorage";
 
-    QPointer<QDialog> ObjectPoseGuiWidgetController::getConfigDialog(QWidget* parent)
+    QPointer<QDialog>
+    ObjectPoseGuiWidgetController::getConfigDialog(QWidget* parent)
     {
         if (!configDialog)
         {
             configDialog = new SimpleConfigDialog(parent);
-            configDialog->addProxyFinder<armarx::objpose::ObjectPoseStorageInterfacePrx>({CONFIG_KEY_OBJECT_POSE_OBSERVER, "Object pose observer.", "*"});
+            configDialog->addProxyFinder<armarx::objpose::ObjectPoseStorageInterfacePrx>(
+                {CONFIG_KEY_OBJECT_POSE_STORAGE, "Object pose storage", "Object*"});
         }
         return qobject_cast<QDialog*>(configDialog);
     }
 
-    void ObjectPoseGuiWidgetController::configured()
+    void
+    ObjectPoseGuiWidgetController::configured()
     {
         if (configDialog)
         {
-            ObjectPoseStorageName = configDialog->getProxyName(CONFIG_KEY_OBJECT_POSE_OBSERVER);
+            objectPoseStorageName = configDialog->getProxyName(CONFIG_KEY_OBJECT_POSE_STORAGE);
+            if (objectPoseStorageName.empty())
+            {
+                objectPoseStorageName = "ObjectMemory";
+            }
         }
     }
 
-    void ObjectPoseGuiWidgetController::onInitComponent()
+    void
+    ObjectPoseGuiWidgetController::onInitComponent()
     {
-        if (!ObjectPoseStorageName.empty())
+        if (!objectPoseStorageName.empty())
         {
-            usingProxy(ObjectPoseStorageName);
+            usingProxy(objectPoseStorageName);
         }
     }
 
-    void ObjectPoseGuiWidgetController::onConnectComponent()
+    void
+    ObjectPoseGuiWidgetController::onConnectComponent()
     {
-        if (!ObjectPoseStorageName.empty())
+        if (!objectPoseStorageName.empty())
         {
-            getProxy(ObjectPoseStorage, ObjectPoseStorageName);
+            getProxy(ObjectPoseStorage, objectPoseStorageName);
         }
 
         this->attachableFrames = ObjectPoseStorage->getAttachableFrames();
-        std::sort(attachableFrames.begin(), attachableFrames.end(), [](const auto & lhs, const auto & rhs)
-        {
-            return lhs.agent < rhs.agent;
-        });
+        std::sort(attachableFrames.begin(),
+                  attachableFrames.end(),
+                  [](const auto& lhs, const auto& rhs) { return lhs.agent < rhs.agent; });
         for (objpose::AgentFrames& frames : attachableFrames)
         {
             std::sort(frames.frames.begin(), frames.frames.end());
         }
+
+        // Update once.
+        updateTab();
     }
 
-    void ObjectPoseGuiWidgetController::onDisconnectComponent()
+    void
+    ObjectPoseGuiWidgetController::onDisconnectComponent()
     {
         ObjectPoseStorage = nullptr;
     }
 
-    void ObjectPoseGuiWidgetController::updateTab()
+    void
+    ObjectPoseGuiWidgetController::updateTab()
     {
         if (widget.tabWidget->currentWidget() == widget.tabObjects)
         {
@@ -162,14 +185,13 @@ namespace armarx
         }
     }
 
-
-
-    void ObjectPoseGuiWidgetController::updateObjectsTab()
+    void
+    ObjectPoseGuiWidgetController::updateObjectsTab()
     {
         if (!ObjectPoseStorage)
         {
             // Probably disconnected.
-            ARMARX_VERBOSE << "No object pose observer.";
+            ARMARX_VERBOSE << "No object pose storage.";
             return;
         }
 
@@ -177,7 +199,8 @@ namespace armarx
         ARMARX_VERBOSE << "Getting object poses...";
         const objpose::data::ObjectPoseSeq objectPosesIce = ObjectPoseStorage->getObjectPoses();
         ARMARX_VERBOSE << "Got " << objectPosesIce.size() << " object poses. "
-                       << "(Took " << (IceUtil::Time::now() - start).toMilliSecondsDouble() << " ms.)";
+                       << "(Took " << (IceUtil::Time::now() - start).toMilliSecondsDouble()
+                       << " ms.)";
 
         const objpose::ObjectPoseSeq objectPoses = objpose::fromIce(objectPosesIce);
 
@@ -192,87 +215,97 @@ namespace armarx
         QTreeWidget* tree = widget.objectsTree;
 
         MapTreeWidgetBuilder builder(objectPosesByProvider);
-        builder.setMakeItemFn([](const std::string & provider, const objpose::ObjectPoseSeq&)
-        {
-            QTreeWidgetItem* item = new QTreeWidgetItem({QString::fromStdString(provider)});
-            return item;
-        });
-        builder.setUpdateItemFn([](const std::string&, const objpose::ObjectPoseSeq & objectPoses, QTreeWidgetItem * item)
-        {
-            bool expand = item->childCount() == 0;
-
-            TreeWidgetBuilder<objpose::ObjectPose> builder;
-            builder.setNameFn([](const objpose::ObjectPose & pose)
+        builder.setMakeItemFn(
+            [](const std::string& provider, const objpose::ObjectPoseSeq&)
             {
-                return pose.objectID.str();
-            });
-            builder.setMakeItemFn([](const objpose::ObjectPose&)
-            {
-                QTreeWidgetItem* item = new QTreeWidgetItem(QStringList{});
+                QTreeWidgetItem* item = new QTreeWidgetItem({QString::fromStdString(provider)});
                 return item;
             });
-            builder.setUpdateItemFn([](const objpose::ObjectPose & pose, QTreeWidgetItem * item)
+        builder.setUpdateItemFn(
+            [](const std::string&, const objpose::ObjectPoseSeq& objectPoses, QTreeWidgetItem* item)
             {
-                int col = 0;
-                item->setText(col++, QString::fromStdString(pose.objectID.str()));
-                item->setText(col++, QString::fromStdString(pose.providerName));
-                item->setText(col++, QString::fromStdString(objpose::ObjectTypeNames.to_name(pose.objectType)));
+                bool expand = item->childCount() == 0;
 
-                {
-                    std::stringstream ss;
-                    if (pose.localOOBB)
+                TreeWidgetBuilder<objpose::ObjectPose> builder;
+                builder.setNameFn([](const objpose::ObjectPose& pose)
+                                  { return pose.objectID.str(); });
+                builder.setMakeItemFn(
+                    [](const objpose::ObjectPose&)
                     {
-                        static const Eigen::IOFormat iof(5, 0, "", " x ", "", "", "", "");
-                        ss << pose.localOOBB->dimensions().format(iof);
-                    }
-                    else
+                        QTreeWidgetItem* item = new QTreeWidgetItem(QStringList{});
+                        return item;
+                    });
+                builder.setUpdateItemFn(
+                    [](const objpose::ObjectPose& pose, QTreeWidgetItem* item)
                     {
-                        ss << "None";
-                    }
-                    item->setText(col++, QString::fromStdString(ss.str()));
-                }
-                item->setText(col++, QString::number(double(pose.confidence), 'g', 2));
-                item->setText(col++, QString::fromStdString(pose.timestamp.toDateTimeString()));
-
+                        int col = 0;
+                        item->setText(col++, QString::fromStdString(pose.objectID.str()));
+                        item->setText(col++, QString::fromStdString(pose.providerName));
+                        item->setText(col++,
+                                      QString::fromStdString(
+                                          objpose::ObjectTypeNames.to_name(pose.objectType)));
+
+                        {
+                            std::stringstream ss;
+                            if (pose.localOOBB)
+                            {
+                                static const Eigen::IOFormat iof(5, 0, "", " x ", "", "", "", "");
+                                ss << pose.localOOBB->dimensions().format(iof);
+                            }
+                            else
+                            {
+                                ss << "None";
+                            }
+                            item->setText(col++, QString::fromStdString(ss.str()));
+                        }
+                        item->setText(col++, QString::number(double(pose.confidence), 'g', 2));
+                        item->setText(col++,
+                                      QString::fromStdString(pose.timestamp.toDateTimeString()));
+
+                        {
+                            std::stringstream ss;
+                            if (pose.attachment)
+                            {
+                                ss << pose.attachment->frameName << " ("
+                                   << pose.attachment->agentName << ")";
+                            }
+                            item->setText(col++, QString::fromStdString(ss.str()));
+                        }
+
+                        return true;
+                    });
+                builder.updateTreeWithContainer(item, objectPoses);
+
+                if (expand)
                 {
-                    std::stringstream ss;
-                    if (pose.attachment)
-                    {
-                        ss << pose.attachment->frameName << " (" << pose.attachment->agentName << ")";
-                    }
-                    item->setText(col++, QString::fromStdString(ss.str()));
+                    item->setExpanded(true);
                 }
 
                 return true;
             });
-            builder.updateTreeWithContainer(item, objectPoses);
-
-            if (expand)
-            {
-                item->setExpanded(true);
-            }
-
-            return true;
-        });
         builder.updateTree(tree, objectPosesByProvider);
 
-        ARMARX_VERBOSE << "Gui update took " << (IceUtil::Time::now() - start).toMilliSecondsDouble() << " ms.";
+        ARMARX_VERBOSE << "Gui update took "
+                       << (IceUtil::Time::now() - start).toMilliSecondsDouble() << " ms.";
     }
 
-
-    void ObjectPoseGuiWidgetController::updateRequestTab()
+    void
+    ObjectPoseGuiWidgetController::updateRequestTab()
     {
         if (!ObjectPoseStorage)
         {
             // Probably disconnected.
-            ARMARX_VERBOSE << "No object pose observer.";
+            ARMARX_VERBOSE << "No object pose storage.";
             return;
         }
 
         IceUtil::Time start = IceUtil::Time::now();
-        objpose::ProviderInfoMap availableProvidersInfo = ObjectPoseStorage->getAvailableProvidersInfo();
-        ARMARX_VERBOSE << "Got infos of " << availableProvidersInfo.size() << " object pose providers. "
-                       << "(Took " << (IceUtil::Time::now() - start).toMilliSecondsDouble() << " ms.)";
+        objpose::ProviderInfoMap availableProvidersInfo =
+            ObjectPoseStorage->getAvailableProvidersInfo();
+        ARMARX_VERBOSE << "Got infos of " << availableProvidersInfo.size()
+                       << " object pose providers. "
+                       << "(Took " << (IceUtil::Time::now() - start).toMilliSecondsDouble()
+                       << " ms.)";
 
 
         // Restructure data.
@@ -290,50 +323,62 @@ namespace armarx
         QTreeWidget* tree = widget.requestTree;
 
         MapTreeWidgetBuilder builder(data);
-        builder.setMakeItemFn([](const std::string & dataset, const auto&)
-        {
-            QTreeWidgetItem* item = new QTreeWidgetItem({QString::fromStdString(dataset)});
-            return item;
-        });
-        builder.setUpdateItemFn([tree](const std::string & dataset, const auto & datasetData, QTreeWidgetItem * datasetItem)
-        {
-            (void) dataset;
-
-            TreeWidgetBuilder<std::pair<std::string, std::string>> builder;
-            builder.setCompareFn([](const std::pair<std::string, std::string>& lhs, QTreeWidgetItem * item)
-            {
-                auto rhs = std::make_pair(item->text(0).toStdString(), item->text(1).toStdString());
-                if (lhs < rhs)
-                {
-                    return -1;
-                }
-                return lhs == rhs ? 0 : 1;
-            });
-            builder.setMakeItemFn([](const std::pair<std::string, std::string>& element)
+        builder.setMakeItemFn(
+            [](const std::string& dataset, const auto&)
             {
-                QTreeWidgetItem* item = new QTreeWidgetItem({ QString::fromStdString(element.first), QString::fromStdString(element.second)});
+                QTreeWidgetItem* item = new QTreeWidgetItem({QString::fromStdString(dataset)});
                 return item;
             });
-            builder.setUpdateItemFn([tree](const std::pair<std::string, std::string>& element, QTreeWidgetItem * item)
+        builder.setUpdateItemFn(
+            [tree](
+                const std::string& dataset, const auto& datasetData, QTreeWidgetItem* datasetItem)
             {
-                (void) element;
-                if (!tree->itemWidget(item, 2))
-                {
-                    QCheckBox* requestCheckBox = new QCheckBox();
-                    tree->setItemWidget(item, 2, requestCheckBox);
-                }
+                (void)dataset;
+
+                TreeWidgetBuilder<std::pair<std::string, std::string>> builder;
+                builder.setCompareFn(
+                    [](const std::pair<std::string, std::string>& lhs, QTreeWidgetItem* item)
+                    {
+                        auto rhs = std::make_pair(item->text(0).toStdString(),
+                                                  item->text(1).toStdString());
+                        if (lhs < rhs)
+                        {
+                            return -1;
+                        }
+                        return lhs == rhs ? 0 : 1;
+                    });
+                builder.setMakeItemFn(
+                    [](const std::pair<std::string, std::string>& element)
+                    {
+                        QTreeWidgetItem* item =
+                            new QTreeWidgetItem({QString::fromStdString(element.first),
+                                                 QString::fromStdString(element.second)});
+                        return item;
+                    });
+                builder.setUpdateItemFn(
+                    [tree](const std::pair<std::string, std::string>& element,
+                           QTreeWidgetItem* item)
+                    {
+                        (void)element;
+                        if (!tree->itemWidget(item, 2))
+                        {
+                            QCheckBox* requestCheckBox = new QCheckBox();
+                            tree->setItemWidget(item, 2, requestCheckBox);
+                        }
+                        return true;
+                    });
+                builder.updateTreeWithContainer(datasetItem, datasetData);
+
                 return true;
             });
-            builder.updateTreeWithContainer(datasetItem, datasetData);
-
-            return true;
-        });
         builder.updateTree(tree, data);
 
-        ARMARX_VERBOSE << "Gui update took " << (IceUtil::Time::now() - start).toMilliSecondsDouble() << " ms.";
+        ARMARX_VERBOSE << "Gui update took "
+                       << (IceUtil::Time::now() - start).toMilliSecondsDouble() << " ms.";
     }
 
-    void ObjectPoseGuiWidgetController::prepareObjectContextMenu(const QPoint& pos)
+    void
+    ObjectPoseGuiWidgetController::prepareObjectContextMenu(const QPoint& pos)
     {
         QTreeWidget* tree = widget.objectsTree;
         QTreeWidgetItem* item = tree->itemAt(pos);
@@ -356,11 +401,12 @@ namespace armarx
             {
                 QAction* attachAgentAction = new QAction(QString::fromStdString(frame), tree);
                 // attachAgentAction->setStatusTip(tr("Attach object rigidly to a robot node"));
-                connect(attachAgentAction, &QAction::triggered,
-                        [ =, this ]()
-                {
-                    this->attachObjectToRobotNode(providerName, objectID, agentFrames.agent, frame);
-                });
+                connect(attachAgentAction,
+                        &QAction::triggered,
+                        [=, this]() {
+                            this->attachObjectToRobotNode(
+                                providerName, objectID, agentFrames.agent, frame);
+                        });
                 agentMenu->addAction(attachAgentAction);
             }
             attachMenu->addMenu(agentMenu);
@@ -368,10 +414,9 @@ namespace armarx
 
         QAction* detachAction = new QAction(tr("Detach from to robot node"), tree);
         detachAction->setEnabled(!item->text(OBJECTS_COLUMN_ATTACHMENT).isEmpty());
-        connect(detachAction, &QAction::triggered, [ =, this ]()
-        {
-            this->detachObjectFromRobotNode(providerName, objectID);
-        });
+        connect(detachAction,
+                &QAction::triggered,
+                [=, this]() { this->detachObjectFromRobotNode(providerName, objectID); });
 
         QMenu menu(tree);
         menu.addMenu(attachMenu);
@@ -380,9 +425,11 @@ namespace armarx
         menu.exec(tree->mapToGlobal(pos));
     }
 
-    void ObjectPoseGuiWidgetController::attachObjectToRobotNode(
-        QString providerName, QString objectID,
-        const std::string& agentName, const std::string& frameName)
+    void
+    ObjectPoseGuiWidgetController::attachObjectToRobotNode(QString providerName,
+                                                           QString objectID,
+                                                           const std::string& agentName,
+                                                           const std::string& frameName)
     {
         ARMARX_VERBOSE << "Attaching " << objectID << " by '" << providerName << "' to robot node '"
                        << frameName << "' of agent '" << agentName << "'.";
@@ -395,7 +442,8 @@ namespace armarx
 
         try
         {
-            objpose::AttachObjectToRobotNodeOutput output = ObjectPoseStorage->attachObjectToRobotNode(input);
+            objpose::AttachObjectToRobotNodeOutput output =
+                ObjectPoseStorage->attachObjectToRobotNode(input);
             ARMARX_VERBOSE << "Success of attaching: " << output.success;
         }
         catch (const IceUtil::Exception& e)
@@ -406,9 +454,11 @@ namespace armarx
         }
     }
 
-    void ObjectPoseGuiWidgetController::detachObjectFromRobotNode(QString providerName, QString objectID)
+    void
+    ObjectPoseGuiWidgetController::detachObjectFromRobotNode(QString providerName, QString objectID)
     {
-        ARMARX_VERBOSE << "Detaching " << objectID << " by '" << providerName << "' from robot node.";
+        ARMARX_VERBOSE << "Detaching " << objectID << " by '" << providerName
+                       << "' from robot node.";
 
         objpose::DetachObjectFromRobotNodeInput input;
         input.providerName = providerName.toStdString();
@@ -416,17 +466,39 @@ namespace armarx
 
         try
         {
-            objpose::DetachObjectFromRobotNodeOutput output = ObjectPoseStorage->detachObjectFromRobotNode(input);
+            objpose::DetachObjectFromRobotNodeOutput output =
+                ObjectPoseStorage->detachObjectFromRobotNode(input);
             ARMARX_VERBOSE << "Was attached: " << output.wasAttached;
         }
         catch (const IceUtil::Exception& e)
         {
-            ARMARX_WARNING << "Failed to detach object '" << input.objectID << "' from a robot node."
+            ARMARX_WARNING << "Failed to detach object '" << input.objectID
+                           << "' from a robot node."
                            << "\nReason: " << e.what();
         }
     }
 
-    void ObjectPoseGuiWidgetController::requestSelectedObjects()
+    void
+    ObjectPoseGuiWidgetController::detachAllObjectsFromRobotNodes(bool commitAttachedPose)
+    {
+
+        objpose::DetachAllObjectsFromRobotNodesInput input;
+        input.commitAttachedPose = commitAttachedPose;
+
+        try
+        {
+            objpose::DetachAllObjectsFromRobotNodesOutput output =
+                ObjectPoseStorage->detachAllObjectsFromRobotNodes(input);
+            ARMARX_VERBOSE << "Detached " << output.numDetached << " objects from robot nodes.";
+        }
+        catch (const IceUtil::Exception& e)
+        {
+            ARMARX_WARNING << "Failed to detach all objects from robot nodes.";
+        }
+    }
+
+    void
+    ObjectPoseGuiWidgetController::requestSelectedObjects()
     {
         std::map<std::string, objpose::observer::RequestObjectsInput> requestsPerProvider;
 
@@ -442,7 +514,8 @@ namespace armarx
                 if (selected->isChecked())
                 {
                     std::string providerName = classItem->text(1).toStdString();
-                    objpose::observer::RequestObjectsInput& requests = requestsPerProvider[providerName];
+                    objpose::observer::RequestObjectsInput& requests =
+                        requestsPerProvider[providerName];
                     data::ObjectID& id = requests.request.objectIDs.emplace_back();
                     id.dataset = datasetItem->text(0).toStdString();
                     id.className = classItem->text(0).toStdString();
@@ -463,14 +536,16 @@ namespace armarx
 
             ARMARX_INFO << "Requesting " << request.request.objectIDs.size() << " objects for "
                         << request.request.relativeTimeoutMS << " ms.";
-            objpose::observer::RequestObjectsOutput output = ObjectPoseStorage->requestObjects(request);
+            objpose::observer::RequestObjectsOutput output =
+                ObjectPoseStorage->requestObjects(request);
             int successful = 0;
             for (const auto& [id, result] : output.results)
             {
                 successful += int(!result.providerName.empty() && result.result.success);
             }
-            ARMARX_INFO << successful << " of " << request.request.objectIDs.size() << " object request successful.";
+            ARMARX_INFO << successful << " of " << request.request.objectIDs.size()
+                        << " object request successful.";
         }
     }
 
-}
+} // namespace armarx
diff --git a/source/RobotAPI/gui-plugins/ObjectPoseGui/ObjectPoseGuiWidgetController.h b/source/RobotAPI/gui-plugins/ObjectPoseGui/ObjectPoseGuiWidgetController.h
index 5e9910bd8185cb13adbd54435758ee871dbd8460..462b1b0485eefe270e7bdcad5b2060bd2f3077dd 100644
--- a/source/RobotAPI/gui-plugins/ObjectPoseGui/ObjectPoseGuiWidgetController.h
+++ b/source/RobotAPI/gui-plugins/ObjectPoseGui/ObjectPoseGuiWidgetController.h
@@ -21,17 +21,15 @@
  */
 #pragma once
 
-#include <RobotAPI/gui-plugins/ObjectPoseGui/ui_ObjectPoseGuiWidget.h>
+#include <ArmarXCore/core/system/ImportExportComponent.h>
 
-#include <ArmarXGui/libraries/ArmarXGuiBase/ArmarXGuiPlugin.h>
 #include <ArmarXGui/libraries/ArmarXGuiBase/ArmarXComponentWidgetController.h>
+#include <ArmarXGui/libraries/ArmarXGuiBase/ArmarXGuiPlugin.h>
 #include <ArmarXGui/libraries/SimpleConfigDialog/SimpleConfigDialog.h>
 
-#include <ArmarXCore/core/system/ImportExportComponent.h>
-
+#include <RobotAPI/gui-plugins/ObjectPoseGui/ui_ObjectPoseGuiWidget.h>
 #include <RobotAPI/interface/objectpose/ObjectPoseStorageInterface.h>
 
-
 namespace armarx
 {
     /**
@@ -52,9 +50,8 @@ namespace armarx
      *
      * Detailed description
      */
-    class ARMARXCOMPONENT_IMPORT_EXPORT
-        ObjectPoseGuiWidgetController :
-        public armarx::ArmarXComponentWidgetControllerTemplate < ObjectPoseGuiWidgetController >
+    class ARMARXCOMPONENT_IMPORT_EXPORT ObjectPoseGuiWidgetController :
+        public armarx::ArmarXComponentWidgetControllerTemplate<ObjectPoseGuiWidgetController>
     {
         Q_OBJECT
 
@@ -98,9 +95,12 @@ namespace armarx
         void updateRequestTab();
 
         void prepareObjectContextMenu(const QPoint& pos);
-        void attachObjectToRobotNode(QString providerName, QString objectID,
-                                     const std::string& agentName, const std::string& frameName);
+        void attachObjectToRobotNode(QString providerName,
+                                     QString objectID,
+                                     const std::string& agentName,
+                                     const std::string& frameName);
         void detachObjectFromRobotNode(QString providerName, QString objectID);
+        void detachAllObjectsFromRobotNodes(bool commitAttachedPose);
 
         void requestSelectedObjects();
 
@@ -109,18 +109,14 @@ namespace armarx
         /* QT signal declarations */
 
     private:
-
         /// Widget Form
         Ui::ObjectPoseGuiWidget widget;
 
         QPointer<SimpleConfigDialog> configDialog;
 
-        std::string ObjectPoseStorageName;
+        std::string objectPoseStorageName;
         armarx::objpose::ObjectPoseStorageInterfacePrx ObjectPoseStorage;
 
         objpose::AgentFramesSeq attachableFrames;
-
     };
-}
-
-
+} // namespace armarx
diff --git a/source/RobotAPI/libraries/PriorKnowledge/util/LocationLoader/LocationLoader.cpp b/source/RobotAPI/libraries/PriorKnowledge/util/LocationLoader/LocationLoader.cpp
index b0f94d03e4868e9051525ad5864c82fbe37a5b13..47b8601280e5191e99a7f1a4d56fec5aeaf75ab5 100644
--- a/source/RobotAPI/libraries/PriorKnowledge/util/LocationLoader/LocationLoader.cpp
+++ b/source/RobotAPI/libraries/PriorKnowledge/util/LocationLoader/LocationLoader.cpp
@@ -1,5 +1,7 @@
 #include "LocationLoader.h"
 
+#include <SimoxUtility/algorithm/string.h>
+
 #include <ArmarXCore/core/eigen/ice_conversions.h>
 #include <ArmarXCore/core/logging/Logging.h>
 
@@ -67,7 +69,12 @@ namespace armarx::priorknowledge::util
                     .get<std::vector<std::vector<float>>>()); // load the 4x4 matrix
 
             armarx::FramedPose fp(pose, frame, agent);
-            Location loc(dataset, locationIdStr, fp);
+
+            // escape locationIdStr
+            auto locationIdStrSplitted = simox::alg::split(locationIdStr, "#");
+            std::string locationIdStrEscaped = simox::alg::trim_copy(locationIdStrSplitted[0]);
+
+            Location loc{{dataset, fp.agent, locationIdStrEscaped}, fp};
             ret.push_back(loc);
         }
         return ret;
diff --git a/source/RobotAPI/libraries/PriorKnowledge/util/LocationLoader/datatypes/Location.cpp b/source/RobotAPI/libraries/PriorKnowledge/util/LocationLoader/datatypes/Location.cpp
index 843d7b6eea739b23861d0ac22a097b9921757b5a..ea08e20229bb09989f2b4239a529d9b107a3e0f2 100644
--- a/source/RobotAPI/libraries/PriorKnowledge/util/LocationLoader/datatypes/Location.cpp
+++ b/source/RobotAPI/libraries/PriorKnowledge/util/LocationLoader/datatypes/Location.cpp
@@ -6,23 +6,20 @@
 
 namespace armarx::priorknowledge::util
 {
-
-    LocationId::LocationId(const std::string& sourceId, const std::string& name) :
-        sourceId(sourceId), name(name)
-    {
-    }
-
     std::string
     LocationId::toString() const
     {
-        return sourceId + "/" + name;
+        return sourceId + "/" + toStringWithoutSourceId();
     }
 
-    Location::Location(const std::string& sourceId,
-                       const std::string& name,
-                       const armarx::FramedPose& p) :
-        id(sourceId, name), pose(p)
+    std::string
+    LocationId::toStringWithoutSourceId() const
     {
+      if (! prefix.empty())
+      {
+        return prefix + "/" + name;
+      }
+      return name;
     }
 
 } // namespace armarx::priorknowledge::util
diff --git a/source/RobotAPI/libraries/PriorKnowledge/util/LocationLoader/datatypes/Location.h b/source/RobotAPI/libraries/PriorKnowledge/util/LocationLoader/datatypes/Location.h
index c85502812b77c4d443c70885ad955cd13ef416df..202b7734a2b7dea90e37d1df1f4a6886ba162b18 100644
--- a/source/RobotAPI/libraries/PriorKnowledge/util/LocationLoader/datatypes/Location.h
+++ b/source/RobotAPI/libraries/PriorKnowledge/util/LocationLoader/datatypes/Location.h
@@ -9,18 +9,16 @@ namespace armarx::priorknowledge::util
     struct LocationId
     {
         std::string sourceId;
+        std::string prefix;
         std::string name;
 
-        LocationId(const std::string& sourceId, const std::string& name);
-
         std::string toString() const;
+        std::string toStringWithoutSourceId() const;
     };
 
     struct Location
     {
         LocationId id;
         armarx::FramedPose pose;
-
-        Location(const std::string& sourceId, const std::string& name, const armarx::FramedPose& p);
     };
 } // namespace armarx::priorknowledge::util
diff --git a/source/RobotAPI/libraries/RobotAPIComponentPlugins/ArVizComponentPlugin.cpp b/source/RobotAPI/libraries/RobotAPIComponentPlugins/ArVizComponentPlugin.cpp
index 7c63d33b767f10ace65279b9be98e9426e5d8644..0bc460c8bc27fea0f3b2dcdfe9ba46921680291a 100644
--- a/source/RobotAPI/libraries/RobotAPIComponentPlugins/ArVizComponentPlugin.cpp
+++ b/source/RobotAPI/libraries/RobotAPIComponentPlugins/ArVizComponentPlugin.cpp
@@ -2,7 +2,6 @@
 
 #include <ArmarXCore/core/Component.h>
 
-
 namespace armarx::plugins
 {
     static const std::string ARVIZ_TOPIC_PROPERTY_NAME = "ArVizTopicName";
@@ -11,28 +10,31 @@ namespace armarx::plugins
     static const std::string ARVIZ_STORAGE_PROPERTY_NAME = "ArVizStorageName";
     static const std::string ARVIZ_STORAGE_PROPERTY_DEFAULT = "ArVizStorage";
 
-
-    std::string ArVizComponentPlugin::getTopicName()
+    std::string
+    ArVizComponentPlugin::getTopicName()
     {
-        return parentDerives<Component>() ?
-               parent<Component>().getProperty<std::string>(makePropertyName(ARVIZ_TOPIC_PROPERTY_NAME)) :
-                    ARVIZ_TOPIC_PROPERTY_DEFAULT;
+        return parentDerives<Component>() ? parent<Component>().getProperty<std::string>(
+                                                makePropertyName(ARVIZ_TOPIC_PROPERTY_NAME))
+                                          : ARVIZ_TOPIC_PROPERTY_DEFAULT;
     }
 
-    std::string ArVizComponentPlugin::getStorageName()
+    std::string
+    ArVizComponentPlugin::getStorageName()
     {
-        return parentDerives<Component>() ?
-               parent<Component>().getProperty<std::string>(makePropertyName(ARVIZ_STORAGE_PROPERTY_NAME)) :
-                    ARVIZ_STORAGE_PROPERTY_DEFAULT;
+        return parentDerives<Component>() ? parent<Component>().getProperty<std::string>(
+                                                makePropertyName(ARVIZ_STORAGE_PROPERTY_NAME))
+                                          : ARVIZ_STORAGE_PROPERTY_DEFAULT;
     }
 
-    void ArVizComponentPlugin::preOnInitComponent()
+    void
+    ArVizComponentPlugin::preOnInitComponent()
     {
         parent().offeringTopic(getTopicName());
         parent().usingProxy(getStorageName());
     }
 
-    void ArVizComponentPlugin::preOnConnectComponent()
+    void
+    ArVizComponentPlugin::preOnConnectComponent()
     {
         if (parentDerives<ArVizComponentPluginUser>())
         {
@@ -40,7 +42,8 @@ namespace armarx::plugins
         }
     }
 
-    void ArVizComponentPlugin::postCreatePropertyDefinitions(armarx::PropertyDefinitionsPtr& properties)
+    void
+    ArVizComponentPlugin::postCreatePropertyDefinitions(armarx::PropertyDefinitionsPtr& properties)
     {
         if (!properties->hasDefinition(makePropertyName(ARVIZ_TOPIC_PROPERTY_NAME)))
         {
@@ -58,11 +61,12 @@ namespace armarx::plugins
         }
     }
 
-    viz::Client ArVizComponentPlugin::createClient()
+    viz::Client
+    ArVizComponentPlugin::createClient()
     {
         return viz::Client(parent(), getTopicName(), getStorageName());
     }
-}
+} // namespace armarx::plugins
 
 namespace armarx
 {
@@ -71,8 +75,9 @@ namespace armarx
         addPlugin(plugin);
     }
 
-    viz::Client ArVizComponentPluginUser::createArVizClient()
+    viz::Client
+    ArVizComponentPluginUser::createArVizClient()
     {
         return plugin->createClient();
     }
-}
+} // namespace armarx
diff --git a/source/RobotAPI/libraries/RobotUnitDataStreamingReceiver/RobotUnitDataStreamingReceiver.cpp b/source/RobotAPI/libraries/RobotUnitDataStreamingReceiver/RobotUnitDataStreamingReceiver.cpp
index 14aceaef8913538df4af2e5272abd125150ca352..3ab4e0530b54331305cdbc8f8ad05603607b0ac9 100644
--- a/source/RobotAPI/libraries/RobotUnitDataStreamingReceiver/RobotUnitDataStreamingReceiver.cpp
+++ b/source/RobotAPI/libraries/RobotUnitDataStreamingReceiver/RobotUnitDataStreamingReceiver.cpp
@@ -20,13 +20,13 @@
  *             GNU General Public License
  */
 
+#include "RobotUnitDataStreamingReceiver.h"
+
 #include <Ice/ObjectAdapter.h>
 
 #include "ArmarXCore/core/logging/Logging.h"
 #include <ArmarXCore/core/ArmarXManager.h>
 
-#include "RobotUnitDataStreamingReceiver.h"
-
 namespace armarx::detail::RobotUnitDataStreamingReceiver
 {
     class Receiver :
@@ -34,23 +34,37 @@ namespace armarx::detail::RobotUnitDataStreamingReceiver
         virtual public RobotUnitDataStreaming::Receiver
     {
     public:
-        std::string getDefaultName() const override
+        std::string
+        getDefaultName() const override
         {
             return "RobotUnitDataStreamingReceiver";
         }
+
         ~Receiver()
         {
             std::lock_guard g{_data_mutex};
         }
-        void onInitComponent() override {}
-        void onConnectComponent() override {}
-        void onExitComponent() override {}
-
-        void update_async(
-            const RobotUnitDataStreaming::AMD_Receiver_updatePtr& ptr,
-            const RobotUnitDataStreaming::TimeStepSeq& data,
-            Ice::Long msgSequenceNbr,
-            const Ice::Current&) override
+
+        void
+        onInitComponent() override
+        {
+        }
+
+        void
+        onConnectComponent() override
+        {
+        }
+
+        void
+        onExitComponent() override
+        {
+        }
+
+        void
+        update_async(const RobotUnitDataStreaming::AMD_Receiver_updatePtr& ptr,
+                     const RobotUnitDataStreaming::TimeStepSeq& data,
+                     Ice::Long msgSequenceNbr,
+                     const Ice::Current&) override
         {
             ptr->ice_response();
             if (_discard_data)
@@ -65,32 +79,31 @@ namespace armarx::detail::RobotUnitDataStreamingReceiver
             _data[seq] = data;
         }
 
-        std::atomic_bool                                              _discard_data = false;
-        std::mutex                                                    _data_mutex;
-        std::map<std::uint64_t, RobotUnitDataStreaming::TimeStepSeq>  _data;
-        Ice::Identity                                                 _identity;
+        std::atomic_bool _discard_data = false;
+        std::mutex _data_mutex;
+        std::map<std::uint64_t, RobotUnitDataStreaming::TimeStepSeq> _data;
+        Ice::Identity _identity;
     };
-}
+} // namespace armarx::detail::RobotUnitDataStreamingReceiver
 
 namespace armarx
 {
     RobotUnitDataStreamingReceiver::RobotUnitDataStreamingReceiver(
         const ManagedIceObjectPtr& obj,
         const RobotUnitInterfacePrx& ru,
-        const RobotUnitDataStreaming::Config& cfg
-    ) : _obj{obj}, _ru{ru}
+        const RobotUnitDataStreaming::Config& cfg) :
+        _obj{obj}, _ru{ru}
     {
         ARMARX_CHECK_NOT_NULL(_obj);
         ARMARX_CHECK_NOT_NULL(_ru);
         _receiver = make_shared<detail::RobotUnitDataStreamingReceiver::Receiver>();
 
-        _receiver->_identity.name =
-            _obj->getName() + "_RobotUnitDataStreamingReceiver_" +
-            std::to_string(clock_t::now().time_since_epoch().count());
+        _receiver->_identity.name = _obj->getName() + "_RobotUnitDataStreamingReceiver_" +
+                                    std::to_string(clock_t::now().time_since_epoch().count());
 
         auto adapter = _obj->getArmarXManager()->getAdapter();
         _proxy = RobotUnitDataStreaming::ReceiverPrx::uncheckedCast(
-                     adapter->add(_receiver,  _receiver->_identity));
+            adapter->add(_receiver, _receiver->_identity));
 
         _description = _ru->startDataStreaming(_proxy, cfg);
     }
@@ -120,14 +133,15 @@ namespace armarx
                 ARMARX_INFO << deactivateSpam() << "waiting until receiver is removed from ice";
             }
         }
-        _proxy    = nullptr;
+        _proxy = nullptr;
         _receiver = nullptr;
     }
 
-    std::deque<RobotUnitDataStreaming::TimeStep>& RobotUnitDataStreamingReceiver::getDataBuffer()
+    std::deque<RobotUnitDataStreaming::TimeStep>&
+    RobotUnitDataStreamingReceiver::getDataBuffer()
     {
         ARMARX_CHECK_NOT_NULL(_receiver);
-        std::map<std::uint64_t, RobotUnitDataStreaming::TimeStepSeq>  data;
+        std::map<std::uint64_t, RobotUnitDataStreaming::TimeStepSeq> data;
         {
             std::lock_guard g{_receiver->_data_mutex};
             std::swap(data, _receiver->_data);
@@ -169,14 +183,12 @@ namespace armarx
             _tmp_data_buffer_seq_id = it->first;
             for (auto& step : it->second)
             {
-                if (
-                    _last_iteration_id != -1 &&
-                    _last_iteration_id + 1 != step.iterationId
-                )
+                if (_last_iteration_id != -1 && _last_iteration_id + 1 != step.iterationId)
                 {
-                    ARMARX_VERBOSE << "Missing Iterations or iterations out of order! "
-                                 << "This should not happen. " 
-                                 << VAROUT(_last_iteration_id) << ", " << VAROUT(step.iterationId);
+                    ARMARX_INFO << deactivateSpam(10)
+                                << "Missing Iterations or iterations out of order! "
+                                << "This should not happen. " << VAROUT(_last_iteration_id) << ", "
+                                << VAROUT(step.iterationId);
                 }
                 _last_iteration_id = step.iterationId;
                 _data_buffer.emplace_back(std::move(step));
@@ -186,12 +198,14 @@ namespace armarx
         return _data_buffer;
     }
 
-    const RobotUnitDataStreaming::DataStreamingDescription& RobotUnitDataStreamingReceiver::getDataDescription() const
+    const RobotUnitDataStreaming::DataStreamingDescription&
+    RobotUnitDataStreamingReceiver::getDataDescription() const
     {
         return _description;
     }
 
-    std::string RobotUnitDataStreamingReceiver::getDataDescriptionString() const
+    std::string
+    RobotUnitDataStreamingReceiver::getDataDescriptionString() const
     {
         std::stringstream str;
         const auto& entr = getDataDescription().entries;
@@ -202,4 +216,4 @@ namespace armarx
         }
         return str.str();
     }
-}
+} // namespace armarx
diff --git a/source/RobotAPI/libraries/armem/client/util/SimpleReaderBase.h b/source/RobotAPI/libraries/armem/client/util/SimpleReaderBase.h
index 22ae30fbd8489aff451fda127a170f58548f5fcc..45b26e7c9e8c4dd124b762d297d2fb0dca29a317 100644
--- a/source/RobotAPI/libraries/armem/client/util/SimpleReaderBase.h
+++ b/source/RobotAPI/libraries/armem/client/util/SimpleReaderBase.h
@@ -54,6 +54,10 @@ namespace armarx::armem::client::util
         virtual void connect();
 
         const Properties& properties() const;
+        void setProperties(const Properties& p)
+        {
+          props = p;
+        }
 
     protected:
 
diff --git a/source/RobotAPI/libraries/armem_locations/CMakeLists.txt b/source/RobotAPI/libraries/armem_locations/CMakeLists.txt
index 22d418142d784080f8f4f99410a25a272d5c628f..38d927aa828a2e1d554492527093c0cb21b09035 100644
--- a/source/RobotAPI/libraries/armem_locations/CMakeLists.txt
+++ b/source/RobotAPI/libraries/armem_locations/CMakeLists.txt
@@ -11,12 +11,20 @@ armarx_add_library(
 
         RobotAPI::Core
         RobotAPI::armem
+
+        armem_objects
+        armem_robot_state
+
         # aronjsonconverter
     SOURCES  
         ./aron_conversions.cpp
+        ./frame_conversions.cpp
+        ./client/Reader.cpp
 
     HEADERS  
         ./aron_conversions.h
+        ./frame_conversions.h
+        ./client/Reader.h
 )
 
 armarx_enable_aron_file_generation_for_target(
diff --git a/source/RobotAPI/libraries/armem_locations/aron/Location.xml b/source/RobotAPI/libraries/armem_locations/aron/Location.xml
index 9a0539d5d40a3b3b91dc32ad2034077a815437ff..d53f51c2c8f75bacae2868ae9bc155aad717379e 100644
--- a/source/RobotAPI/libraries/armem_locations/aron/Location.xml
+++ b/source/RobotAPI/libraries/armem_locations/aron/Location.xml
@@ -1,41 +1,12 @@
 <?xml version="1.0" encoding="UTF-8" ?>
 <AronTypeDefinition>
-    <CodeIncludes>
-    </CodeIncludes>
-    <AronIncludes>
-        <Include include="<RobotAPI/libraries/armem/aron/MemoryID.xml>" autoinclude="true"/>
-    </AronIncludes>
 
     <GenerateTypes>
 
-        <!--
-        ToDo: Model regions. Ideas:
-        - Polygon (convex, non-convex)
-        -
-        -->
-
-
-        <Object name='armarx::navigation::location::arondto::ObjectRelativeLocation'>
-
-            <ObjectChild key='objectInstanceID'>
-                <armarx::armem::arondto::MemoryID />
-            </ObjectChild>
-
-            <ObjectChild key='relativeRobotPose'>
-                <Pose />
-            </ObjectChild>
-
-        </Object>
-
-
         <Object name='armarx::navigation::location::arondto::Location'>
 
-            <ObjectChild key='globalRobotPose'>
-                <Pose />
-            </ObjectChild>
-
-            <ObjectChild key='relativeToObject'>
-                <armarx::navigation::location::arondto::ObjectRelativeLocation optional="true" />
+            <ObjectChild key='framedPose'>
+                <FramedPose />
             </ObjectChild>
 
         </Object>
diff --git a/source/RobotAPI/libraries/armem_locations/client/Reader.cpp b/source/RobotAPI/libraries/armem_locations/client/Reader.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..0fd0c6a1b5258d7960e9179c649ab0286b26be5a
--- /dev/null
+++ b/source/RobotAPI/libraries/armem_locations/client/Reader.cpp
@@ -0,0 +1,108 @@
+#include "Reader.h"
+
+#include <RobotAPI/libraries/armem/client/query/Builder.h>
+#include <RobotAPI/libraries/armem/core/Time.h>
+#include <RobotAPI/libraries/armem/core/error.h>
+#include <RobotAPI/libraries/armem/core/wm/memory_definitions.h>
+#include <RobotAPI/libraries/armem/util/util.h>
+
+#include "../frame_conversions.h"
+
+namespace armarx::armem::locations::client
+{
+    Reader::Reader(armem::client::MemoryNameSystem& memoryNameSystem) :
+        memoryNameSystem(memoryNameSystem),
+        objReader(memoryNameSystem),
+        robotReader(memoryNameSystem)
+    {
+    }
+
+    void
+    Reader::registerPropertyDefinitions(armarx::PropertyDefinitionsPtr& def)
+    {
+        const std::string prefix = propertyPrefix;
+
+        def->optional(p.memoryName, prefix + "MemoryName");
+        objReader.registerPropertyDefinitions(def);
+        robotReader.registerPropertyDefinitions(def);
+    }
+
+    void
+    Reader::connect()
+    {
+        // Wait for the memory to become available and add it as dependency.
+        ARMARX_IMPORTANT << "Waiting for memory '" << p.memoryName << "' ...";
+        try
+        {
+            // simply wait until memory is ready. Do nothing with reader but get prx
+            locationReader = memoryNameSystem.useReader(p.memoryName);
+
+            ARMARX_IMPORTANT << "Connected to Memory '" << p.memoryName << "'";
+        }
+        catch (const armem::error::CouldNotResolveMemoryServer& e)
+        {
+            ARMARX_ERROR << e.what();
+            return;
+        }
+
+        objReader.connect();
+        robotReader.connect();
+    }
+
+    std::map<std::string, armarx::navigation::location::arondto::Location>
+    Reader::getAllLocations()
+    {
+        auto mId = armarx::armem::MemoryID{p.memoryName, "Location"};
+        auto res = locationReader.getLatestSnapshotsIn(mId);
+
+        if (res.success)
+        {
+            std::map<std::string, armarx::navigation::location::arondto::Location> ret;
+            res.memory.forEachEntity(
+                [&ret](const armarx::armem::wm::Entity& e)
+                {
+                    auto i = e.findLatestInstance();
+                    if (i)
+                      {
+                      auto loc = i->dataAs<armarx::navigation::location::arondto::Location>();
+                      ret[i->id().providerSegmentName + "/" + i->id().entityName] = loc;
+                    }
+                  });
+            return ret;
+        }
+
+        throw error::ArMemError(res.errorMessage);
+    }
+
+    std::map<std::string, armarx::navigation::location::arondto::Location>
+    Reader::getAllLocationsInGlobalFrame()
+    {
+        auto locations = this->getAllLocations();
+        auto objects = objReader.queryLatestObjectInstances();
+        auto robotDecs = robotReader.queryDescriptions(armarx::core::time::DateTime::Now());
+
+        for (auto& [locName, location] : locations)
+        {
+            (void) locName;
+            if (location.framedPose.header.frame == armarx::GlobalFrame)
+            {
+                location.framedPose.header.agent = ""; //sanity set
+                continue;
+            }
+            // check if we have an object that matches the relative location
+            for (const auto& [objectInstanceId, object] : objects)
+            {
+                if (simox::alg::starts_with(objectInstanceId, location.framedPose.header.agent))
+                {
+                    toGlobal(location, object);
+                }
+            }
+
+            // TODO: check if we have an robot that matches the relative location
+        }
+
+        return locations;
+    }
+
+
+} // namespace armarx::armem::locations::client
diff --git a/source/RobotAPI/libraries/armem_locations/client/Reader.h b/source/RobotAPI/libraries/armem_locations/client/Reader.h
new file mode 100644
index 0000000000000000000000000000000000000000..ad895c269e52fd2e4ec1b6e6bbda037fbefedb04
--- /dev/null
+++ b/source/RobotAPI/libraries/armem_locations/client/Reader.h
@@ -0,0 +1,54 @@
+#pragma once
+
+#include <mutex>
+#include <optional>
+
+#include <Eigen/Core>
+
+#include <ArmarXCore/core/application/properties/PropertyDefinitionContainer.h>
+
+#include <RobotAPI/libraries/armem/client/MemoryNameSystem.h>
+#include <RobotAPI/libraries/armem/client/Reader.h>
+#include <RobotAPI/libraries/armem_locations/aron/Location.aron.generated.h>
+#include <RobotAPI/libraries/armem_objects/client/instance/ObjectReader.h>
+#include <RobotAPI/libraries/armem_robot_state/client/common/RobotReader.h>
+
+namespace armarx::armem::locations::client
+{
+    class Reader
+    {
+    public:
+        struct Properties
+        {
+            std::string memoryName = "Navigation";
+        };
+
+        Reader(armem::client::MemoryNameSystem& memoryNameSystem);
+        virtual ~Reader() = default;
+
+        void registerPropertyDefinitions(armarx::PropertyDefinitionsPtr& def);
+        void connect();
+
+        Properties
+        getProperties()
+        {
+            return this->p;
+        }
+
+        std::map<std::string, armarx::navigation::location::arondto::Location> getAllLocations();
+        std::map<std::string, armarx::navigation::location::arondto::Location>
+        getAllLocationsInGlobalFrame();
+
+    private:
+        Properties p;
+
+        const std::string propertyPrefix = "mem.nav.location";
+
+        armem::client::MemoryNameSystem& memoryNameSystem;
+        armarx::armem::obj::instance::Reader objReader;
+        armarx::armem::robot_state::RobotReader robotReader;
+
+        armarx::armem::client::Reader locationReader;
+    };
+
+} // namespace armarx::armem::locations::client
diff --git a/source/RobotAPI/libraries/armem_locations/frame_conversions.cpp b/source/RobotAPI/libraries/armem_locations/frame_conversions.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..50ef19ce29d8432970e47071ac3dc4358cef6745
--- /dev/null
+++ b/source/RobotAPI/libraries/armem_locations/frame_conversions.cpp
@@ -0,0 +1,6 @@
+#include "aron_conversions.h"
+
+namespace armarx::armem
+{
+
+}
diff --git a/source/RobotAPI/libraries/armem_locations/frame_conversions.h b/source/RobotAPI/libraries/armem_locations/frame_conversions.h
new file mode 100644
index 0000000000000000000000000000000000000000..876e6f9529fb83c88c5f7575daed6c7437f4b3f3
--- /dev/null
+++ b/source/RobotAPI/libraries/armem_locations/frame_conversions.h
@@ -0,0 +1,52 @@
+#pragma once
+
+#include <Eigen/Core>
+
+#include <ArmarXCore/core/exceptions/local/ExpressionException.h>
+
+#include <RobotAPI/libraries/ArmarXObjects/ObjectPose.h>
+#include <RobotAPI/libraries/armem_locations/aron/Location.aron.generated.h>
+#include <RobotAPI/libraries/core/FramedPose.h>
+
+namespace armarx::armem::locations
+{
+    void
+    toGlobal(armarx::navigation::location::arondto::Location& framedLoc,
+             const Eigen::Matrix4f& framedToGlobal)
+    {
+        if (framedLoc.framedPose.header.frame == armarx::GlobalFrame)
+        {
+            // No need to change to global
+            framedLoc.framedPose.header.agent = ""; // sanity set
+            return;
+        }
+
+        framedLoc.framedPose.pose = framedToGlobal * framedLoc.framedPose.pose;
+        framedLoc.framedPose.header.frame = armarx::GlobalFrame;
+        framedLoc.framedPose.header.agent = "";
+    }
+
+    void
+    toGlobal(armarx::navigation::location::arondto::Location& framedLoc,
+             const armarx::objpose::ObjectPose& objPose)
+    {
+        if (framedLoc.framedPose.header.frame == armarx::GlobalFrame)
+        {
+            // No need to change to global
+            framedLoc.framedPose.header.agent = ""; // sanity set
+            return;
+        }
+
+        if (simox::alg::starts_with(objPose.objectID.str(), framedLoc.framedPose.header.agent))
+        {
+            ARMARX_CHECK(framedLoc.framedPose.header.frame ==
+                         "root"); // TODO: Right now we only allow root
+            toGlobal(framedLoc, objPose.objectPoseGlobal);
+            return;
+        }
+
+        throw armarx::LocalException(
+            "Could not convert a framedLocation because the used object is wrong!");
+    }
+
+} // namespace armarx::armem::locations
diff --git a/source/RobotAPI/libraries/armem_objects/client/instance/ObjectReader.cpp b/source/RobotAPI/libraries/armem_objects/client/instance/ObjectReader.cpp
index 66bd99afbcf294f533a180bfe8727b1e73bc01a5..b2b740b735e933245a44bbfd3ce8d1c437ff30b2 100644
--- a/source/RobotAPI/libraries/armem_objects/client/instance/ObjectReader.cpp
+++ b/source/RobotAPI/libraries/armem_objects/client/instance/ObjectReader.cpp
@@ -88,7 +88,13 @@ namespace armarx::armem::obj::instance
 
         auto requestResult = objPoseStorage->requestObjects(req);
 
-        return requestResult.results.at(requestObject).result.success;
+        if (requestResult.results.count(requestObject))
+        {
+            return requestResult.results.at(requestObject).result.success;
+        }
+        return false;
+
+
     }
 
     std::optional<objpose::ObjectPose>
diff --git a/source/RobotAPI/libraries/armem_objects/client/instance/ObjectReader.h b/source/RobotAPI/libraries/armem_objects/client/instance/ObjectReader.h
index 0a77d4d0fe8e77557a5fb4659b52aa9b1be23035..81a0fc03092bbbe67c476d3e5f2146a28d62517a 100644
--- a/source/RobotAPI/libraries/armem_objects/client/instance/ObjectReader.h
+++ b/source/RobotAPI/libraries/armem_objects/client/instance/ObjectReader.h
@@ -74,6 +74,11 @@ namespace armarx::armem::obj::instance
             return this->p;
         }
 
+        objpose::ObjectPoseStorageInterfacePrx getObjectPoseStorage() const
+        {
+            return objPoseStorage;
+        }
+
     private:
         Properties p;
 
diff --git a/source/RobotAPI/libraries/armem_objects/server/instance/Segment.cpp b/source/RobotAPI/libraries/armem_objects/server/instance/Segment.cpp
index 03da4c2061d786b22fd1f126d9e8c2983e28faec..a5822667f61138a40a9f581de8dc68fb7fd812d6 100644
--- a/source/RobotAPI/libraries/armem_objects/server/instance/Segment.cpp
+++ b/source/RobotAPI/libraries/armem_objects/server/instance/Segment.cpp
@@ -1,59 +1,53 @@
 #include "Segment.h"
 
-#include <RobotAPI/libraries/ArmarXObjects/Scene.h>
-#include <RobotAPI/libraries/ArmarXObjects/json_conversions.h>
-
-#include <RobotAPI/libraries/armem_objects/aron/ObjectClass.aron.generated.h>
-#include <RobotAPI/libraries/armem_objects/aron/ObjectInstance.aron.generated.h>
-#include <RobotAPI/libraries/armem_objects/aron_conversions.h>
-#include <RobotAPI/libraries/armem_objects/memory_ids.h>
+#include <sstream>
 
-#include <RobotAPI/libraries/armem/core/aron_conversions.h>
-#include <RobotAPI/libraries/armem/core/error.h>
-#include <RobotAPI/libraries/armem/client/Writer.h>
-#include <RobotAPI/libraries/armem/client/query/Builder.h>
-#include <RobotAPI/libraries/armem/client/query/query_fns.h>
-#include <RobotAPI/libraries/armem/server/MemoryToIceAdapter.h>
-#include <RobotAPI/libraries/armem/util/util.h>
+#include <Eigen/Dense>
+#include <Eigen/Geometry>
 
+#include <SimoxUtility/algorithm/get_map_keys_values.h>
+#include <SimoxUtility/algorithm/string.h>
+#include <SimoxUtility/json.h>
+#include <SimoxUtility/math/pose/pose.h>
+#include <SimoxUtility/math/regression/linear.h>
 
-#include <RobotAPI/libraries/aron/common/aron_conversions.h>
+#include <ArmarXCore/core/ice_conversions/ice_conversions_templates.h>
+#include <ArmarXCore/core/logging/Logging.h>
+#include <ArmarXCore/core/system/cmake/CMakePackageFinder.h>
+#include <ArmarXCore/core/time/Clock.h>
+#include <ArmarXCore/core/time/DateTime.h>
+#include <ArmarXCore/core/time/ice_conversions.h>
 
 #include <RobotAPI/libraries/ArmarXObjects/ObjectFinder.h>
+#include <RobotAPI/libraries/ArmarXObjects/Scene.h>
+#include <RobotAPI/libraries/ArmarXObjects/aron/ObjectPose.aron.generated.h>
 #include <RobotAPI/libraries/ArmarXObjects/aron_conversions.h>
 #include <RobotAPI/libraries/ArmarXObjects/ice_conversions.h>
-#include <RobotAPI/libraries/ArmarXObjects/aron/ObjectPose.aron.generated.h>
-
+#include <RobotAPI/libraries/ArmarXObjects/json_conversions.h>
+#include <RobotAPI/libraries/armem/client/Writer.h>
+#include <RobotAPI/libraries/armem/client/query/Builder.h>
+#include <RobotAPI/libraries/armem/client/query/query_fns.h>
+#include <RobotAPI/libraries/armem/core/aron_conversions.h>
+#include <RobotAPI/libraries/armem/core/error.h>
+#include <RobotAPI/libraries/armem/server/MemoryToIceAdapter.h>
+#include <RobotAPI/libraries/armem/util/util.h>
+#include <RobotAPI/libraries/armem_objects/aron/ObjectClass.aron.generated.h>
+#include <RobotAPI/libraries/armem_objects/aron/ObjectInstance.aron.generated.h>
+#include <RobotAPI/libraries/armem_objects/aron_conversions.h>
+#include <RobotAPI/libraries/armem_objects/memory_ids.h>
 #include <RobotAPI/libraries/armem_robot/aron_conversions.h>
-
+#include <RobotAPI/libraries/aron/common/aron_conversions.h>
 #include <RobotAPI/libraries/core/FramedPose.h>
 #include <RobotAPI/libraries/core/remoterobot/RemoteRobot.h>
 
-#include "ArmarXCore/core/time/Clock.h"
-#include <ArmarXCore/core/ice_conversions/ice_conversions_templates.h>
-#include <ArmarXCore/core/logging/Logging.h>
-#include <ArmarXCore/core/system/cmake/CMakePackageFinder.h>
-#include <ArmarXCore/core/time/DateTime.h>
-#include <ArmarXCore/core/time/ice_conversions.h>
-
-#include <SimoxUtility/algorithm/get_map_keys_values.h>
-#include <SimoxUtility/algorithm/string.h>
-#include <SimoxUtility/json.h>
-#include <SimoxUtility/math/pose/pose.h>
-#include <SimoxUtility/math/regression/linear.h>
-
-#include <Eigen/Geometry>
-#include <Eigen/Dense>
-
-#include <sstream>
-
-
 namespace armarx::armem::server::obj::instance
 {
 
-    void Segment::Calibration::defineProperties(PropertyDefinitionsPtr defs, const std::string& prefix)
+    void
+    Segment::Calibration::defineProperties(PropertyDefinitionsPtr defs, const std::string& prefix)
     {
-        defs->optional(robotName, prefix + "robotName",
+        defs->optional(robotName,
+                       prefix + "robotName",
                        "Name of robot whose note can be calibrated.\n"
                        "If not given, the 'fallbackName' is used.");
         defs->optional(robotNode, prefix + "robotNode", "Robot node which can be calibrated.");
@@ -66,111 +60,126 @@ namespace armarx::armem::server::obj::instance
                                arondto::ObjectInstance::ToAronType(),
                                64)
     {
-        oobbCache.setFetchFn([this](const ObjectID & id) -> std::optional<simox::OrientedBoxf>
-        {
-            // Try to get OOBB from repository.
-            if (std::optional<ObjectInfo> objectInfo = objectFinder.findObject(id))
+        oobbCache.setFetchFn(
+            [this](const ObjectID& id) -> std::optional<simox::OrientedBoxf>
             {
-                try
+                // Try to get OOBB from repository.
+                if (std::optional<ObjectInfo> objectInfo = objectFinder.findObject(id))
                 {
-                    objectInfo->setLogError(false);  // Don't log missing files
-                    return objectInfo->loadOOBB();
+                    try
+                    {
+                        objectInfo->setLogError(false); // Don't log missing files
+                        return objectInfo->loadOOBB();
+                    }
+                    catch (const std::ios_base::failure& e)
+                    {
+                        // Give up - no OOBB information.
+                        ARMARX_WARNING << "Could not get OOBB of object " << id << ".\n- "
+                                       << e.what();
+                        return std::nullopt;
+                    }
                 }
-                catch (const std::ios_base::failure& e)
+                else
                 {
-                    // Give up - no OOBB information.
-                    ARMARX_WARNING << "Could not get OOBB of object " << id << ".\n- " << e.what();
                     return std::nullopt;
                 }
-            }
-            else
-            {
-                return std::nullopt;
-            }
-        });
+            });
 
-        classNameToDatasetCache.setFetchFn([this](const std::string & className)
-        {
-            std::optional<ObjectInfo> objectInfo = objectFinder.findObject(className);
-            return objectInfo ? objectInfo->dataset() : "";
-        });
+        classNameToDatasetCache.setFetchFn(
+            [this](const std::string& className)
+            {
+                std::optional<ObjectInfo> objectInfo = objectFinder.findObject(className);
+                return objectInfo ? objectInfo->dataset() : "";
+            });
     }
 
-
     Segment::~Segment()
     {
     }
 
-
-    void Segment::defineProperties(armarx::PropertyDefinitionsPtr defs, const std::string& prefix)
+    void
+    Segment::defineProperties(armarx::PropertyDefinitionsPtr defs, const std::string& prefix)
     {
         SpecializedCoreSegment::defineProperties(defs, prefix);
 
-        defs->optional(p.discardSnapshotsWhileAttached, prefix + "DiscardSnapshotsWhileAttached",
-                       "If true, no new snapshots are stored while an object is attached to a robot node.\n"
-                       "If false, new snapshots are stored, but the attachment is kept in the new snapshots.");
+        defs->optional(
+            p.discardSnapshotsWhileAttached,
+            prefix + "DiscardSnapshotsWhileAttached",
+            "If true, no new snapshots are stored while an object is attached to a robot node.\n"
+            "If false, new snapshots are stored, but the attachment is kept in the new snapshots.");
 
-        defs->optional(robots.fallbackName, prefix + "robots.FallbackName",
+        defs->optional(robots.fallbackName,
+                       prefix + "robots.FallbackName",
                        "Robot name to use as fallback if the robot name is not specified "
                        "in a provided object pose.");
 
-        defs->optional(p.sceneSnapshotsPackage, prefix + "scene.10_Package",
-                       "ArmarX package containing the scene snapshots.\n"
-                       "Scene snapshots are expected to be located in Package/data/Package/Scenes/*.json.");
-        defs->optional(p.sceneSnapshotsDirectory, prefix + "scene.11_Directory",
+        defs->optional(
+            p.sceneSnapshotsPackage,
+            prefix + "scene.10_Package",
+            "ArmarX package containing the scene snapshots.\n"
+            "Scene snapshots are expected to be located in Package/data/Package/Scenes/*.json.");
+        defs->optional(p.sceneSnapshotsDirectory,
+                       prefix + "scene.11_Directory",
                        "Directory in Package/data/Package/ containing the scene snapshots.");
 
-        std::vector<std::string> sceneSnapshotToLoadDescription =
-        {
+        std::vector<std::string> sceneSnapshotToLoadDescription = {
             "Scene(s) to load on startup.",
             "Specify multiple scenes in a ; separated list.",
             "Each entry must be one of the following:",
             "(1) A scene file in 'Package/scenes/' (with or without '.json' extension), "
             "e.g. 'MyScene', 'MyScene.json'",
-            "(2) A path to a scene file relative to 'Package/scenes/' (with or without '.json' extension), "
+            "(2) A path to a scene file relative to 'Package/scenes/' (with or without '.json' "
+            "extension), "
             "e.g. 'path/to/MyScene', 'path/to/MyScene.json'",
             "(3) An ArmarX data path to a scene file, e.g. 'Package/scenes/path/to/MyScene.json'",
         };
-        defs->optional(p.sceneSnapshotsToLoad, prefix + "scene.12_SnapshotToLoad",
+        defs->optional(p.sceneSnapshotsToLoad,
+                       prefix + "scene.12_SnapshotToLoad",
                        simox::alg::join(sceneSnapshotToLoadDescription, " \n"));
 
         decay.defineProperties(defs, prefix + "decay.");
     }
 
+    std::vector<std::string>
+    Segment::Properties::getSceneSnapshotsToLoad() const
+    {
+        if (sceneSnapshotsToLoad.empty())
+        {
+            return {};
+        }
+        bool trim = true;
+        return simox::alg::split(sceneSnapshotsToLoad, ";", trim);
+    }
 
-    void Segment::init()
+    void
+    Segment::init()
     {
         SpecializedCoreSegment::init();
 
-        if (not p.sceneSnapshotsToLoad.empty())
+        const std::vector<std::string> scenes = p.getSceneSnapshotsToLoad();
+        for (const std::string& scene : scenes)
         {
-            bool trim = true;
-            const std::vector<std::string> scenes = simox::alg::split(p.sceneSnapshotsToLoad, ";", trim);
-            for (const std::string& scene : scenes)
-            {
-                const bool lockMemory = false;
-                commitSceneSnapshotFromFilename(scene, lockMemory);
-            }
+            const bool lockMemory = false;
+            commitSceneSnapshotFromFilename(scene, lockMemory);
         }
 
         robots.setTag(Logging::tag);
     }
 
-
-    void Segment::connect(viz::Client arviz)
+    void
+    Segment::connect(viz::Client arviz)
     {
-        (void) arviz;
+        (void)arviz;
         // ARMARX_INFO << "ArticulatedObjectVisu";
         // this->visu = std::make_unique<ArticulatedObjectVisu>(arviz, *this);
         // visu->init();
     }
 
-
-    Segment::CommitStats Segment::commitObjectPoses(
-        const std::string& providerName,
-        const objpose::data::ProvidedObjectPoseSeq& providedPoses,
-        const Calibration& calibration,
-        std::optional<armem::Time> discardUpdatesUntil)
+    Segment::CommitStats
+    Segment::commitObjectPoses(const std::string& providerName,
+                               const objpose::data::ProvidedObjectPoseSeq& providedPoses,
+                               const Calibration& calibration,
+                               std::optional<armem::Time> discardUpdatesUntil)
     {
         CommitStats stats;
 
@@ -187,7 +196,8 @@ namespace armarx::armem::server::obj::instance
 
             // Check whether we have an old snapshot for this object.
             std::optional<objpose::ObjectPose> previousPose;
-            const wm::Entity* entity = findObjectEntity(armarx::fromIce(provided.objectID), providerName);
+            const wm::Entity* entity =
+                findObjectEntity(armarx::fromIce(provided.objectID), providerName);
             if (entity)
             {
                 const arondto::ObjectInstance data = getLatestInstanceData(*entity);
@@ -221,11 +231,13 @@ namespace armarx::armem::server::obj::instance
                 // Update the entity.
                 stats.numUpdated++;
 
-                VirtualRobot::RobotPtr robot = robots.get(provided.robotName, provided.providerName);
+                VirtualRobot::RobotPtr robot =
+                    robots.get(provided.robotName, provided.providerName);
 
-                if(not robot)
+                if (not robot)
                 {
-                    ARMARX_INFO << deactivateSpam(1) << "Failed to retrieve robot `" << provided.robotName << "`.";
+                    ARMARX_INFO << deactivateSpam(1) << "Failed to retrieve robot `"
+                                << provided.robotName << "`.";
                 }
 
                 // robot may be null!
@@ -233,10 +245,10 @@ namespace armarx::armem::server::obj::instance
                 // Update the robot to obtain correct local -> global transformation
                 if (robot and robotSyncTimestamp != timestamp)
                 {
-                    ARMARX_CHECK(robots.reader->synchronizeRobot(*robot, timestamp)) 
-                        << "Failed to synchronize robot to timestamp " << timestamp 
-                        << ". This is " << (Clock::Now() - timestamp).toSecondsDouble() << " seconds in the past.";
-                        
+                    ARMARX_CHECK(robots.reader->synchronizeRobot(*robot, timestamp))
+                        << "Failed to synchronize robot to timestamp " << timestamp << ". This is "
+                        << (Clock::Now() - timestamp).toSecondsDouble() << " seconds in the past.";
+
                     robotSyncTimestamp = timestamp;
 
 
@@ -244,7 +256,8 @@ namespace armarx::armem::server::obj::instance
                     {
                         if (calibration.offset != 0 and robot->hasRobotNode(calibration.robotNode))
                         {
-                            VirtualRobot::RobotNodePtr robotNode = robot->getRobotNode(calibration.robotNode);
+                            VirtualRobot::RobotNodePtr robotNode =
+                                robot->getRobotNode(calibration.robotNode);
 
                             float value = robotNode->getJointValue();
                             float newValue = value + calibration.offset;
@@ -255,7 +268,8 @@ namespace armarx::armem::server::obj::instance
                              * for the calibrated value.
                              * As this is just for perception (and not for controlling the robot), this should be fine^TM.
                              */
-                            VirtualRobot::RobotNode::JointLimits limits = robotNode->getJointLimits();
+                            VirtualRobot::RobotNode::JointLimits limits =
+                                robotNode->getJointLimits();
                             bool limitsChanged = false;
                             if (newValue < limits.low)
                             {
@@ -282,11 +296,11 @@ namespace armarx::armem::server::obj::instance
                 {
                     objpose::data::ProvidedObjectPose copy = provided;
                     copy.objectPoseFrame = armarx::GlobalFrame;
-                    newPose.fromProvidedPose(copy, robot);  // robot == nullptr is OK.
+                    newPose.fromProvidedPose(copy, robot); // robot == nullptr is OK.
                 }
                 else
                 {
-                    newPose.fromProvidedPose(provided, robot);  // robot == nullptr is OK.
+                    newPose.fromProvidedPose(provided, robot); // robot == nullptr is OK.
                 }
 
                 if (previousPose && previousPose->attachment)
@@ -299,10 +313,12 @@ namespace armarx::armem::server::obj::instance
                 if (newPose.objectID.dataset().empty())
                 {
                     // Try to find the data set.
-                    const std::string dataset = classNameToDatasetCache.get(newPose.objectID.className());
+                    const std::string dataset =
+                        classNameToDatasetCache.get(newPose.objectID.className());
                     if (!dataset.empty())
                     {
-                        newPose.objectID = { dataset, newPose.objectID.className(), newPose.objectID.instanceName() };
+                        newPose.objectID = {
+                            dataset, newPose.objectID.className(), newPose.objectID.instanceName()};
                     }
                 }
                 if (!provided.localOOBB)
@@ -318,8 +334,8 @@ namespace armarx::armem::server::obj::instance
         return stats;
     }
 
-
-    void Segment::commitObjectPoses(const ObjectPoseSeq& objectPoses, const std::string& providerName)
+    void
+    Segment::commitObjectPoses(const ObjectPoseSeq& objectPoses, const std::string& providerName)
     {
         Time now = Time::Now();
 
@@ -332,7 +348,7 @@ namespace armarx::armem::server::obj::instance
             EntityUpdate& update = commit.updates.emplace_back();
 
             const MemoryID providerID = coreSegmentID.withProviderSegmentName(
-                                            providerName.empty() ? pose.providerName : providerName);
+                providerName.empty() ? pose.providerName : providerName);
 
             update.entityID = providerID.withEntityName(pose.objectID.str());
             update.arrivedTime = now;
@@ -352,13 +368,11 @@ namespace armarx::armem::server::obj::instance
             }
             toAron(dto.sourceID, MemoryID());
             update.instancesData.push_back(dto.toAron());
-
         }
         // Commit non-locking.
         iceMemory.commit(commit);
     }
 
-
     objpose::ObjectPoseMap
     Segment::getObjectPoses(const DateTime& now)
     {
@@ -367,20 +381,16 @@ namespace armarx::armem::server::obj::instance
         return filterObjectPoses(objectPoses);
     }
 
-
-
     objpose::ObjectPoseMap
-    Segment::getObjectPosesByProvider(
-        const std::string& providerName,
-        const DateTime& now)
+    Segment::getObjectPosesByProvider(const std::string& providerName, const DateTime& now)
     {
         ARMARX_CHECK_NOT_NULL(segmentPtr);
-        ObjectPoseMap objectPoses = getLatestObjectPoses(segmentPtr->getProviderSegment(providerName));
+        ObjectPoseMap objectPoses =
+            getLatestObjectPoses(segmentPtr->getProviderSegment(providerName));
         updateObjectPoses(objectPoses, now);
         return filterObjectPoses(objectPoses);
     }
 
-
     wm::Entity*
     Segment::findObjectEntity(const ObjectID& objectID, const std::string& providerName)
     {
@@ -389,15 +399,16 @@ namespace armarx::armem::server::obj::instance
         if (providerName.empty())
         {
             wm::Entity* result = nullptr;
-            segmentPtr->forEachProviderSegment([&result, &entityID](wm::ProviderSegment & prov)
-            {
-                if (prov.hasEntity(entityID.entityName))
+            segmentPtr->forEachProviderSegment(
+                [&result, &entityID](wm::ProviderSegment& prov)
                 {
-                    result = &prov.getEntity(entityID);
-                    return false;
-                }
-                return true;
-            });
+                    if (prov.hasEntity(entityID.entityName))
+                    {
+                        result = &prov.getEntity(entityID);
+                        return false;
+                    }
+                    return true;
+                });
             return result;
         }
         else
@@ -415,24 +426,24 @@ namespace armarx::armem::server::obj::instance
         }
     }
 
-
-    void Segment::updateObjectPoses(ObjectPoseMap& objectPoses, const DateTime& now)
+    void
+    Segment::updateObjectPoses(ObjectPoseMap& objectPoses, const DateTime& now)
     {
         bool agentSynchronized = false;
 
         for (auto& [id, objectPose] : objectPoses)
         {
-            VirtualRobot::RobotPtr robot = robots.get(objectPose.robotName, objectPose.providerName);
+            VirtualRobot::RobotPtr robot =
+                robots.get(objectPose.robotName, objectPose.providerName);
             updateObjectPose(objectPose, now, robot, agentSynchronized);
         }
     }
 
-
-    void Segment::updateObjectPoses(
-        ObjectPoseMap& objectPoses,
-        const DateTime& now,
-        VirtualRobot::RobotPtr agent,
-        bool& agentSynchronized) const
+    void
+    Segment::updateObjectPoses(ObjectPoseMap& objectPoses,
+                               const DateTime& now,
+                               VirtualRobot::RobotPtr agent,
+                               bool& agentSynchronized) const
     {
         for (auto& [id, objectPose] : objectPoses)
         {
@@ -440,12 +451,11 @@ namespace armarx::armem::server::obj::instance
         }
     }
 
-
-    void Segment::updateObjectPose(
-        ObjectPose& objectPose,
-        const DateTime& now,
-        VirtualRobot::RobotPtr agent,
-        bool& agentSynchronized) const
+    void
+    Segment::updateObjectPose(ObjectPose& objectPose,
+                              const DateTime& now,
+                              VirtualRobot::RobotPtr agent,
+                              bool& agentSynchronized) const
     {
         updateAttachement(objectPose, agent, agentSynchronized);
 
@@ -455,8 +465,8 @@ namespace armarx::armem::server::obj::instance
         }
     }
 
-
-    Segment::ObjectPoseMap Segment::filterObjectPoses(const ObjectPoseMap& objectPoses) const
+    Segment::ObjectPoseMap
+    Segment::filterObjectPoses(const ObjectPoseMap& objectPoses) const
     {
         ObjectPoseMap result;
         for (const auto& [id, objectPose] : objectPoses)
@@ -469,9 +479,10 @@ namespace armarx::armem::server::obj::instance
         return result;
     }
 
-
-    void Segment::updateAttachement(
-        ObjectPose& objectPose, VirtualRobot::RobotPtr agent, bool& synchronized) const
+    void
+    Segment::updateAttachement(ObjectPose& objectPose,
+                               VirtualRobot::RobotPtr agent,
+                               bool& synchronized) const
     {
         if (not objectPose.attachment.has_value())
         {
@@ -487,7 +498,7 @@ namespace armarx::armem::server::obj::instance
         }
         ARMARX_CHECK_NOT_NULL(agent);
 
-        if (not synchronized)  // Synchronize only once.
+        if (not synchronized) // Synchronize only once.
         {
             ARMARX_CHECK_NOT_NULL(robots.reader);
 
@@ -499,7 +510,6 @@ namespace armarx::armem::server::obj::instance
         objectPose.updateAttached(agent);
     }
 
-
     objpose::ObjectPoseMap
     Segment::getLatestObjectPoses() const
     {
@@ -507,7 +517,6 @@ namespace armarx::armem::server::obj::instance
         return getLatestObjectPoses(*segmentPtr);
     }
 
-
     objpose::ObjectPoseMap
     Segment::getLatestObjectPoses(const wm::CoreSegment& coreSeg)
     {
@@ -516,7 +525,6 @@ namespace armarx::armem::server::obj::instance
         return result;
     }
 
-
     objpose::ObjectPoseMap
     Segment::getLatestObjectPoses(const wm::ProviderSegment& provSeg)
     {
@@ -525,7 +533,6 @@ namespace armarx::armem::server::obj::instance
         return result;
     }
 
-
     objpose::ObjectPose
     Segment::getLatestObjectPose(const wm::Entity& entity)
     {
@@ -534,51 +541,51 @@ namespace armarx::armem::server::obj::instance
         return result;
     }
 
-
-    void Segment::getLatestObjectPoses(const wm::CoreSegment& coreSeg, ObjectPoseMap& out)
+    void
+    Segment::getLatestObjectPoses(const wm::CoreSegment& coreSeg, ObjectPoseMap& out)
     {
-        coreSeg.forEachProviderSegment([&out](const wm::ProviderSegment & provSegment)
-        {
-            getLatestObjectPoses(provSegment, out);
-        });
+        coreSeg.forEachProviderSegment([&out](const wm::ProviderSegment& provSegment)
+                                       { getLatestObjectPoses(provSegment, out); });
     }
 
-
-    void Segment::getLatestObjectPoses(const wm::ProviderSegment& provSegment, ObjectPoseMap& out)
+    void
+    Segment::getLatestObjectPoses(const wm::ProviderSegment& provSegment, ObjectPoseMap& out)
     {
-        provSegment.forEachEntity([&out](const wm::Entity & entity)
-        {
-            if (!entity.empty())
+        provSegment.forEachEntity(
+            [&out](const wm::Entity& entity)
             {
-                ObjectPose pose = getLatestObjectPose(entity);
-                // Try to insert. Fails and returns false if an entry already exists.
-                const auto [it, success] = out.insert({pose.objectID, pose});
-                if (!success)
+                if (!entity.empty())
                 {
-                    // An entry with that ID already exists. We keep the newest.
-                    if (it->second.timestamp < pose.timestamp)
+                    ObjectPose pose = getLatestObjectPose(entity);
+                    // Try to insert. Fails and returns false if an entry already exists.
+                    const auto [it, success] = out.insert({pose.objectID, pose});
+                    if (!success)
                     {
-                        it->second = pose;
+                        // An entry with that ID already exists. We keep the newest.
+                        if (it->second.timestamp < pose.timestamp)
+                        {
+                            it->second = pose;
+                        }
                     }
                 }
-            }
-        });
+            });
     }
 
-
-    void Segment::getLatestObjectPose(const wm::Entity& entity, ObjectPose& out)
+    void
+    Segment::getLatestObjectPose(const wm::Entity& entity, ObjectPose& out)
     {
-        entity.getLatestSnapshot().forEachInstance([&out](const wm::EntityInstance & instance)
-        {
-            arondto::ObjectInstance dto;
-            dto.fromAron(instance.data());
+        entity.getLatestSnapshot().forEachInstance(
+            [&out](const wm::EntityInstance& instance)
+            {
+                arondto::ObjectInstance dto;
+                dto.fromAron(instance.data());
 
-            fromAron(dto, out);
-        });
+                fromAron(dto, out);
+            });
     }
 
-
-    arondto::ObjectInstance Segment::getLatestInstanceData(const wm::Entity& entity)
+    arondto::ObjectInstance
+    Segment::getLatestInstanceData(const wm::Entity& entity)
     {
         ARMARX_CHECK_GREATER_EQUAL(entity.size(), 1);
         const wm::EntitySnapshot& snapshot = entity.getLatestSnapshot();
@@ -592,7 +599,6 @@ namespace armarx::armem::server::obj::instance
         return data;
     }
 
-
     ::armarx::armem::articulated_object::ArticulatedObjects
     Segment::getArticulatedObjects()
     {
@@ -601,7 +607,7 @@ namespace armarx::armem::server::obj::instance
         ARMARX_INFO << "Found " << objectPoses.size() << " object poses";
 
         ::armarx::armem::articulated_object::ArticulatedObjects objects;
-        for (const auto&[objectId, objectPose] : objectPoses)
+        for (const auto& [objectId, objectPose] : objectPoses)
         {
             armem::articulated_object::ArticulatedObject articulatedObject;
             articulatedObject.config.jointMap = objectPose.objectJointValues;
@@ -625,7 +631,6 @@ namespace armarx::armem::server::obj::instance
 
                     fromAron(dto, description);
                     articulatedObject.description = description;
-
                 }
                 catch (...)
                 {
@@ -648,7 +653,6 @@ namespace armarx::armem::server::obj::instance
         return objects;
     }
 
-
     std::map<DateTime, objpose::ObjectPose>
     Segment::getObjectPosesInRange(const wm::Entity& entity,
                                    const DateTime& start,
@@ -677,14 +681,14 @@ namespace armarx::armem::server::obj::instance
         return result;
     }
 
-
-    std::optional<simox::OrientedBoxf> Segment::getObjectOOBB(const ObjectID& id)
+    std::optional<simox::OrientedBoxf>
+    Segment::getObjectOOBB(const ObjectID& id)
     {
         return oobbCache.get(id);
     }
 
-
-    objpose::ProviderInfo Segment::getProviderInfo(const std::string& providerName)
+    objpose::ProviderInfo
+    Segment::getProviderInfo(const std::string& providerName)
     {
         try
         {
@@ -703,14 +707,13 @@ namespace armarx::armem::server::obj::instance
         }
     }
 
-
     objpose::AttachObjectToRobotNodeOutput
     Segment::attachObjectToRobotNode(const objpose::AttachObjectToRobotNodeInput& input)
     {
         const armem::Time now = armem::Time::Now();
 
         objpose::AttachObjectToRobotNodeOutput output;
-        output.success = false;  // We are not successful until proven otherwise.
+        output.success = false; // We are not successful until proven otherwise.
 
         ObjectID objectID = armarx::fromIce(input.objectID);
 
@@ -718,7 +721,8 @@ namespace armarx::armem::server::obj::instance
         if (not agent)
         {
             std::stringstream ss;
-            ss << "Tried to attach object " << objectID << " to unknown agent '" << input.agentName << "'."
+            ss << "Tried to attach object " << objectID << " to unknown agent '" << input.agentName
+               << "'."
                << "\n(You can leave the agent name empty if there is only one agent.)\n"
                << "\nKnown agents: ";
             for (const auto& [name, robot] : robots.loaded)
@@ -732,8 +736,8 @@ namespace armarx::armem::server::obj::instance
 
         if (!agent->hasRobotNode(input.frameName))
         {
-            ARMARX_WARNING << "Tried to attach object " << objectID << " to unknown node '" << input.frameName
-                           << "' of agent '" << agent->getName() << "'.";
+            ARMARX_WARNING << "Tried to attach object " << objectID << " to unknown node '"
+                           << input.frameName << "' of agent '" << agent->getName() << "'.";
             return output;
         }
         std::string frameName = input.frameName;
@@ -744,7 +748,8 @@ namespace armarx::armem::server::obj::instance
         if (!objectEntity || objectEntity->empty())
         {
             ARMARX_WARNING << "Tried to attach object " << objectID << " to node '" << frameName
-                           << "' of agent '" << agent->getName() << "', but object is currently not provided.";
+                           << "' of agent '" << agent->getName()
+                           << "', but object is currently not provided.";
             return output;
         }
         arondto::ObjectInstance data = getLatestInstanceData(*objectEntity);
@@ -764,7 +769,8 @@ namespace armarx::armem::server::obj::instance
             const auto timestamp = armarx::Clock::Now();
             ARMARX_CHECK(robots.reader->synchronizeRobot(*agent, timestamp));
 
-            armarx::FramedPose framed(data.pose.objectPoseGlobal, armarx::GlobalFrame, agent->getName());
+            armarx::FramedPose framed(
+                data.pose.objectPoseGlobal, armarx::GlobalFrame, agent->getName());
             if (frameName == armarx::GlobalFrame)
             {
                 info.poseInFrame = framed.toGlobalEigen(agent);
@@ -779,21 +785,23 @@ namespace armarx::armem::server::obj::instance
         // Store attachment in new entity snapshot.
         {
             armem::Commit commit;
-            armem::EntityUpdate & update = commit.add();
+            armem::EntityUpdate& update = commit.add();
             update.entityID = objectEntity->id();
             update.referencedTime = now;
             {
                 arondto::ObjectInstance updated = data;
                 toAron(updated.pose.attachment, info);
                 updated.pose.attachmentValid = true;
-                update.instancesData = { updated.toAron() };
+                update.instancesData = {updated.toAron()};
             }
             iceMemory.commit(commit);
         }
 
-        ARMARX_INFO << "Attached object " << objectID << " by provider '" << data.pose.providerName << "' "
+        ARMARX_INFO << "Attached object " << objectID << " by provider '" << data.pose.providerName
+                    << "' "
                     << "to node '" << info.frameName << "' of agent '" << info.agentName << "'.\n"
-                    << "Object pose in frame: \n" << info.poseInFrame;
+                    << "Object pose in frame: \n"
+                    << info.poseInFrame;
 
         output.success = true;
         output.attachment = new objpose::data::ObjectAttachmentInfo();
@@ -804,10 +812,8 @@ namespace armarx::armem::server::obj::instance
         return output;
     }
 
-
     objpose::DetachObjectFromRobotNodeOutput
-    Segment::detachObjectFromRobotNode(
-        const objpose::DetachObjectFromRobotNodeInput& input)
+    Segment::detachObjectFromRobotNode(const objpose::DetachObjectFromRobotNodeInput& input)
     {
         const armem::Time now = armem::Time::Now();
 
@@ -840,19 +846,20 @@ namespace armarx::armem::server::obj::instance
         output.wasAttached = bool(attachment);
         if (attachment)
         {
-            ARMARX_INFO << "Detached object " << objectID << " by provider '" << providerName << "' from robot node '"
-                        << attachment->frameName << "' of agent '" << attachment->agentName << "'.";
+            ARMARX_INFO << "Detached object " << objectID << " by provider '" << providerName
+                        << "' from robot node '" << attachment->frameName << "' of agent '"
+                        << attachment->agentName << "'.";
         }
         else
         {
-            ARMARX_INFO << "Tried to detach object " << objectID << " by provider '" << providerName << "' "
+            ARMARX_INFO << "Tried to detach object " << objectID << " by provider '" << providerName
+                        << "' "
                         << "from robot node, but it was not attached.";
         }
 
         return output;
     }
 
-
     objpose::DetachAllObjectsFromRobotNodesOutput
     Segment::detachAllObjectsFromRobotNodes(
         const objpose::DetachAllObjectsFromRobotNodesInput& input)
@@ -863,31 +870,31 @@ namespace armarx::armem::server::obj::instance
 
         objpose::DetachAllObjectsFromRobotNodesOutput output;
         output.numDetached = 0;
-        segmentPtr->forEachEntity([this, now, &input, &output](wm::Entity & entity)
-        {
-            const arondto::ObjectInstance data = this->getLatestInstanceData(entity);
-            if (data.pose.attachmentValid)
+        segmentPtr->forEachEntity(
+            [this, now, &input, &output](wm::Entity& entity)
             {
-                ++output.numDetached;
-                // Store non-attached pose in new snapshot.
-                this->storeDetachedSnapshot(entity, data, now, input.commitAttachedPose);
-            }
-        });
+                const arondto::ObjectInstance data = this->getLatestInstanceData(entity);
+                if (data.pose.attachmentValid)
+                {
+                    ++output.numDetached;
+                    // Store non-attached pose in new snapshot.
+                    this->storeDetachedSnapshot(entity, data, now, input.commitAttachedPose);
+                }
+            });
 
         ARMARX_INFO << "Detached all objects (" << output.numDetached << ") from robot nodes.";
 
         return output;
     }
 
-
-    void Segment::storeDetachedSnapshot(
-        wm::Entity& entity,
-        const arondto::ObjectInstance& data,
-        Time now,
-        bool commitAttachedPose)
+    void
+    Segment::storeDetachedSnapshot(wm::Entity& entity,
+                                   const arondto::ObjectInstance& data,
+                                   Time now,
+                                   bool commitAttachedPose)
     {
         armem::Commit commit;
-        armem::EntityUpdate & update = commit.add();
+        armem::EntityUpdate& update = commit.add();
         update.entityID = entity.id();
         update.referencedTime = now;
         {
@@ -897,7 +904,8 @@ namespace armarx::armem::server::obj::instance
                 ObjectPose objectPose;
                 fromAron(data, objectPose);
 
-                VirtualRobot::RobotPtr robot = robots.get(objectPose.robotName, objectPose.providerName);
+                VirtualRobot::RobotPtr robot =
+                    robots.get(objectPose.robotName, objectPose.providerName);
                 bool agentSynchronized = false;
                 updateAttachement(objectPose, robot, agentSynchronized);
 
@@ -911,34 +919,34 @@ namespace armarx::armem::server::obj::instance
                 toAron(updated.pose.attachment, objpose::ObjectAttachmentInfo{});
             }
 
-            update.instancesData = { updated.toAron() };
+            update.instancesData = {updated.toAron()};
         }
         iceMemory.commit(commit);
     }
 
-
     std::optional<wm::EntityInstance>
     Segment::findClassInstance(const ObjectID& objectID) const
     {
-        const ObjectID classID = { objectID.dataset(), objectID.className() };
+        const ObjectID classID = {objectID.dataset(), objectID.className()};
         try
         {
             std::optional<wm::EntityInstance> result;
             iceMemory.workingMemory->getCoreSegment("Class").forEachProviderSegment(
-                [&classID, &result](const wm::ProviderSegment & provSeg)
-            {
-                if (provSeg.hasEntity(classID.str()))
+                [&classID, &result](const wm::ProviderSegment& provSeg)
                 {
-                    result = provSeg.getEntity(classID.str()).getLatestSnapshot().getInstance(0);
-                    return false;
-                }
-                return true;
-            });
+                    if (provSeg.hasEntity(classID.str()))
+                    {
+                        result =
+                            provSeg.getEntity(classID.str()).getLatestSnapshot().getInstance(0);
+                        return false;
+                    }
+                    return true;
+                });
 
             if (not result.has_value())
             {
-                ARMARX_WARNING << deactivateSpam(120)
-                               << "No provider segment for classID " << classID.str() << " found";
+                ARMARX_WARNING << deactivateSpam(120) << "No provider segment for classID "
+                               << classID.str() << " found";
             }
             return result;
         }
@@ -950,12 +958,11 @@ namespace armarx::armem::server::obj::instance
         }
     }
 
-
-    void Segment::storeScene(const std::string& filename, const armarx::objects::Scene& scene)
+    void
+    Segment::storeScene(const std::string& filename, const armarx::objects::Scene& scene)
     {
         if (const std::optional<std::filesystem::path> path = resolveSceneFilepath(filename))
         {
-
             ARMARX_INFO << "Storing scene snapshot at: \n" << path.value();
             try
             {
@@ -968,7 +975,6 @@ namespace armarx::armem::server::obj::instance
         }
     }
 
-
     std::optional<armarx::objects::Scene>
     Segment::loadScene(const std::string& filename)
     {
@@ -982,7 +988,6 @@ namespace armarx::armem::server::obj::instance
         }
     }
 
-
     std::optional<armarx::objects::Scene>
     Segment::loadScene(const std::filesystem::path& path)
     {
@@ -997,57 +1002,56 @@ namespace armarx::armem::server::obj::instance
         }
     }
 
-
     const std::string Segment::timestampPlaceholder = "%TIMESTAMP";
 
-
     std::optional<std::filesystem::path>
     Segment::resolveSceneFilepath(const std::string& _filename)
     {
-        std::string filepath = _filename;
+        std::stringstream log;
+        std::filesystem::path filepath = _filename;
 
-        filepath = simox::alg::replace_all(filepath, timestampPlaceholder,
-                                           Time::Now().toString("%Y-%m-%d_%H-%M-%S"));
+        filepath = simox::alg::replace_all(
+            filepath, timestampPlaceholder, Time::Now().toString("%Y-%m-%d_%H-%M-%S"));
         if (not simox::alg::ends_with(filepath, ".json"))
         {
             filepath += ".json";
         }
 
-        // Try to interprete it as relative to 'Package/scenes/'.
-        if (!finder)
+        if (filepath.is_absolute())
         {
-            finder.reset(new CMakePackageFinder(p.sceneSnapshotsPackage));
-            if (not finder->packageFound())
-            {
-                ARMARX_WARNING << "Could not find CMake package " << p.sceneSnapshotsPackage << ".";
-            }
+            return filepath;
         }
-        if (finder->packageFound())
+
+        armarx::PackagePath packagePath = [&filepath, this]()
         {
-            std::filesystem::path absDataDir = finder->getDataDir();
-            std::filesystem::path absPath = absDataDir / p.sceneSnapshotsPackage
-                    / p.sceneSnapshotsDirectory / filepath;
-            if (std::filesystem::is_regular_file(absPath))
+            if (filepath.has_parent_path())
             {
-                return absPath;
+                // Interpret the first component as package name.
+                std::string packageName = *filepath.begin();
+                return PackagePath(packageName, std::filesystem::relative(filepath, packageName));
             }
-        }
-
-        // Try to interprete it as ArmarXDataPath.
-        {
-            std::string resolved = ArmarXDataPath::resolvePath(filepath);
-            if (resolved != filepath)
+            else
             {
-                return resolved;
+                // Only a filename => Interprete it as relative to 'Package/scenes/'.
+                return PackagePath(p.sceneSnapshotsPackage, p.sceneSnapshotsDirectory / filepath);
             }
-        }
+        }();
 
-        // Else: Fail
-        return std::nullopt;
+        try
+        {
+            std::filesystem::path systemPath = packagePath.toSystemPath();
+            return systemPath;
+        }
+        catch (const armarx::PackageNotFoundException& e)
+        {
+            ARMARX_INFO << "Could not interpret '" << packagePath.serialize().package
+                        << "' as ArmarX package name (" << e.what() << ").";
+            return std::nullopt;
+        }
     }
 
-
-    armarx::objects::Scene Segment::getSceneSnapshot() const
+    armarx::objects::Scene
+    Segment::getSceneSnapshot() const
     {
         using armarx::objects::SceneObject;
 
@@ -1060,36 +1064,42 @@ namespace armarx::armem::server::obj::instance
         };
 
         std::map<ObjectID, StampedSceneObject> objects;
-        segmentPtr->forEachEntity([&objects](wm::Entity & entity)
-        {
-            const wm::EntityInstance* entityInstance = entity.findLatestInstance();
-            if (entityInstance)
+        segmentPtr->forEachEntity(
+            [&objects](wm::Entity& entity)
             {
-                std::optional<arondto::ObjectInstance> objectInstance = tryCast<arondto::ObjectInstance>(*entityInstance);
-                if (objectInstance)
+                const wm::EntityInstance* entityInstance = entity.findLatestInstance();
+                if (entityInstance)
                 {
-                    const ObjectID objectID = ObjectID::FromString(objectInstance->classID.entityName);
-
-                    auto it = objects.find(objectID);
-                    if (it == objects.end() or objectInstance->pose.timestamp > it->second.timestamp)
+                    std::optional<arondto::ObjectInstance> objectInstance =
+                        tryCast<arondto::ObjectInstance>(*entityInstance);
+                    if (objectInstance)
                     {
-                        StampedSceneObject& stamped = objects[objectID];
-                        stamped.timestamp = objectInstance->pose.timestamp;
+                        const ObjectID objectID =
+                            ObjectID::FromString(objectInstance->classID.entityName);
 
-                        SceneObject& object = stamped.object;
-                        object.className = objectID.getClassID().str();
-                        object.instanceName = objectID.instanceName();
-                        object.collection = "";
+                        auto it = objects.find(objectID);
+                        if (it == objects.end() or
+                            objectInstance->pose.timestamp > it->second.timestamp)
+                        {
+                            StampedSceneObject& stamped = objects[objectID];
+                            stamped.timestamp = objectInstance->pose.timestamp;
 
-                        object.position = simox::math::position(objectInstance->pose.objectPoseGlobal);
-                        object.orientation = simox::math::orientation(objectInstance->pose.objectPoseGlobal);
+                            SceneObject& object = stamped.object;
+                            object.className = objectID.getClassID().str();
+                            object.instanceName = objectID.instanceName();
+                            object.collection = "";
 
-                        object.isStatic = objectInstance->pose.isStatic;
-                        object.jointValues = objectInstance->pose.objectJointValues;
+                            object.position =
+                                simox::math::position(objectInstance->pose.objectPoseGlobal);
+                            object.orientation =
+                                simox::math::orientation(objectInstance->pose.objectPoseGlobal);
+
+                            object.isStatic = objectInstance->pose.isStatic;
+                            object.jointValues = objectInstance->pose.objectJointValues;
+                        }
                     }
                 }
-            }
-        });
+            });
 
         armarx::objects::Scene scene;
         for (const auto& [id, stamped] : objects)
@@ -1099,8 +1109,8 @@ namespace armarx::armem::server::obj::instance
         return scene;
     }
 
-
-    void Segment::commitSceneSnapshot(const armarx::objects::Scene& scene, const std::string& sceneName)
+    void
+    Segment::commitSceneSnapshot(const armarx::objects::Scene& scene, const std::string& sceneName)
     {
         const Time now = Time::Now();
         std::map<ObjectID, int> idCounters;
@@ -1117,11 +1127,9 @@ namespace armarx::armem::server::obj::instance
             pose.objectType = objpose::ObjectType::KnownObject;
             // If not specified, assume loaded objects are static.
             pose.isStatic = object.isStatic.has_value() ? object.isStatic.value() : true;
-            pose.objectID = classID.withInstanceName(
-                                object.instanceName.empty()
-                                ? std::to_string(idCounters[classID]++)
-                                : object.instanceName
-                            );
+            pose.objectID = classID.withInstanceName(object.instanceName.empty()
+                                                         ? std::to_string(idCounters[classID]++)
+                                                         : object.instanceName);
 
             pose.objectPoseGlobal = simox::math::pose(object.position, object.orientation);
             pose.objectPoseRobot = pose.objectPoseGlobal;
@@ -1142,8 +1150,8 @@ namespace armarx::armem::server::obj::instance
         commitObjectPoses(objectPoses);
     }
 
-
-    void Segment::commitSceneSnapshotFromFilename(const std::string& filename, bool lockMemory)
+    void
+    Segment::commitSceneSnapshotFromFilename(const std::string& filename, bool lockMemory)
     {
         std::stringstream ss;
         ss << "Loading scene '" << filename << "' ...";
@@ -1156,7 +1164,7 @@ namespace armarx::armem::server::obj::instance
                 auto makeSceneName = [](const std::filesystem::path& path)
                 {
                     std::filesystem::path filename = path.filename();
-                    filename.replace_extension();  // Removes extension
+                    filename.replace_extension(); // Removes extension
                     return filename.string();
                 };
                 std::string sceneName = makeSceneName(path.value());
@@ -1164,10 +1172,8 @@ namespace armarx::armem::server::obj::instance
                 // The check seems useless?
                 if (lockMemory)
                 {
-                    segmentPtr->doLocked([this,&snapshot, &sceneName]()
-                    {
-                        commitSceneSnapshot(snapshot.value(), sceneName);
-                    });
+                    segmentPtr->doLocked([this, &snapshot, &sceneName]()
+                                         { commitSceneSnapshot(snapshot.value(), sceneName); });
                 }
                 else
                 {
@@ -1181,8 +1187,8 @@ namespace armarx::armem::server::obj::instance
         }
     }
 
-
-    void Segment::RemoteGui::setup(const Segment& data)
+    void
+    Segment::RemoteGui::setup(const Segment& data)
     {
         using namespace armarx::RemoteGui::Client;
 
@@ -1191,18 +1197,33 @@ namespace armarx::armem::server::obj::instance
         infiniteHistory.setValue(data.properties.maxHistorySize == -1);
         discardSnapshotsWhileAttached.setValue(data.p.discardSnapshotsWhileAttached);
 
-        storeLoadLine.setValue("Scene_" + timestampPlaceholder);
+        const std::string storeLoadPath = [&data]()
+        {
+            const std::vector<std::string> scenes = data.p.getSceneSnapshotsToLoad();
+            if (scenes.empty())
+            {
+                std::string storeLoadFilename = "Scene_" + timestampPlaceholder;
+                return data.p.sceneSnapshotsPackage + "/" + data.p.sceneSnapshotsToLoad;
+            }
+            else
+            {
+                return scenes.front();
+            }
+        }();
+
+        storeLoadLine.setValue(storeLoadPath);
         loadButton.setLabel("Load Scene");
         storeButton.setLabel("Store Scene");
 
-        HBoxLayout storeLoadLineLayout(
-        {
-            Label(data.p.sceneSnapshotsPackage + "/" + data.p.sceneSnapshotsDirectory + "/"),
-            storeLoadLine,
-            Label(".json")
-        });
+        HBoxLayout storeLoadLineLayout({storeLoadLine, Label(".json")});
         HBoxLayout storeLoadButtonsLayout({loadButton, storeButton});
 
+        detachAllObjectsButton.setLabel("Detach All Objects");
+        detachAllObjectsCommitAttachedPoseCheckBox.setValue(true);
+        HBoxLayout detachAllObjectsCommitAttachedPoseLayout(
+            {Label("Commit Attached Pose"), detachAllObjectsCommitAttachedPoseCheckBox});
+
+
         GridLayout grid;
         int row = 0;
 
@@ -1215,15 +1236,19 @@ namespace armarx::armem::server::obj::instance
         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});
+        grid.add(Label("Discard Snapshots while Attached"), {row, 0})
+            .add(discardSnapshotsWhileAttached, {row, 1});
         row++;
 
+        grid.add(detachAllObjectsButton, {row, 0})
+            .add(detachAllObjectsCommitAttachedPoseLayout, {row, 1});
+
         group.setLabel("Data");
         group.addChild(grid);
     }
 
-
-    void Segment::RemoteGui::update(Segment& segment)
+    void
+    Segment::RemoteGui::update(Segment& segment)
     {
         if (loadButton.wasClicked())
         {
@@ -1234,41 +1259,51 @@ namespace armarx::armem::server::obj::instance
         if (storeButton.wasClicked())
         {
             armarx::objects::Scene scene;
-            segment.doLocked([&scene, &segment]()
-            {
-                scene = segment.getSceneSnapshot();
-            });
+            segment.doLocked([&scene, &segment]() { scene = segment.getSceneSnapshot(); });
             segment.storeScene(storeLoadLine.getValue(), scene);
         }
 
-        if (infiniteHistory.hasValueChanged()
-            || maxHistorySize.hasValueChanged()
-            || discardSnapshotsWhileAttached.hasValueChanged())
+        if (infiniteHistory.hasValueChanged() || maxHistorySize.hasValueChanged() ||
+            discardSnapshotsWhileAttached.hasValueChanged())
         {
-            segment.doLocked([this, &segment]()
-            {
-                if (infiniteHistory.hasValueChanged() || maxHistorySize.hasValueChanged())
+            segment.doLocked(
+                [this, &segment]()
                 {
-                    segment.properties.maxHistorySize = infiniteHistory.getValue() ? -1 : maxHistorySize.getValue();
-                    if (segment.segmentPtr)
+                    if (infiniteHistory.hasValueChanged() || maxHistorySize.hasValueChanged())
                     {
-                        segment.segmentPtr->setMaxHistorySize(long(segment.properties.maxHistorySize));
+                        segment.properties.maxHistorySize =
+                            infiniteHistory.getValue() ? -1 : maxHistorySize.getValue();
+                        if (segment.segmentPtr)
+                        {
+                            segment.segmentPtr->setMaxHistorySize(
+                                long(segment.properties.maxHistorySize));
+                        }
                     }
-                }
 
-                segment.p.discardSnapshotsWhileAttached = discardSnapshotsWhileAttached.getValue();
-            });
+                    segment.p.discardSnapshotsWhileAttached =
+                        discardSnapshotsWhileAttached.getValue();
+                });
         }
-    }
 
+        if (detachAllObjectsButton.wasClicked())
+        {
+            objpose::DetachAllObjectsFromRobotNodesInput input;
+            input.commitAttachedPose = detachAllObjectsCommitAttachedPoseCheckBox.getValue();
+
+            objpose::DetachAllObjectsFromRobotNodesOutput output = segment.doLocked(
+                [&segment, &input]() { return segment.detachAllObjectsFromRobotNodes(input); });
+            (void)output;
+        }
+    }
 
-    VirtualRobot::RobotPtr Segment::RobotsCache::get(const std::string& _robotName, const std::string& providerName)
+    VirtualRobot::RobotPtr
+    Segment::RobotsCache::get(const std::string& _robotName, const std::string& providerName)
     {
         std::string robotName = _robotName;
 
         if (robotName.empty())
         {
-            auto antiSpam = deactivateSpam(10 * 60);  // 10 minutes.
+            auto antiSpam = deactivateSpam(10 * 60); // 10 minutes.
 
             std::stringstream ss;
             if (providerName.empty())
@@ -1285,8 +1320,7 @@ namespace armarx::armem::server::obj::instance
             {
                 ss << ", and no fallback robot name was configured (e.g. via the properties).\n"
                    << "For these object poses, the object instance segment is not able "
-                   << "to provide transformed object poses (global and in robot root frame)."
-                      ;
+                   << "to provide transformed object poses (global and in robot root frame).";
                 ARMARX_INFO << antiSpam << ss.str();
 
                 return nullptr;
@@ -1312,8 +1346,7 @@ namespace armarx::armem::server::obj::instance
             // Try to fetch the robot.
             ARMARX_CHECK_NOT_NULL(reader);
             VirtualRobot::RobotPtr robot = reader->getRobot(
-                        robotName, Clock::Now(),
-                        VirtualRobot::RobotIO::RobotDescription::eStructure);
+                robotName, Clock::Now(), VirtualRobot::RobotIO::RobotDescription::eStructure);
 
             if (robot)
             {
@@ -1321,14 +1354,16 @@ namespace armarx::armem::server::obj::instance
                 if (not synchronized)
                 {
                     ARMARX_INFO << "The robot '" << robotName << "' could be loaded, but not"
-                                << " synchronized successfully (e.g., the global localization could be missing). "
+                                << " synchronized successfully (e.g., the global localization "
+                                   "could be missing). "
                                 << "Make sure to synchronize it before use if necessary.";
                 }
                 // Store robot if valid.
                 loaded.emplace(robotName, robot);
             }
-            return robot;  // valid or nullptr
+            return robot; // valid or nullptr
         }
     }
 
-}
+
+} // namespace armarx::armem::server::obj::instance
diff --git a/source/RobotAPI/libraries/armem_objects/server/instance/Segment.h b/source/RobotAPI/libraries/armem_objects/server/instance/Segment.h
index c5e62d975ca161773c9ae4e8b7d7f5352f0f1922..b922f1211cbe769e89d9a55108b257b336c73642 100644
--- a/source/RobotAPI/libraries/armem_objects/server/instance/Segment.h
+++ b/source/RobotAPI/libraries/armem_objects/server/instance/Segment.h
@@ -9,24 +9,20 @@
 #include <SimoxUtility/shapes/OrientedBox.h>
 
 #include "RobotAPI/libraries/armem_robot_state/client/common/VirtualRobotReader.h"
+#include <RobotAPI/components/ArViz/Client/Client.h>
 #include <RobotAPI/interface/core/RobotState.h>
 #include <RobotAPI/interface/objectpose/ObjectPoseStorageInterface.h>
-
-#include <RobotAPI/components/ArViz/Client/Client.h>
-
+#include <RobotAPI/libraries/ArmarXObjects/ObjectFinder.h>
 #include <RobotAPI/libraries/ArmarXObjects/ObjectID.h>
 #include <RobotAPI/libraries/ArmarXObjects/ObjectPose.h>
-#include <RobotAPI/libraries/ArmarXObjects/ObjectFinder.h>
 #include <RobotAPI/libraries/ArmarXObjects/forward_declarations.h>
-
 #include <RobotAPI/libraries/armem/core/Prediction.h>
-#include <RobotAPI/libraries/armem/server/wm/memory_definitions.h>
 #include <RobotAPI/libraries/armem/server/segment/SpecializedSegment.h>
+#include <RobotAPI/libraries/armem/server/wm/memory_definitions.h>
 
 #include "ArticulatedObjectVisu.h"
 #include "Decay.h"
 
-
 namespace armarx::armem::arondto
 {
     class ObjectInstance;
@@ -38,11 +34,11 @@ namespace armarx::armem::server::obj::instance
     class Segment : public segment::SpecializedCoreSegment
     {
     public:
-
         struct CommitStats
         {
             int numUpdated = 0;
         };
+
         using ObjectPose = objpose::ObjectPose;
         using ObjectPoseSeq = objpose::ObjectPoseSeq;
         using ObjectPoseMap = std::map<ObjectID, ObjectPose>;
@@ -53,41 +49,46 @@ namespace armarx::armem::server::obj::instance
             std::string robotNode = "Neck_2_Pitch";
             float offset = 0.0f;
 
-            void defineProperties(armarx::PropertyDefinitionsPtr defs, const std::string& prefix = "calibration.");
+            void defineProperties(armarx::PropertyDefinitionsPtr defs,
+                                  const std::string& prefix = "calibration.");
         };
 
 
     public:
-
         Segment(server::MemoryToIceAdapter& iceMemory);
         virtual ~Segment() override;
 
 
-        void defineProperties(armarx::PropertyDefinitionsPtr defs, const std::string& prefix = "") override;
+        void defineProperties(armarx::PropertyDefinitionsPtr defs,
+                              const std::string& prefix = "") override;
         void init() override;
         void connect(viz::Client arviz);
 
 
-
-        CommitStats commitObjectPoses(
-            const std::string& providerName,
-            const objpose::data::ProvidedObjectPoseSeq& providedPoses,
-            const Calibration& calibration,
-            std::optional<Time> discardUpdatesUntil = std::nullopt);
-        void commitObjectPoses(const ObjectPoseSeq& objectPoses, const std::string& providerName = "");
+        CommitStats commitObjectPoses(const std::string& providerName,
+                                      const objpose::data::ProvidedObjectPoseSeq& providedPoses,
+                                      const Calibration& calibration,
+                                      std::optional<Time> discardUpdatesUntil = std::nullopt);
+        void commitObjectPoses(const ObjectPoseSeq& objectPoses,
+                               const std::string& providerName = "");
 
 
         objpose::ObjectPoseMap getObjectPoses(const DateTime& now);
-        objpose::ObjectPoseMap getObjectPosesByProvider(const std::string& providerName, const DateTime& now);
+        objpose::ObjectPoseMap getObjectPosesByProvider(const std::string& providerName,
+                                                        const DateTime& now);
 
-        wm::Entity* findObjectEntity(const ObjectID& objectID, const std::string& providerName = "");
+        wm::Entity* findObjectEntity(const ObjectID& objectID,
+                                     const std::string& providerName = "");
         std::optional<simox::OrientedBoxf> getObjectOOBB(const ObjectID& id);
 
         objpose::ProviderInfo getProviderInfo(const std::string& providerName);
 
-        objpose::AttachObjectToRobotNodeOutput attachObjectToRobotNode(const objpose::AttachObjectToRobotNodeInput& input);
-        objpose::DetachObjectFromRobotNodeOutput detachObjectFromRobotNode(const objpose::DetachObjectFromRobotNodeInput& input);
-        objpose::DetachAllObjectsFromRobotNodesOutput detachAllObjectsFromRobotNodes(const objpose::DetachAllObjectsFromRobotNodesInput& input);
+        objpose::AttachObjectToRobotNodeOutput
+        attachObjectToRobotNode(const objpose::AttachObjectToRobotNodeInput& input);
+        objpose::DetachObjectFromRobotNodeOutput
+        detachObjectFromRobotNode(const objpose::DetachObjectFromRobotNodeInput& input);
+        objpose::DetachAllObjectsFromRobotNodesOutput
+        detachAllObjectsFromRobotNodes(const objpose::DetachAllObjectsFromRobotNodesInput& input);
 
 
         /**
@@ -100,7 +101,8 @@ namespace armarx::armem::server::obj::instance
          *
          * @param synchronized Indicates whether the agent is already synchronized to the current time.
          */
-        void updateAttachement(ObjectPose& objectPose, VirtualRobot::RobotPtr agent,
+        void updateAttachement(ObjectPose& objectPose,
+                               VirtualRobot::RobotPtr agent,
                                bool& synchronized) const;
 
 
@@ -120,34 +122,26 @@ namespace armarx::armem::server::obj::instance
         getObjectPosesInRange(const wm::Entity& entity, const DateTime& start, const DateTime& end);
 
     private:
-
         ObjectPoseMap getLatestObjectPoses() const;
 
-        void updateObjectPoses(
-            ObjectPoseMap& objectPoses,
-            const DateTime& now);
-        void updateObjectPoses(
-            ObjectPoseMap& objectPoses,
-            const DateTime& now,
-            VirtualRobot::RobotPtr agent,
-            bool& agentSynchronized
-        ) const;
-        void updateObjectPose(
-            ObjectPose& objectPose,
-            const DateTime& now,
-            VirtualRobot::RobotPtr agent,
-            bool& agentSynchronized
-        ) const;
+        void updateObjectPoses(ObjectPoseMap& objectPoses, const DateTime& now);
+        void updateObjectPoses(ObjectPoseMap& objectPoses,
+                               const DateTime& now,
+                               VirtualRobot::RobotPtr agent,
+                               bool& agentSynchronized) const;
+        void updateObjectPose(ObjectPose& objectPose,
+                              const DateTime& now,
+                              VirtualRobot::RobotPtr agent,
+                              bool& agentSynchronized) const;
 
 
         ObjectPoseMap filterObjectPoses(const ObjectPoseMap& objectPoses) const;
 
 
-        void storeDetachedSnapshot(
-            wm::Entity& entity,
-            const arondto::ObjectInstance& data,
-            Time now,
-            bool commitAttachedPose);
+        void storeDetachedSnapshot(wm::Entity& entity,
+                                   const arondto::ObjectInstance& data,
+                                   Time now,
+                                   bool commitAttachedPose);
 
 
         std::optional<wm::EntityInstance> findClassInstance(const ObjectID& objectID) const;
@@ -156,7 +150,6 @@ namespace armarx::armem::server::obj::instance
 
 
     private:
-
         void storeScene(const std::string& filename, const armarx::objects::Scene& scene);
         std::optional<armarx::objects::Scene> loadScene(const std::string& filename);
         std::optional<armarx::objects::Scene> loadScene(const std::filesystem::path& path);
@@ -168,7 +161,6 @@ namespace armarx::armem::server::obj::instance
 
 
     public:
-
         /// Loaded robot models identified by the robot name.
         struct RobotsCache : public armarx::Logging
         {
@@ -177,8 +169,10 @@ namespace armarx::armem::server::obj::instance
 
             std::map<std::string, VirtualRobot::RobotPtr> loaded;
 
-            VirtualRobot::RobotPtr get(const std::string& robotName, const std::string& providerName = "");
+            VirtualRobot::RobotPtr get(const std::string& robotName,
+                                       const std::string& providerName = "");
         };
+
         RobotsCache robots;
 
 
@@ -192,7 +186,6 @@ namespace armarx::armem::server::obj::instance
 
 
     private:
-
         struct Properties
         {
             bool discardSnapshotsWhileAttached = true;
@@ -201,7 +194,10 @@ namespace armarx::armem::server::obj::instance
             std::string sceneSnapshotsPackage = armarx::ObjectFinder::DefaultObjectsPackageName;
             std::string sceneSnapshotsDirectory = "scenes";
             std::string sceneSnapshotsToLoad = "";
+
+            std::vector<std::string> getSceneSnapshotsToLoad() const;
         };
+
         Properties p;
 
 
@@ -216,7 +212,6 @@ namespace armarx::armem::server::obj::instance
         static const std::string timestampPlaceholder;
 
     public:
-
         struct RemoteGui
         {
             armarx::RemoteGui::Client::GroupBox group;
@@ -229,15 +224,16 @@ namespace armarx::armem::server::obj::instance
             armarx::RemoteGui::Client::CheckBox infiniteHistory;
             armarx::RemoteGui::Client::CheckBox discardSnapshotsWhileAttached;
 
+            armarx::RemoteGui::Client::Button detachAllObjectsButton;
+            armarx::RemoteGui::Client::CheckBox detachAllObjectsCommitAttachedPoseCheckBox;
+
             void setup(const Segment& data);
             void update(Segment& data);
         };
 
 
     private:
-
         std::unique_ptr<ArticulatedObjectVisu> visu;
-
     };
 
-}
+} // namespace armarx::armem::server::obj::instance
diff --git a/source/RobotAPI/libraries/armem_robot_state/common/localization/TransformHelper.cpp b/source/RobotAPI/libraries/armem_robot_state/common/localization/TransformHelper.cpp
index e808a4b2e31f7d3763b0a0a8052502eb77260f27..c163ff7f68ca6fae8b4bccdf6ecfce72187f10fa 100644
--- a/source/RobotAPI/libraries/armem_robot_state/common/localization/TransformHelper.cpp
+++ b/source/RobotAPI/libraries/armem_robot_state/common/localization/TransformHelper.cpp
@@ -1,4 +1,5 @@
 #include "TransformHelper.h"
+
 #include <optional>
 #include <string>
 
@@ -6,55 +7,53 @@
 #include <SimoxUtility/algorithm/string/string_tools.h>
 #include <SimoxUtility/math/pose/interpolate.h>
 
-#include "ArmarXCore/core/logging/Logging.h"
-#include <ArmarXCore/core/exceptions/LocalException.h>
 #include "ArmarXCore/core/exceptions/local/ExpressionException.h"
+#include "ArmarXCore/core/logging/Logging.h"
 #include "ArmarXCore/core/time/DateTime.h"
 #include "ArmarXCore/core/time/Duration.h"
-#include "RobotAPI/libraries/armem/core/forward_declarations.h"
+#include <ArmarXCore/core/exceptions/LocalException.h>
 
+#include "RobotAPI/libraries/armem/core/forward_declarations.h"
 #include "RobotAPI/libraries/armem_robot_state/client/common/constants.h"
-#include <RobotAPI/libraries/core/FramedPose.h>
-
-#include <RobotAPI/libraries/aron/common/aron_conversions.h>
-
 #include <RobotAPI/libraries/armem/core/Time.h>
 #include <RobotAPI/libraries/armem/core/error/ArMemError.h>
 #include <RobotAPI/libraries/armem/core/wm/memory_definitions.h>
 #include <RobotAPI/libraries/armem/server/wm/memory_definitions.h>
-
 #include <RobotAPI/libraries/armem_robot_state/aron/Transform.aron.generated.h>
 #include <RobotAPI/libraries/armem_robot_state/aron_conversions.h>
-
+#include <RobotAPI/libraries/aron/common/aron_conversions.h>
+#include <RobotAPI/libraries/core/FramedPose.h>
 
 namespace armarx::armem::common::robot_state::localization
 {
 
-    template <class ...Args>
+    template <class... Args>
     TransformResult
     TransformHelper::_lookupTransform(
         const armem::base::CoreSegmentBase<Args...>& localizationCoreSegment,
         const TransformQuery& query)
     {
-        const std::vector<std::string> tfChain = _buildTransformChain(localizationCoreSegment, query);
+        const std::vector<std::string> tfChain =
+            _buildTransformChain(localizationCoreSegment, query);
         if (tfChain.empty())
         {
-            return {.transform    = {.header = query.header},
-                    .status       = TransformResult::Status::ErrorFrameNotAvailable,
-                    .errorMessage = "Cannot create tf lookup chain '" +
-                                    query.header.parentFrame + " -> " + query.header.frame +
-                                    "' for robot `" + query.header.agent + "`."};
+            return {.transform = {.header = query.header},
+                    .status = TransformResult::Status::ErrorFrameNotAvailable,
+                    .errorMessage = "Cannot create tf lookup chain '" + query.header.parentFrame +
+                                    " -> " + query.header.frame + "' for robot `" +
+                                    query.header.agent + "`."};
         }
 
         const std::vector<Eigen::Affine3f> transforms = _obtainTransforms(
-                    localizationCoreSegment, tfChain, query.header.agent, query.header.timestamp);
+            localizationCoreSegment, tfChain, query.header.agent, query.header.timestamp);
 
-        const std::optional<armem::Time> sanitizedTimestamp = _obtainTimestamp(localizationCoreSegment, query.header.timestamp);
+        const std::optional<armem::Time> sanitizedTimestamp =
+            _obtainTimestamp(localizationCoreSegment, query.header.timestamp);
 
-        if(not sanitizedTimestamp.has_value())
+        if (not sanitizedTimestamp.has_value())
         {
-            return {.transform    = {.header = query.header},
-                    .status       = TransformResult::Status::Error,
+            return {.transform = {.header = query.header},
+                    .status = TransformResult::Status::Error,
                     .errorMessage = "Error: Issue with timestamp"};
         }
 
@@ -66,79 +65,69 @@ namespace armarx::armem::common::robot_state::localization
         // ARMARX_INFO << header.timestamp << "vs" << sanitizedTimestamp;
 
         header.timestamp = sanitizedTimestamp.value();
-                
+
         if (transforms.empty())
         {
-            ARMARX_WARNING << deactivateSpam(1) << "No transform available.";
-            return {.transform    = {.header = query.header},
-                    .status       = TransformResult::Status::ErrorFrameNotAvailable,
+            ARMARX_INFO << deactivateSpam(1) << "No transform available.";
+            return {.transform = {.header = query.header},
+                    .status = TransformResult::Status::ErrorFrameNotAvailable,
                     .errorMessage = "Error in TF loookup:  '" + query.header.parentFrame +
                                     " -> " + query.header.frame +
                                     "'. No memory data in time range."};
         }
 
-        const Eigen::Affine3f transform = std::accumulate(transforms.begin(),
-                                          transforms.end(),
-                                          Eigen::Affine3f::Identity(),
-                                          std::multiplies<>());
+        const Eigen::Affine3f transform = std::accumulate(
+            transforms.begin(), transforms.end(), Eigen::Affine3f::Identity(), std::multiplies<>());
 
         ARMARX_DEBUG << "Found valid transform";
 
         return {.transform = {.header = header, .transform = transform},
-                .status    = TransformResult::Status::Success};
+                .status = TransformResult::Status::Success};
     }
 
-
-    template <class ...Args>
+    template <class... Args>
     TransformChainResult
     TransformHelper::_lookupTransformChain(
         const armem::base::CoreSegmentBase<Args...>& localizationCoreSegment,
         const TransformQuery& query)
     {
-        const std::vector<std::string> tfChain = _buildTransformChain(localizationCoreSegment, query);
+        const std::vector<std::string> tfChain =
+            _buildTransformChain(localizationCoreSegment, query);
         if (tfChain.empty())
         {
-            ARMARX_VERBOSE << "TF chain is empty";
-            return
-            {
-                .header = query.header,
-                .transforms    = std::vector<Eigen::Affine3f>{},
-                .status       = TransformChainResult::Status::ErrorFrameNotAvailable,
-                .errorMessage = "Cannot create tf lookup chain '" +
-                query.header.parentFrame + " -> " + query.header.frame +
-                "' for robot `" + query.header.agent + "`."
-            };
+            ARMARX_DEBUG << "TF chain is empty";
+            return {.header = query.header,
+                    .transforms = std::vector<Eigen::Affine3f>{},
+                    .status = TransformChainResult::Status::ErrorFrameNotAvailable,
+                    .errorMessage = "Cannot create tf lookup chain '" + query.header.parentFrame +
+                                    " -> " + query.header.frame + "' for robot `" +
+                                    query.header.agent + "`."};
         }
 
         const std::vector<Eigen::Affine3f> transforms = _obtainTransforms(
-                    localizationCoreSegment, tfChain, query.header.agent, query.header.timestamp);
+            localizationCoreSegment, tfChain, query.header.agent, query.header.timestamp);
         if (transforms.empty())
         {
-            ARMARX_WARNING << deactivateSpam(1) << "No transform available.";
+            ARMARX_INFO << deactivateSpam(1) << "No transform available.";
             return
             {
                 .header = query.header,
-                .transforms    = {},
-                .status       = TransformChainResult::Status::ErrorFrameNotAvailable,
-                .errorMessage = "Error in TF loookup:  '" + query.header.parentFrame +
-                " -> " + query.header.frame +
-                "'. No memory data in time range."
+                .transforms = {},
+                .status = TransformChainResult::Status::ErrorFrameNotAvailable,
+                .errorMessage = "Error in TF loookup:  '" + query.header.parentFrame + " -> " +
+                                 query.header.frame + "'. No memory data in time range."
             };
         }
 
 
         ARMARX_DEBUG << "Found valid transform";
 
-        return
-        {
-            .header = query.header,
-            .transforms = transforms,
-            .status    = TransformChainResult::Status::Success
-        };
+        return {.header = query.header,
+                .transforms = transforms,
+                .status = TransformChainResult::Status::Success};
     }
 
-
-    template <class ...Args>
+    template <class... Args>
     std::vector<std::string>
     TransformHelper::_buildTransformChain(
         const armem::base::CoreSegmentBase<Args...>& localizationCoreSegment,
@@ -148,14 +137,15 @@ namespace armarx::armem::common::robot_state::localization
 
         std::vector<std::string> chain;
 
-        const auto& agentProviderSegment = localizationCoreSegment.getProviderSegment(query.header.agent);
+        const auto& agentProviderSegment =
+            localizationCoreSegment.getProviderSegment(query.header.agent);
 
         const std::vector<std::string> tfs = agentProviderSegment.getEntityNames();
 
         // lookup from robot root to global
         std::map<std::string, std::string> tfLookup;
 
-        for(const std::string& tf: tfs)
+        for (const std::string& tf : tfs)
         {
             const auto frames = simox::alg::split(tf, ",");
             ARMARX_CHECK_EQUAL(frames.size(), 2);
@@ -165,60 +155,66 @@ namespace armarx::armem::common::robot_state::localization
 
         std::string currentFrame = query.header.parentFrame;
         chain.push_back(currentFrame);
-        while(tfLookup.count(currentFrame) > 0 and currentFrame != query.header.frame)
+        while (tfLookup.count(currentFrame) > 0 and currentFrame != query.header.frame)
         {
             currentFrame = tfLookup.at(currentFrame);
             chain.push_back(currentFrame);
         }
-       
+
         ARMARX_DEBUG << VAROUT(chain);
 
         if (chain.empty() or chain.back() != query.header.frame)
         {
-            ARMARX_WARNING << deactivateSpam(60) << "Cannot create tf lookup chain '" << query.header.parentFrame
-                           << " -> " << query.header.frame << "' for robot `" + query.header.agent + "`.";
+            ARMARX_INFO << deactivateSpam(60) << "Cannot create tf lookup chain '"
+                        << query.header.parentFrame << " -> " << query.header.frame
+                        << "' for robot `" + query.header.agent + "`.";
             return {};
         }
 
         std::vector<std::string> frameChain;
-        for(size_t i = 0; i < (chain.size() - 1); i++)
+        for (size_t i = 0; i < (chain.size() - 1); i++)
         {
-            frameChain.push_back(chain.at(i) + "," + chain.at(i+1));
+            frameChain.push_back(chain.at(i) + "," + chain.at(i + 1));
         }
 
         return frameChain;
     }
 
-    template <class ...Args>
+    template <class... Args>
     std::optional<armarx::core::time::DateTime>
-    TransformHelper::_obtainTimestamp(const armem::base::CoreSegmentBase<Args...>& localizationCoreSegment, const armem::Time& timestamp)
+    TransformHelper::_obtainTimestamp(
+        const armem::base::CoreSegmentBase<Args...>& localizationCoreSegment,
+        const armem::Time& timestamp)
     {
-        
+
         // first we check which the newest timestamp is
         std::optional<int64_t> timeSinceEpochUs = std::nullopt;
 
-        localizationCoreSegment.forEachEntity([&timeSinceEpochUs, &timestamp](const auto& entity){
-            auto snapshot = entity.findLatestSnapshotBeforeOrAt(timestamp);
-
-            if(snapshot == nullptr)
+        localizationCoreSegment.forEachEntity(
+            [&timeSinceEpochUs, &timestamp](const auto& entity)
             {
-                return;
-            }
+                auto snapshot = entity.findLatestSnapshotBeforeOrAt(timestamp);
 
-            if(not snapshot->hasInstance(0))
-            {
-                return;
-            }
+                if (snapshot == nullptr)
+                {
+                    return;
+                }
+
+                if (not snapshot->hasInstance(0))
+                {
+                    return;
+                }
 
-            const armem::wm::EntityInstance& item = snapshot->getInstance(0);
-            const auto tf = _convertEntityToTransform(item);
-            
-            const auto& dataTs = tf.header.timestamp;
+                const armem::wm::EntityInstance& item = snapshot->getInstance(0);
+                const auto tf = _convertEntityToTransform(item);
 
-            timeSinceEpochUs = std::max(timeSinceEpochUs.value_or(0), dataTs.toMicroSecondsSinceEpoch());
-        });
+                const auto& dataTs = tf.header.timestamp;
 
-        if(not timeSinceEpochUs.has_value())
+                timeSinceEpochUs =
+                    std::max(timeSinceEpochUs.value_or(0), dataTs.toMicroSecondsSinceEpoch());
+            });
+
+        if (not timeSinceEpochUs.has_value())
         {
             return std::nullopt;
         }
@@ -226,11 +222,11 @@ namespace armarx::armem::common::robot_state::localization
         // then we ensure that the timestamp is not more recent than the query timestamp
         timeSinceEpochUs = std::min(timeSinceEpochUs.value(), timestamp.toMicroSecondsSinceEpoch());
 
-        return armarx::core::time::DateTime(armarx::core::time::Duration::MicroSeconds(timeSinceEpochUs.value()));
+        return armarx::core::time::DateTime(
+            armarx::core::time::Duration::MicroSeconds(timeSinceEpochUs.value()));
     }
 
-
-    template <class ...Args>
+    template <class... Args>
     std::vector<Eigen::Affine3f>
     TransformHelper::_obtainTransforms(
         const armem::base::CoreSegmentBase<Args...>& localizationCoreSegment,
@@ -250,10 +246,9 @@ namespace armarx::armem::common::robot_state::localization
             std::transform(tfChain.begin(),
                            tfChain.end(),
                            std::back_inserter(transforms),
-                           [&](const std::string & entityName)
-            {
-                return _obtainTransform(entityName, agentProviderSegment, timestamp);
-            });
+                           [&](const std::string& entityName) {
+                               return _obtainTransform(entityName, agentProviderSegment, timestamp);
+                           });
             return transforms;
         }
         catch (const armem::error::MissingEntry& missingEntryError)
@@ -276,8 +271,7 @@ namespace armarx::armem::common::robot_state::localization
         return {};
     }
 
-
-    template <class ...Args>
+    template <class... Args>
     Eigen::Affine3f
     TransformHelper::_obtainTransform(
         const std::string& entityName,
@@ -327,7 +321,6 @@ namespace armarx::armem::common::robot_state::localization
         return transforms.front().transform;
     }
 
-
     ::armarx::armem::robot_state::Transform
     TransformHelper::_convertEntityToTransform(const armem::wm::EntityInstance& item)
     {
@@ -344,18 +337,13 @@ namespace armarx::armem::common::robot_state::localization
     findFirstElementAfter(const std::vector<::armarx::armem::robot_state::Transform>& transforms,
                           const armem::Time& timestamp)
     {
-        const auto comp = [](const armem::Time & timestamp, const auto & transform)
-        {
-            return transform.header.timestamp < timestamp;
-        };
+        const auto comp = [](const armem::Time& timestamp, const auto& transform)
+        { return transform.header.timestamp < timestamp; };
 
         const auto it = std::upper_bound(transforms.begin(), transforms.end(), timestamp, comp);
 
-        auto timestampBeyond =
-            [timestamp](const ::armarx::armem::robot_state::Transform & transform)
-        {
-            return transform.header.timestamp > timestamp;
-        };
+        auto timestampBeyond = [timestamp](const ::armarx::armem::robot_state::Transform& transform)
+        { return transform.header.timestamp > timestamp; };
 
         const auto poseNextIt = std::find_if(transforms.begin(), transforms.end(), timestampBeyond);
 
@@ -374,7 +362,7 @@ namespace armarx::armem::common::robot_state::localization
         ARMARX_DEBUG << "Entering";
 
         ARMARX_CHECK(not queue.empty())
-                << "The queue has to contain at least two items to perform a lookup";
+            << "The queue has to contain at least two items to perform a lookup";
 
         ARMARX_DEBUG << "Entering ... "
                      << "Q front " << queue.front().header.timestamp << "  "
@@ -384,11 +372,11 @@ namespace armarx::armem::common::robot_state::localization
         // TODO(fabian.reister): sort queue.
 
         ARMARX_CHECK(queue.back().header.timestamp > timestamp)
-                << "Cannot perform lookup into the future!";
+            << "Cannot perform lookup into the future!";
 
         // ARMARX_DEBUG << "Entering 1.5 " << queue.front().timestamp << "  " << timestamp;
         ARMARX_CHECK(queue.front().header.timestamp < timestamp)
-                << "Cannot perform lookup. Timestamp too old";
+            << "Cannot perform lookup. Timestamp too old";
         // => now we know that there is an element right after and before the timestamp within our queue
 
         ARMARX_DEBUG << "Entering 2";
@@ -402,36 +390,39 @@ namespace armarx::armem::common::robot_state::localization
         ARMARX_DEBUG << "deref";
 
         // the time fraction [0..1] of the lookup wrt to posePre and poseNext
-        const double t = (timestamp - posePreIt->header.timestamp).toMicroSecondsDouble() /
-                         (poseNextIt->header.timestamp - posePreIt->header.timestamp).toMicroSecondsDouble();
+        const double t =
+            (timestamp - posePreIt->header.timestamp).toMicroSecondsDouble() /
+            (poseNextIt->header.timestamp - posePreIt->header.timestamp).toMicroSecondsDouble();
 
         ARMARX_DEBUG << "interpolate";
 
-        return simox::math::interpolatePose(posePreIt->transform, poseNextIt->transform, static_cast<float>(t));
+        return simox::math::interpolatePose(
+            posePreIt->transform, poseNextIt->transform, static_cast<float>(t));
     }
 
-
-    TransformResult TransformHelper::lookupTransform(
-        const armem::wm::CoreSegment& localizationCoreSegment,
-        const TransformQuery& query)
+    TransformResult
+    TransformHelper::lookupTransform(const armem::wm::CoreSegment& localizationCoreSegment,
+                                     const TransformQuery& query)
     {
         return _lookupTransform(localizationCoreSegment, query);
     }
-    TransformResult TransformHelper::lookupTransform(
-        const armem::server::wm::CoreSegment& localizationCoreSegment,
-        const TransformQuery& query)
+
+    TransformResult
+    TransformHelper::lookupTransform(const armem::server::wm::CoreSegment& localizationCoreSegment,
+                                     const TransformQuery& query)
     {
         return _lookupTransform(localizationCoreSegment, query);
     }
 
-
-    TransformChainResult TransformHelper::lookupTransformChain(
-        const armem::wm::CoreSegment& localizationCoreSegment,
-        const TransformQuery& query)
+    TransformChainResult
+    TransformHelper::lookupTransformChain(const armem::wm::CoreSegment& localizationCoreSegment,
+                                          const TransformQuery& query)
     {
         return _lookupTransformChain(localizationCoreSegment, query);
     }
-    TransformChainResult TransformHelper::lookupTransformChain(
+
+    TransformChainResult
+    TransformHelper::lookupTransformChain(
         const armem::server::wm::CoreSegment& localizationCoreSegment,
         const TransformQuery& query)
     {
diff --git a/source/RobotAPI/libraries/armem_robot_state/server/common/Visu.cpp b/source/RobotAPI/libraries/armem_robot_state/server/common/Visu.cpp
index b8b3190d1bae586226c60b490bb399abe5799272..41eaf6e2ec2f2bcead697ec6ca7e86868bca44c4 100644
--- a/source/RobotAPI/libraries/armem_robot_state/server/common/Visu.cpp
+++ b/source/RobotAPI/libraries/armem_robot_state/server/common/Visu.cpp
@@ -117,6 +117,24 @@ namespace armarx::armem::server::robot_state
         }
     }
 
+    void Visu::visualizeFramesIndividual(
+        viz::Layer& layerFrames,
+        const std::unordered_map<std::string, std::vector<Eigen::Affine3f>>& frames)
+    {
+
+        std::vector<std::string> FRAME_NAMES{/*world*/ "map", "odom", "robot"};
+
+        for (const auto& [robotName, robotFrames] : frames)
+        {
+            int i = 0;
+            for (const auto& frame : robotFrames)
+            {
+                layerFrames.add(viz::Pose(robotName + FRAME_NAMES.at(i++)).pose(frame.matrix()).scale(3));
+            }
+        }
+    }
+
+
 
     void Visu::visualizeRun()
     {
@@ -213,6 +231,12 @@ namespace armarx::armem::server::robot_state
 
         TIMING_END_STREAM(tVisuBuildLayers, ARMARX_DEBUG);
 
+        {
+            viz::Layer layerFrames = arviz.layer("FramesIndividual");
+            visualizeFramesIndividual(layerFrames, frames);
+            layers.push_back(layerFrames);
+        }
+
 
         // Commit layers.
 
diff --git a/source/RobotAPI/libraries/armem_robot_state/server/common/Visu.h b/source/RobotAPI/libraries/armem_robot_state/server/common/Visu.h
index 66222e0cf8dc6cf6043e6db35ebb7ba00e0cab00..99321b656be9977a23096e3b9bdd9ed4ba62a101 100644
--- a/source/RobotAPI/libraries/armem_robot_state/server/common/Visu.h
+++ b/source/RobotAPI/libraries/armem_robot_state/server/common/Visu.h
@@ -71,6 +71,11 @@ namespace armarx::armem::server::robot_state
             viz::Layer& layerFrames,
             const std::unordered_map<std::string, std::vector<Eigen::Affine3f>>& frames);
 
+        static
+        void visualizeFramesIndividual(
+            viz::Layer& layerFrames,
+            const std::unordered_map<std::string, std::vector<Eigen::Affine3f>>& frames);
+
 
     private:
 
diff --git a/source/RobotAPI/libraries/armem_robot_state/server/proprioception/RobotUnitReader.cpp b/source/RobotAPI/libraries/armem_robot_state/server/proprioception/RobotUnitReader.cpp
index 53021dc7d88f9362a967f395b1381d07934f271e..34260f51e36951f7b9a0a68369cf8317e8a4dedc 100644
--- a/source/RobotAPI/libraries/armem_robot_state/server/proprioception/RobotUnitReader.cpp
+++ b/source/RobotAPI/libraries/armem_robot_state/server/proprioception/RobotUnitReader.cpp
@@ -3,7 +3,6 @@
 #include <filesystem>
 #include <istream>
 
-
 #include "ArmarXCore/core/time/Frequency.h"
 #include "ArmarXCore/core/time/Metronome.h"
 #include <ArmarXCore/libraries/ArmarXCoreComponentPlugins/DebugObserverComponentPlugin.h>
@@ -11,13 +10,11 @@
 #include <RobotAPI/libraries/RobotUnitDataStreamingReceiver/RobotUnitDataStreamingReceiver.h>
 #include <RobotAPI/libraries/aron/core/data/variant/container/Dict.h>
 
-
 namespace armarx::armem::server::robot_state::proprioception
 {
 
     RobotUnitReader::RobotUnitReader() = default;
 
-
     void
     RobotUnitReader::connect(armarx::plugins::RobotUnitComponentPlugin& robotUnitPlugin,
                              armarx::plugins::DebugObserverComponentPlugin& debugObserverPlugin,
@@ -48,7 +45,6 @@ namespace armarx::armem::server::robot_state::proprioception
         }
     }
 
-
     void
     RobotUnitReader::run(float pollFrequency, Queue& dataBuffer)
     {
@@ -56,14 +52,22 @@ namespace armarx::armem::server::robot_state::proprioception
 
         while (task and not task->isStopped())
         {
+            auto start = std::chrono::high_resolution_clock::now();
+
             if (std::optional<RobotUnitData> commit = fetchAndConvertLatestRobotUnitData())
             {
                 // will lock a mutex
+                debugObserver->setDebugObserverDatafield("RobotUnitReader | t commitTimestamp [us]",
+                                                         commit->timestamp.toMicroSecondsSinceEpoch());
+
                 dataBuffer.push(std::move(commit.value()));
             }
-
+            auto duration = std::chrono::duration_cast<std::chrono::microseconds>(
+                std::chrono::high_resolution_clock::now() - start);
             if (debugObserver)
             {
+                debugObserver->setDebugObserverDatafield("RobotUnitReader | t run [ms]",
+                                                         duration.count() / 1000.f);
                 debugObserver->sendDebugObserverBatch();
             }
 
@@ -71,13 +75,24 @@ namespace armarx::armem::server::robot_state::proprioception
         }
     }
 
-
     std::optional<RobotUnitData>
     RobotUnitReader::fetchAndConvertLatestRobotUnitData()
     {
         ARMARX_CHECK_NOT_NULL(converterProprioception);
 
-        const std::optional<RobotUnitDataStreaming::TimeStep> data = fetchLatestData();
+
+        std::optional<RobotUnitDataStreaming::TimeStep> data;
+        {
+            auto start = std::chrono::high_resolution_clock::now();
+            data = fetchLatestData();
+            auto duration = std::chrono::duration_cast<std::chrono::microseconds>(
+                std::chrono::high_resolution_clock::now() - start);
+            if (debugObserver)
+            {
+                debugObserver->setDebugObserverDatafield("RobotUnitReader | t Fetch [ms]",
+                                                         duration.count() / 1000.f);
+            }
+        }
         if (not data.has_value())
         {
             return std::nullopt;
@@ -88,16 +103,16 @@ namespace armarx::armem::server::robot_state::proprioception
 
         RobotUnitData result;
 
-        if(converterProprioception != nullptr)
+        if (converterProprioception != nullptr)
         {
             result.proprioception = converterProprioception->convert(data.value(), description);
         }
 
-        if(converterExteroception != nullptr)
+        if (converterExteroception != nullptr)
         {
             result.exteroception = converterExteroception->convert(data.value(), description);
         }
-        
+
         result.timestamp = Time(Duration::MicroSeconds(data->timestampUSec));
 
         auto stop = std::chrono::high_resolution_clock::now();
@@ -114,7 +129,6 @@ namespace armarx::armem::server::robot_state::proprioception
         return result;
     }
 
-
     std::optional<RobotUnitDataStreaming::TimeStep>
     RobotUnitReader::fetchLatestData()
     {
@@ -122,6 +136,14 @@ namespace armarx::armem::server::robot_state::proprioception
         if (debugObserver)
         {
             debugObserver->setDebugObserverDatafield("RobotUnitReader | Buffer Size", data.size());
+            if (data.size())
+            {
+                debugObserver->setDebugObserverDatafield("RobotUnitReader | RT Timestamp USec",
+                                                         data.back().timestampUSec);
+                debugObserver->setDebugObserverDatafield(
+                    "RobotUnitReader | RT Timestamp Since Last Iteration",
+                    data.back().timesSinceLastIterationUSec);
+            }
         }
         if (data.empty())
         {
diff --git a/source/RobotAPI/statecharts/CMakeLists.txt b/source/RobotAPI/statecharts/CMakeLists.txt
index 006016c5daa24d555c8a5d9537b8bfbbd0c96229..33340476f9568dce65fbd43bcd3f745f80df32f6 100644
--- a/source/RobotAPI/statecharts/CMakeLists.txt
+++ b/source/RobotAPI/statecharts/CMakeLists.txt
@@ -13,3 +13,5 @@ add_subdirectory(StatechartExecutionGroup)
 
 add_subdirectory(ProsthesisKinestheticTeachIn)
 add_subdirectory(DebugDrawerToArVizGroup)
+
+add_subdirectory(ObjectMemoryGroup)
diff --git a/source/RobotAPI/statecharts/ObjectMemoryGroup/CMakeLists.txt b/source/RobotAPI/statecharts/ObjectMemoryGroup/CMakeLists.txt
new file mode 100644
index 0000000000000000000000000000000000000000..a751e89b2566ed34fadcfa9c04943088955c1d5e
--- /dev/null
+++ b/source/RobotAPI/statecharts/ObjectMemoryGroup/CMakeLists.txt
@@ -0,0 +1,31 @@
+# Modern CMake way:
+#armarx_add_statechart(ObjectMemoryGroup
+#    SOURCES
+#        ObjectMemoryGroupRemoteStateOfferer.cpp
+#    HEADERS
+#        ObjectMemoryGroupRemoteStateOfferer.h
+#    DEPENDENCIES
+#)
+
+# Legacy CMake way:
+
+armarx_component_set_name("ObjectMemoryGroup")
+
+set(COMPONENT_LIBS
+    ArmarXCoreInterfaces ArmarXCore ArmarXCoreStatechart ArmarXCoreObservers
+    # RobotAPI
+    RobotAPIArmarXObjects
+    armem_objects
+)
+
+set(SOURCES
+    ObjectMemoryGroupRemoteStateOfferer.cpp
+)
+
+set(HEADERS
+    ObjectMemoryGroupRemoteStateOfferer.h
+    ObjectMemoryGroup.scgxml
+)
+
+armarx_generate_statechart_cmake_lists()
+armarx_add_component("${SOURCES}" "${HEADERS}")
diff --git a/source/RobotAPI/statecharts/ObjectMemoryGroup/ObjectMemoryGroup.scgxml b/source/RobotAPI/statecharts/ObjectMemoryGroup/ObjectMemoryGroup.scgxml
new file mode 100644
index 0000000000000000000000000000000000000000..8f7d00053ef37819464e9d1b7bc4171cf4caf72b
--- /dev/null
+++ b/source/RobotAPI/statecharts/ObjectMemoryGroup/ObjectMemoryGroup.scgxml
@@ -0,0 +1,11 @@
+<?xml version="1.0" encoding="utf-8"?>
+<StatechartGroup name="ObjectMemoryGroup" package="RobotAPI" generateContext="true">
+	<Proxies>
+		<Proxy value="RobotAPIInterfaces.MemoryNameSystem"/>
+	</Proxies>
+	<Folder basename="test">
+		<State filename="RequestObjectsTest.xml" visibility="public"/>
+	</Folder>
+	<State filename="RequestObjects.xml" visibility="public"/>
+</StatechartGroup>
+
diff --git a/source/RobotAPI/statecharts/ObjectMemoryGroup/ObjectMemoryGroupRemoteStateOfferer.cpp b/source/RobotAPI/statecharts/ObjectMemoryGroup/ObjectMemoryGroupRemoteStateOfferer.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..1324dfff62f4a6ec3df04e61d451f062125a50c8
--- /dev/null
+++ b/source/RobotAPI/statecharts/ObjectMemoryGroup/ObjectMemoryGroupRemoteStateOfferer.cpp
@@ -0,0 +1,29 @@
+#include "ObjectMemoryGroupRemoteStateOfferer.h"
+
+namespace armarx::ObjectMemoryGroup
+{
+    // DO NOT EDIT NEXT LINE
+    ObjectMemoryGroupRemoteStateOfferer::SubClassRegistry ObjectMemoryGroupRemoteStateOfferer::Registry(ObjectMemoryGroupRemoteStateOfferer::GetName(), &ObjectMemoryGroupRemoteStateOfferer::CreateInstance);
+
+    ObjectMemoryGroupRemoteStateOfferer::ObjectMemoryGroupRemoteStateOfferer(StatechartGroupXmlReaderPtr reader) :
+        XMLRemoteStateOfferer < ObjectMemoryGroupStatechartContext > (reader)
+    {}
+
+    void ObjectMemoryGroupRemoteStateOfferer::onInitXMLRemoteStateOfferer() {}
+
+    void ObjectMemoryGroupRemoteStateOfferer::onConnectXMLRemoteStateOfferer() {}
+
+    void ObjectMemoryGroupRemoteStateOfferer::onExitXMLRemoteStateOfferer() {}
+
+    // DO NOT EDIT NEXT FUNCTION
+    std::string ObjectMemoryGroupRemoteStateOfferer::GetName()
+    {
+        return "ObjectMemoryGroupRemoteStateOfferer";
+    }
+
+    // DO NOT EDIT NEXT FUNCTION
+    XMLStateOffererFactoryBasePtr ObjectMemoryGroupRemoteStateOfferer::CreateInstance(StatechartGroupXmlReaderPtr reader)
+    {
+        return XMLStateOffererFactoryBasePtr(new ObjectMemoryGroupRemoteStateOfferer(reader));
+    }
+}
diff --git a/source/RobotAPI/statecharts/ObjectMemoryGroup/ObjectMemoryGroupRemoteStateOfferer.h b/source/RobotAPI/statecharts/ObjectMemoryGroup/ObjectMemoryGroupRemoteStateOfferer.h
new file mode 100644
index 0000000000000000000000000000000000000000..882627aec09b55c16b4b0f07fe313c0138392368
--- /dev/null
+++ b/source/RobotAPI/statecharts/ObjectMemoryGroup/ObjectMemoryGroupRemoteStateOfferer.h
@@ -0,0 +1,26 @@
+#pragma once
+
+#include <ArmarXCore/statechart/xmlstates/XMLRemoteStateOfferer.h>
+#include "ObjectMemoryGroupStatechartContext.generated.h"
+
+namespace armarx::ObjectMemoryGroup
+{
+    class ObjectMemoryGroupRemoteStateOfferer :
+        virtual public XMLRemoteStateOfferer < ObjectMemoryGroupStatechartContext > // Change this statechart context if you need another context (dont forget to change in the constructor as well)
+    {
+    public:
+        ObjectMemoryGroupRemoteStateOfferer(StatechartGroupXmlReaderPtr reader);
+
+        // inherited from RemoteStateOfferer
+        void onInitXMLRemoteStateOfferer() override;
+        void onConnectXMLRemoteStateOfferer() override;
+        void onExitXMLRemoteStateOfferer() override;
+
+        // static functions for AbstractFactory Method
+        static std::string GetName();
+        static XMLStateOffererFactoryBasePtr CreateInstance(StatechartGroupXmlReaderPtr reader);
+        static SubClassRegistry Registry;
+
+
+    };
+}
diff --git a/source/RobotAPI/statecharts/ObjectMemoryGroup/RequestObjects.cpp b/source/RobotAPI/statecharts/ObjectMemoryGroup/RequestObjects.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..562ddabd56b6d07428f8ce2b386fa682ac95dd1f
--- /dev/null
+++ b/source/RobotAPI/statecharts/ObjectMemoryGroup/RequestObjects.cpp
@@ -0,0 +1,133 @@
+#include "RequestObjects.h"
+
+//#include <ArmarXCore/core/time/TimeUtil.h>
+//#include <ArmarXCore/observers/variant/DatafieldRef.h>
+
+#include <RobotAPI/libraries/armem_objects/client/instance/ObjectReader.h>
+#include <RobotAPI/libraries/ArmarXObjects/ObjectID.h>
+#include <RobotAPI/libraries/ArmarXObjects/ice_conversions.h>
+
+#include "ObjectMemoryGroupStatechartContext.generated.h"
+
+namespace armarx::ObjectMemoryGroup
+{
+    // DO NOT EDIT NEXT LINE
+    RequestObjects::SubClassRegistry RequestObjects::Registry(RequestObjects::GetName(), &RequestObjects::CreateInstance);
+
+    RequestObjects::RequestObjects(const XMLStateConstructorParams& stateData):
+        XMLStateTemplate<RequestObjects>(stateData), RequestObjectsGeneratedBase<RequestObjects>(stateData)
+    {
+    }
+
+    void RequestObjects::onEnter()
+    {
+
+        // put your user code for the enter-point here
+        // execution time should be short (<100ms)
+    }
+
+    void RequestObjects::run()
+    {
+        if (not in.getEnable())
+        {
+            emitSuccess();
+            return;
+        }
+
+        using Reader = armarx::armem::obj::instance::Reader;
+
+        const std::string provider = in.isProviderSet() ? in.getProvider() : "";
+
+        const std::vector<std::string> objectIdsString = in.getObjectIds();
+        const armarx::Duration relativeTimeout = armarx::Duration::MilliSeconds(in.getRelativeTimeoutMilliseconds());
+
+        std::stringstream info;
+        std::stringstream warn;
+
+        std::vector<armarx::ObjectID> objectIds;
+        for (const std::string& idString : objectIdsString)
+        {
+            try
+            {
+                 armarx::ObjectID id = armarx::ObjectID::FromString(idString);
+                 objectIds.push_back(id);
+                 info << "Requesting object " << id << "\n";
+            }
+            catch (const armarx::LocalException& e)
+            {
+                warn << "\nGiven object ID '" << idString << "' could not parsed as ObjectID: " << e.what();
+            }
+        }
+
+        auto context = getContext<ObjectMemoryGroupStatechartContext>();
+        armarx::armem::client::MemoryNameSystem mns(getMemoryNameSystem(), context);
+
+        Reader reader{mns};
+        reader.connect();
+        objpose::ObjectPoseStorageInterfacePrx storage = reader.getObjectPoseStorage();
+
+        armarx::objpose::observer::RequestObjectsInput input;
+        input.provider = provider;
+        for (const armarx::ObjectID& id : objectIds)
+        {
+            armarx::toIce(input.request.objectIDs.emplace_back(), id);
+        }
+        input.request.relativeTimeoutMS = relativeTimeout.toMilliSeconds();
+
+
+        objpose::observer::RequestObjectsOutput output;
+        try
+        {
+            output = storage->requestObjects(input);
+        }
+        catch (const Ice::Exception& e)
+        {
+            ARMARX_WARNING << "Failed to request object localization: " << e.what();
+            emitFailure();
+            return;
+        }
+
+        for (const auto& [id, result] : output.results)
+        {
+            if (result.result.success)
+            {
+                info << "Requested object " << id << " via provider '" << result.providerName << "'.\n";
+            }
+            else
+            {
+                warn << "\nFailed to request the object " << id << " for localization.";
+            }
+        }
+
+        if (not info.str().empty())
+        {
+            ARMARX_INFO << info.str();
+        }
+        if (not warn.str().empty())
+        {
+            ARMARX_WARNING << "The following issues occurred whhen requesting objects for localization:"
+                           << warn.str();
+        }
+
+        emitSuccess();
+    }
+
+    //void RequestObjects::onBreak()
+    //{
+    //    // put your user code for the breaking point here
+    //    // execution time should be short (<100ms)
+    //}
+
+    void RequestObjects::onExit()
+    {
+        // put your user code for the exit point here
+        // execution time should be short (<100ms)
+    }
+
+
+    // DO NOT EDIT NEXT FUNCTION
+    XMLStateFactoryBasePtr RequestObjects::CreateInstance(XMLStateConstructorParams stateData)
+    {
+        return XMLStateFactoryBasePtr(new RequestObjects(stateData));
+    }
+}
diff --git a/source/RobotAPI/statecharts/ObjectMemoryGroup/RequestObjects.h b/source/RobotAPI/statecharts/ObjectMemoryGroup/RequestObjects.h
new file mode 100644
index 0000000000000000000000000000000000000000..4390865434749d591d6082df003c55e3b8560cd6
--- /dev/null
+++ b/source/RobotAPI/statecharts/ObjectMemoryGroup/RequestObjects.h
@@ -0,0 +1,27 @@
+#pragma once
+
+#include <RobotAPI/statecharts/ObjectMemoryGroup/RequestObjects.generated.h>
+
+namespace armarx::ObjectMemoryGroup
+{
+    class RequestObjects :
+        public RequestObjectsGeneratedBase < RequestObjects >
+    {
+    public:
+        RequestObjects(const XMLStateConstructorParams& stateData);
+
+        // inherited from StateBase
+        void onEnter() override;
+        void run() override;
+        // void onBreak() override;
+        void onExit() override;
+
+        // static functions for AbstractFactory Method
+        static XMLStateFactoryBasePtr CreateInstance(XMLStateConstructorParams stateData);
+        static SubClassRegistry Registry;
+
+        // DO NOT INSERT ANY CLASS MEMBERS,
+        // use stateparameters instead,
+        // if classmember are neccessary nonetheless, reset them in onEnter
+    };
+}
diff --git a/source/RobotAPI/statecharts/ObjectMemoryGroup/RequestObjects.xml b/source/RobotAPI/statecharts/ObjectMemoryGroup/RequestObjects.xml
new file mode 100644
index 0000000000000000000000000000000000000000..8b32c20109a1bee77bcd3ee1203716d3abb02f0d
--- /dev/null
+++ b/source/RobotAPI/statecharts/ObjectMemoryGroup/RequestObjects.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+<State version="1.2" name="RequestObjects" uuid="9F09FB2F-CC0C-4B8A-A716-F130E04A7230" width="800" height="600" type="Normal State">
+	<InputParameters>
+		<Parameter name="Enable" type="::armarx::BoolVariantData" docType="bool" optional="no">
+			<DefaultValue value='{"type":"::armarx::SingleVariantBase","variant":{"typeName":"::armarx::BoolVariantData","value":true}}' docValue="True"/>
+		</Parameter>
+		<Parameter name="ObjectIds" type="::armarx::SingleTypeVariantListBase(::armarx::StringVariantData)" docType="List(string)" optional="no"/>
+		<Parameter name="Provider" type="::armarx::StringVariantData" docType="string" optional="yes"/>
+		<Parameter name="RelativeTimeoutMilliseconds" type="::armarx::IntVariantData" docType="int" optional="no"/>
+	</InputParameters>
+	<OutputParameters/>
+	<LocalParameters/>
+	<Substates/>
+	<Events>
+		<Event name="Failure">
+			<Description>Event for statechart-internal failures or optionally user-code failures</Description>
+		</Event>
+		<Event name="Success"/>
+	</Events>
+	<Transitions/>
+</State>
+
diff --git a/source/RobotAPI/statecharts/ObjectMemoryGroup/test/RequestObjectsTest.xml b/source/RobotAPI/statecharts/ObjectMemoryGroup/test/RequestObjectsTest.xml
new file mode 100644
index 0000000000000000000000000000000000000000..edb16e98297feb19d1769ca6c54ab28901da7ad1
--- /dev/null
+++ b/source/RobotAPI/statecharts/ObjectMemoryGroup/test/RequestObjectsTest.xml
@@ -0,0 +1,67 @@
+<?xml version="1.0" encoding="utf-8"?>
+<State version="1.2" name="RequestObjectsTest" uuid="E74E1D8D-2E97-4846-9282-73AC4F49FAEE" width="493.167" height="355.278" type="Normal State">
+	<InputParameters>
+		<Parameter name="ObjectIds" type="::armarx::SingleTypeVariantListBase(::armarx::StringVariantData)" docType="List(string)" optional="no">
+			<DefaultValue value='{"array":[{"type":"::armarx::SingleVariantBase","variant":{"typeName":"::armarx::StringVariantData","value":"Maintenance/spraybottle"}},{"type":"::armarx::SingleVariantBase","variant":{"typeName":"::armarx::StringVariantData","value":"Maintenance/handwash-paste"}},{"type":"::armarx::SingleVariantBase","variant":{"typeName":"::armarx::StringVariantData","value":"Maintenance/mounting-adhesive"}},{"type":"::armarx::SingleVariantBase","variant":{"typeName":"::armarx::StringVariantData","value":"Maintenance/multipurpose-grease"}}],"type":"::armarx::SingleTypeVariantListBase"}' docValue="Maintenance/spraybottle\nMaintenance/handwash-paste\nMaintenance/mounting-adhesive\nMaintenance/multipurpose-grease"/>
+		</Parameter>
+		<Parameter name="Provider" type="::armarx::StringVariantData" docType="string" optional="no">
+			<DefaultValue value='{"type":"::armarx::SingleVariantBase","variant":{"typeName":"::armarx::StringVariantData","value":"sim_track"}}' docValue="sim_track"/>
+		</Parameter>
+		<Parameter name="RelativeTimeoutMilliseconds" type="::armarx::IntVariantData" docType="int" optional="no">
+			<DefaultValue value='{"type":"::armarx::SingleVariantBase","variant":{"typeName":"::armarx::IntVariantData","value":10000}}' docValue="10000"/>
+		</Parameter>
+	</InputParameters>
+	<OutputParameters/>
+	<LocalParameters/>
+	<Substates>
+		<EndState name="Failure" event="Failure" left="363.167" top="140.056" boundingSquareSize="99.6636"/>
+		<LocalState name="RequestObjects" refuuid="9F09FB2F-CC0C-4B8A-A716-F130E04A7230" left="114.167" top="196.278" boundingSquareSize="99.6636"/>
+		<EndState name="Success" event="Success" left="363.167" top="250.278" boundingSquareSize="99.6636"/>
+	</Substates>
+	<Events>
+		<Event name="Failure">
+			<Description>Event for statechart-internal failures or optionally user-code failures</Description>
+		</Event>
+	</Events>
+	<StartState substateName="RequestObjects">
+		<ParameterMappings>
+			<ParameterMapping sourceType="Parent" from="ObjectIds" to="ObjectIds"/>
+			<ParameterMapping sourceType="Parent" from="Provider" to="Provider"/>
+			<ParameterMapping sourceType="Parent" from="RelativeTimeoutMilliseconds" to="RelativeTimeoutMilliseconds"/>
+		</ParameterMappings>
+		<SupportPoints>
+			<SupportPoint posX="67.1067" posY="233.278"/>
+			<SupportPoint posX="76.5839" posY="233.278"/>
+			<SupportPoint posX="88.7241" posY="233.278"/>
+			<SupportPoint posX="101.186" posY="233.278"/>
+		</SupportPoints>
+	</StartState>
+	<Transitions>
+		<Transition from="RequestObjects" to="Failure" eventName="Failure">
+			<ParameterMappings/>
+			<ParameterMappingsToParentsLocal/>
+			<ParameterMappingsToParentsOutput/>
+			<SupportPoints>
+				<SupportPoint posX="214.588" posY="221.9"/>
+				<SupportPoint posX="253.892" posY="213.031"/>
+				<SupportPoint posX="308.683" posY="200.669"/>
+				<SupportPoint posX="350.786" posY="191.175"/>
+			</SupportPoints>
+		</Transition>
+		<Transition from="RequestObjects" to="Success" eventName="Success">
+			<ParameterMappings/>
+			<ParameterMappingsToParentsLocal/>
+			<ParameterMappingsToParentsOutput/>
+			<SupportPoints>
+				<SupportPoint posX="214.358" posY="252.153"/>
+				<SupportPoint posX="221.884" posY="254.613"/>
+				<SupportPoint posX="229.602" posY="256.935"/>
+				<SupportPoint posX="237" posY="258.833"/>
+				<SupportPoint posX="274.158" posY="268.372"/>
+				<SupportPoint posX="316.529" posY="275.551"/>
+				<SupportPoint posX="350.428" posY="280.424"/>
+			</SupportPoints>
+		</Transition>
+	</Transitions>
+</State>
+