diff --git a/scenarios/ArMemObjectMemory/config/ArticulatedObjectLocalizerExample.cfg b/scenarios/ArMemObjectMemory/config/ArticulatedObjectLocalizerExample.cfg
index 50dce2f4a5313f280f8f06bab180de49a4ce8098..82769e0f22bfa6de0ca678be094d396df07c89e0 100644
--- a/scenarios/ArMemObjectMemory/config/ArticulatedObjectLocalizerExample.cfg
+++ b/scenarios/ArMemObjectMemory/config/ArticulatedObjectLocalizerExample.cfg
@@ -102,6 +102,14 @@ ArmarX.ArticulatedObjectLocalizerExample.mem.obj.articulated.ProviderName = Exam
 # ArmarX.ArticulatedObjectLocalizerExample.tpc.sub.MemoryListener = MemoryUpdates
 
 
+# ArmarX.ArticulatedObjectLocalizerExample.updateFrequency:  Memory update frequency (write).
+#  Attributes:
+#  - Default:            25
+#  - Case sensitivity:   yes
+#  - Required:           no
+# ArmarX.ArticulatedObjectLocalizerExample.updateFrequency = 25
+
+
 # ArmarX.CachePath:  Path for cache files. If relative path AND env. variable ARMARX_USER_CONFIG_DIR is set, the cache path will be made relative to ARMARX_USER_CONFIG_DIR. Otherwise if relative it will be relative to the default ArmarX config dir (${HOME}/.armarx)
 #  Attributes:
 #  - Default:            mongo/.cache
diff --git a/source/RobotAPI/components/armem/server/ObjectMemory/ObjectMemory.cpp b/source/RobotAPI/components/armem/server/ObjectMemory/ObjectMemory.cpp
index 837fcbcf8278e12b120b3dc9ff0a0b1de514fc9a..b6d997f6882daa1b9ee95d97fb4502ae181aa9ab 100644
--- a/source/RobotAPI/components/armem/server/ObjectMemory/ObjectMemory.cpp
+++ b/source/RobotAPI/components/armem/server/ObjectMemory/ObjectMemory.cpp
@@ -57,6 +57,8 @@ namespace armarx::armem::server::obj
         articulatedObjectInstanceSegment.defineProperties(defs, prefix + "articulated.inst.");
         articulatedObjectClassSegment.defineProperties(defs, prefix + "articulated.cls.");
 
+        attachmentSegment.defineProperties(defs, prefix + "attachments.");
+
         return defs;
     }
 
@@ -69,7 +71,9 @@ namespace armarx::armem::server::obj
         articulatedObjectClassSegment(server::ComponentPluginUser::iceMemory,
                                       server::ComponentPluginUser::workingMemoryMutex),
         articulatedObjectInstanceSegment(server::ComponentPluginUser::iceMemory,
-                                         server::ComponentPluginUser::workingMemoryMutex)
+                                         server::ComponentPluginUser::workingMemoryMutex),
+        attachmentSegment(server::ComponentPluginUser::iceMemory,
+                          server::ComponentPluginUser::workingMemoryMutex)
     {
     }
 
@@ -120,6 +124,10 @@ namespace armarx::armem::server::obj
             articulatedObjectInstanceSegment.init();
         });
 
+        initSegmentWithCatch("attachment", [&]()
+        {
+            attachmentSegment.init();
+        });
 
     }
 
@@ -155,12 +163,9 @@ namespace armarx::armem::server::obj
             ArVizComponentPluginUser::getArvizClient()
         );
 
-
-        // {
-        //     std::lock_guard g(server::ComponentPluginUser::workingMemoryMutex);
-        //     // server::ComponentPluginUser::workingMemory.addCoreSegment("ArticulatedObjectInstance"); // TODO , arondto::::toInitialAronType());
-        //     server::ComponentPluginUser::workingMemory.addCoreSegment("ArticulatedObjectClass"); // TODO , arondto::::toInitialAronType());
-        // }
+        attachmentSegment.connect(
+            ArVizComponentPluginUser::getArvizClient()
+        );
 
         createRemoteGuiTab();
         RemoteGui_startRunningTask();
diff --git a/source/RobotAPI/components/armem/server/ObjectMemory/ObjectMemory.h b/source/RobotAPI/components/armem/server/ObjectMemory/ObjectMemory.h
index 822fabbe56fad5158337c81c9c0089aa5d7233c2..2dfd668d1e43df914ff7b2f02205e699ad2ea5e9 100644
--- a/source/RobotAPI/components/armem/server/ObjectMemory/ObjectMemory.h
+++ b/source/RobotAPI/components/armem/server/ObjectMemory/ObjectMemory.h
@@ -40,6 +40,7 @@
 #include <RobotAPI/libraries/armem_objects/server/instance/SegmentAdapter.h>
 #include <RobotAPI/libraries/armem_objects/server/articulated_object_instance/Segment.h>
 #include <RobotAPI/libraries/armem_objects/server/articulated_object_class/Segment.h>
+#include <RobotAPI/libraries/armem_objects/server/attachments/Segment.h>
 
 
 #define ICE_CURRENT_ARG const Ice::Current& = Ice::emptyCurrent
@@ -112,7 +113,9 @@ namespace armarx::armem::server::obj
 
         articulated_object_class::Segment articulatedObjectClassSegment;
         articulated_object_instance::Segment articulatedObjectInstanceSegment;
+        attachments::Segment attachmentSegment;
 
+        // associations::Segment associationsSegment;
 
         struct RemoteGuiTab : armarx::RemoteGui::Client::Tab
         {
diff --git a/source/RobotAPI/libraries/armem_objects/CMakeLists.txt b/source/RobotAPI/libraries/armem_objects/CMakeLists.txt
index ed02a9adf315ef755af2c8da64d4a37c3d4817b6..8c0f625f022e3efeb7cf7763841a25e6469b6ac8 100644
--- a/source/RobotAPI/libraries/armem_objects/CMakeLists.txt
+++ b/source/RobotAPI/libraries/armem_objects/CMakeLists.txt
@@ -34,8 +34,14 @@ armarx_add_library(
         # server/articulated_object/SegmentAdapter.h
         server/articulated_object_instance/Visu.h
 
-        client/articulated_object/Reader.cpp
-        client/articulated_object/Writer.cpp
+        server/attachments/Segment.h
+
+        client/articulated_object/Reader.h
+        client/articulated_object/Writer.h
+        client/articulated_object/interfaces.h
+
+        client/attachment/Reader.h
+        client/attachment/Writer.h
 
     SOURCES
         aron_conversions.cpp
@@ -55,9 +61,13 @@ armarx_add_library(
         # server/articulated_object/SegmentAdapter.cpp
         server/articulated_object_instance/Visu.cpp
 
-        client/articulated_object/Reader.h
-        client/articulated_object/Writer.h
-        client/articulated_object/interfaces.h
+        server/attachments/Segment.cpp
+
+        client/articulated_object/Reader.cpp
+        client/articulated_object/Writer.cpp
+
+        client/attachment/Reader.cpp
+        client/attachment/Writer.cpp
 
 )
 
@@ -70,8 +80,8 @@ armarx_enable_aron_file_generation_for_target(
         aron/ObjectClass.xml
         aron/ObjectInstance.xml
 
-        # aron/Attachment.xml
-        aron/Constraint.xml
+        aron/Attachment.xml
+        # aron/Constraint.xml
 )
 
 add_library(${PROJECT_NAME}::armem_objects ALIAS armem_objects)
diff --git a/source/RobotAPI/libraries/armem_objects/aron/Attachment.xml b/source/RobotAPI/libraries/armem_objects/aron/Attachment.xml
index 6b0227772cb6c40b0b449dcd3e931e5314ad1548..76cb21c07a16e8f37c0fa00f6a4ab2b90cfd2983 100644
--- a/source/RobotAPI/libraries/armem_objects/aron/Attachment.xml
+++ b/source/RobotAPI/libraries/armem_objects/aron/Attachment.xml
@@ -1,27 +1,71 @@
 <!--This class contains the data structure for ObjectPose -->
 <?xml version="1.0" encoding="UTF-8" ?>
 <AronTypeDefinition>
-    <CodeIncludes>
-        <Include include="<Eigen/Core>" />
+     <CodeIncludes>
+        <Include include="<RobotAPI/libraries/armem/aron/MemoryID.aron.generated.h>" />
     </CodeIncludes>
+     <AronIncludes>
+        <Include include="<RobotAPI/libraries/armem/aron/MemoryID.xml>" />
+    </AronIncludes>
     <GenerateTypes>
 
-        <Object name="armarx::armem::arondto::Attachment">
+        <Object name="armarx::armem::arondto::attachment::AgentDescription">
 
-            <ObjectChild key="constraintType">
+            <!-- Memory link pointing to arondto::Robot or arondto::ArticulatedObject -->
+            <ObjectChild key="id">
+                <armarx::armem::arondto::MemoryID />
+            </ObjectChild>
+
+            <!-- one of the robot's frames -->
+            <ObjectChild key="frame">
+                <string/>
+            </ObjectChild>
+        </Object>
 
+        <!-- Fixed transformation between agent and object -->
+        <Object name="armarx::armem::arondto::attachment::ObjectAttachment">
+            <ObjectChild key="agent">
+                <armarx::armem::arondto::attachment::AgentDescription />
             </ObjectChild>
 
             <ObjectChild key="transformation">
                 <Pose/>
             </ObjectChild>
 
-            <ObjectChild key="objectName">
-                <string/>
+            <ObjectChild key="object">
+                <armarx::armem::arondto::MemoryID />
             </ObjectChild>
 
-            <ObjectChild key="objectNode">
-                <string/>
+            <ObjectChild key="active">
+                <Bool/>
+            </ObjectChild>
+
+            <ObjectChild key="timestamp">
+                <Time/>
+            </ObjectChild>
+        </Object>
+
+        <!-- Fixed transformation between agent and articulated object -->
+        <Object name="armarx::armem::arondto::attachment::ArticulatedObjectAttachment">
+
+            <ObjectChild key="agent">
+                <armarx::armem::arondto::attachment::AgentDescription />
+            </ObjectChild>
+
+            <ObjectChild key="transformation">
+                <Pose/>
+            </ObjectChild>
+
+            <ObjectChild key="object">
+                <armarx::armem::arondto::attachment::AgentDescription />
+            </ObjectChild>
+
+            <ObjectChild key="active">
+                <Bool/>
+            </ObjectChild>
+
+            <ObjectChild key="timestamp">
+                <Time/>
             </ObjectChild>
         </Object>
 
diff --git a/source/RobotAPI/libraries/armem_objects/aron_conversions.cpp b/source/RobotAPI/libraries/armem_objects/aron_conversions.cpp
index 967060360c3bff360150f1c8988b5d40db4dbd5c..8602178224b696fdcf026f50184628ee7a870dae 100644
--- a/source/RobotAPI/libraries/armem_objects/aron_conversions.cpp
+++ b/source/RobotAPI/libraries/armem_objects/aron_conversions.cpp
@@ -2,9 +2,8 @@
 
 #include <RobotAPI/libraries/ArmarXObjects/aron_conversions.h>
 
-#include <RobotAPI/libraries/aron/common/aron_conversions/core.h>
-#include <RobotAPI/libraries/aron/common/aron_conversions/stl.h>
-#include <RobotAPI/libraries/aron/common/aron_conversions/armarx.h>
+#include <RobotAPI/libraries/aron/common/aron_conversions.h>
+#include <RobotAPI/libraries/armem/core/aron_conversions.h>
 
 namespace armarx::armem
 {
@@ -30,6 +29,61 @@ namespace armarx::armem
         objpose::toAron(dto.pose, bo);
     }
 
+
+    /* Attachments */
+    void fromAron(const arondto::attachment::AgentDescription& dto, attachment::AgentDescription& bo)
+    {
+        fromAron(dto.id, bo.id);
+        aron::fromAron(dto.frame, bo.frame);
+    }
+
+    void toAron(arondto::attachment::AgentDescription& dto, const attachment::AgentDescription& bo)
+    {
+        toAron(dto.id, bo.id);
+        aron::toAron(dto.frame, bo.frame);
+    }
+
+
+    void fromAron(const arondto::attachment::ObjectAttachment& dto, attachment::ObjectAttachment& bo)
+    {
+        fromAron(dto.agent, bo.agent);
+        aron::fromAron(dto.transformation, bo.transformation);
+        fromAron(dto.object, bo.object);
+        aron::fromAron(dto.active, bo.active);
+        // TODO aron::fromAron(dto.timestamp, bo.timestamp);
+    }
+
+    void toAron(arondto::attachment::ObjectAttachment& dto, const attachment::ObjectAttachment& bo)
+    {
+        toAron(dto.agent, bo.agent);
+        aron::toAron(dto.transformation, bo.transformation);
+        toAron(dto.object, bo.object);
+        aron::toAron(dto.active, bo.active);
+        // TODO aron::toAron(dto.timestamp, bo.timestamp);
+    }
+
+
+    void fromAron(const arondto::attachment::ArticulatedObjectAttachment& dto, attachment::ArticulatedObjectAttachment& bo)
+    {
+        fromAron(dto.agent, bo.agent);
+        aron::fromAron(dto.transformation, bo.transformation);
+        fromAron(dto.object, bo.object);
+        aron::fromAron(dto.active, bo.active);
+        // TODO aron::fromAron(dto.timestamp, bo.timestamp);
+    }
+
+    void toAron(arondto::attachment::ArticulatedObjectAttachment& dto, const attachment::ArticulatedObjectAttachment& bo)
+    {
+        toAron(dto.agent, bo.agent);
+        aron::toAron(dto.transformation, bo.transformation);
+        toAron(dto.object, bo.object);
+        aron::toAron(dto.active, bo.active);
+        // TODO aron::toAron(dto.timestamp, bo.timestamp);
+    }
+
+
+
+
 }  // namespace armarx::armem
 
 armarx::armem::MemoryID
diff --git a/source/RobotAPI/libraries/armem_objects/aron_conversions.h b/source/RobotAPI/libraries/armem_objects/aron_conversions.h
index 1d74e95317521e27467753e46320914192558908..61e89c37ec00aaabed94e1b20a2ba1b50be976a8 100644
--- a/source/RobotAPI/libraries/armem_objects/aron_conversions.h
+++ b/source/RobotAPI/libraries/armem_objects/aron_conversions.h
@@ -3,6 +3,8 @@
 #include <RobotAPI/libraries/ArmarXObjects/ObjectPose.h>
 
 #include <RobotAPI/libraries/armem_objects/aron/ObjectInstance.aron.generated.h>
+#include <RobotAPI/libraries/armem_objects/aron/Attachment.aron.generated.h>
+
 #include <RobotAPI/libraries/armem_objects/types.h>
 
 namespace armarx::armem
@@ -13,6 +15,17 @@ namespace armarx::armem
     void fromAron(const arondto::ObjectInstance& dto, objpose::ObjectPose& bo);
     void toAron(arondto::ObjectInstance& dto, const objpose::ObjectPose& bo);
 
+
+    /* Attachments */
+    void fromAron(const arondto::attachment::AgentDescription& dto, attachment::AgentDescription& bo);
+    void toAron(arondto::attachment::AgentDescription& dto, const attachment::AgentDescription& bo);
+
+    void fromAron(const arondto::attachment::ObjectAttachment& dto, attachment::ObjectAttachment& bo);
+    void toAron(arondto::attachment::ObjectAttachment& dto, const attachment::ObjectAttachment& bo);
+
+    void fromAron(const arondto::attachment::ArticulatedObjectAttachment& dto, attachment::ArticulatedObjectAttachment& bo);
+    void toAron(arondto::attachment::ArticulatedObjectAttachment& dto, const attachment::ArticulatedObjectAttachment& bo);
+
 }  // namespace armarx::armem
 
 
diff --git a/source/RobotAPI/libraries/armem_objects/client/attachment/Reader.cpp b/source/RobotAPI/libraries/armem_objects/client/attachment/Reader.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..e3ce169b9ef41292b7ad565f94b74faf141ee7ad
--- /dev/null
+++ b/source/RobotAPI/libraries/armem_objects/client/attachment/Reader.cpp
@@ -0,0 +1,210 @@
+#include "Reader.h"
+
+#include <mutex>
+#include <optional>
+
+#include "ArmarXCore/core/logging/Logging.h"
+#include <ArmarXCore/core/PackagePath.h>
+
+#include "RobotAPI/libraries/armem/core/Time.h"
+#include "RobotAPI/libraries/armem/client/query/Builder.h"
+#include "RobotAPI/libraries/armem/core/workingmemory/CoreSegment.h"
+#include "RobotAPI/libraries/armem/util/util.h"
+#include "RobotAPI/libraries/armem_robot/robot_conversions.h"
+#include "RobotAPI/libraries/armem_robot/aron_conversions.h"
+#include <RobotAPI/libraries/armem_robot/aron/Robot.aron.generated.h>
+#include <RobotAPI/libraries/armem_objects/aron/Attachment.aron.generated.h>
+#include <RobotAPI/libraries/armem_objects/aron_conversions.h>
+#include "RobotAPI/libraries/aron/common/aron_conversions.h"
+
+namespace armarx::armem::attachment
+{
+
+    namespace
+    {
+
+        template<typename AronClass, typename ArmemClass>
+        auto getAttachments(const armarx::armem::wm::Memory& memory)
+        {
+            // using ArmemClass = decltype(fromAron(AronClass()));
+            using ArmemClassVector = std::vector<ArmemClass>;
+
+            ArmemClassVector attachments;
+
+            for (const auto&[_, coreSegment] : memory.coreSegments())
+            {
+                for (const auto& [providerName, providerSegment] : coreSegment.providerSegments())
+                {
+                    for (const auto& [name, entity] : providerSegment.entities())
+                    {
+                        if (entity.empty())
+                        {
+                            ARMARX_WARNING << "No entity found";
+                            continue;
+                        }
+
+                        const auto entitySnapshots = simox::alg::get_values(entity.history());
+                        const armem::wm::EntityInstance& instance = entitySnapshots.front().getInstance(0);
+
+                        try
+                        {
+                            AronClass aronAttachment;
+                            aronAttachment.fromAron(instance.data());
+
+                            ArmemClass attachment;
+                            fromAron(aronAttachment, attachment);
+
+                            if (attachment.active)
+                            {
+                                attachments.push_back(attachment);
+                            }
+
+                        }
+                        catch (const armarx::aron::error::AronException&)
+                        {
+                            continue;
+                        }
+                    }
+                }
+            }
+
+            return attachments;
+        }
+    }  // namespace
+
+    Reader::Reader(armem::ClientReaderComponentPluginUser& component) : component(component) {}
+
+    void Reader::registerPropertyDefinitions(armarx::PropertyDefinitionsPtr& def)
+    {
+        ARMARX_DEBUG << "Reader: registerPropertyDefinitions";
+
+        const std::string prefix = propertyPrefix;
+
+        def->optional(properties.memoryName, prefix + "MemoryName");
+
+        def->optional(properties.coreAttachmentsSegmentName,
+                      prefix + "CoreSegment",
+                      "Name of the memory core segment to use for object attachments.");
+    }
+
+
+    void Reader::connect()
+    {
+        // Wait for the memory to become available and add it as dependency.
+        ARMARX_IMPORTANT << "Reader: Waiting for memory '" << properties.memoryName << "' ...";
+        auto result = component.useMemory(properties.memoryName);
+        if (not result.success)
+        {
+            ARMARX_ERROR << result.errorMessage;
+            return;
+        }
+
+        ARMARX_IMPORTANT << "Reader: Connected to memory '" << properties.memoryName;
+
+        memoryReader.setReadingMemory(result.proxy);
+    }
+
+
+    std::vector<ObjectAttachment> Reader::queryObjectAttachments(const armem::Time& timestamp) const
+    {
+        // Query all entities from all provider.
+        armem::client::query::Builder qb;
+
+        // clang-format off
+        qb
+        .coreSegments().withName(properties.coreAttachmentsSegmentName)
+        .providerSegments().all()
+        .entities().all()
+        .snapshots().beforeOrAtTime(timestamp);
+        // clang-format on
+
+        const armem::client::QueryResult qResult = memoryReader.query(qb.buildQueryInput());
+
+        ARMARX_DEBUG << "Lookup result in reader: " << qResult;
+
+        if (not qResult.success) /* c++20 [[unlikely]] */
+        {
+            return {};
+        }
+
+        return getAttachments<::armarx::armem::arondto::attachment::ObjectAttachment, ::armarx::armem::attachment::ObjectAttachment>(qResult.memory);
+    }
+
+    std::vector<ObjectAttachment> Reader::queryObjectAttachments(const armem::Time& timestamp, const std::string& providerName) const
+    {
+        // Query all entities from provider.
+        armem::client::query::Builder qb;
+
+        // clang-format off
+        qb
+        .coreSegments().withName(properties.coreAttachmentsSegmentName)
+        .providerSegments().withName(providerName)
+        .entities().all()
+        .snapshots().beforeOrAtTime(timestamp);
+        // clang-format on
+
+        const armem::client::QueryResult qResult = memoryReader.query(qb.buildQueryInput());
+
+        ARMARX_DEBUG << "Lookup result in reader: " << qResult;
+
+        if (not qResult.success) /* c++20 [[unlikely]] */
+        {
+            return {};
+        }
+
+        return getAttachments<::armarx::armem::arondto::attachment::ObjectAttachment, ::armarx::armem::attachment::ObjectAttachment>(qResult.memory);
+    }
+
+    std::vector<ArticulatedObjectAttachment> Reader::queryArticulatedObjectAttachments(const armem::Time& timestamp) const
+    {
+        // Query all entities from all provider.
+        armem::client::query::Builder qb;
+
+        // clang-format off
+        qb
+        .coreSegments().withName(properties.coreAttachmentsSegmentName)
+        .providerSegments().all()
+        .entities().all()
+        .snapshots().beforeOrAtTime(timestamp);
+        // clang-format on
+
+        const armem::client::QueryResult qResult = memoryReader.query(qb.buildQueryInput());
+
+        ARMARX_DEBUG << "Lookup result in reader: " << qResult;
+
+        if (not qResult.success) /* c++20 [[unlikely]] */
+        {
+            return {};
+        }
+
+        return getAttachments<::armarx::armem::arondto::attachment::ArticulatedObjectAttachment, ::armarx::armem::attachment::ArticulatedObjectAttachment>(qResult.memory);
+    }
+
+    std::vector<ArticulatedObjectAttachment> Reader::queryArticulatedObjectAttachments(const armem::Time& timestamp, const std::string& providerName) const
+    {
+        // Query all entities from provider.
+        armem::client::query::Builder qb;
+
+        // clang-format off
+        qb
+        .coreSegments().withName(properties.coreAttachmentsSegmentName)
+        .providerSegments().withName(providerName)
+        .entities().all()
+        .snapshots().beforeOrAtTime(timestamp);
+        // clang-format on
+
+        const armem::client::QueryResult qResult = memoryReader.query(qb.buildQueryInput());
+
+        ARMARX_DEBUG << "Lookup result in reader: " << qResult;
+
+        if (not qResult.success) /* c++20 [[unlikely]] */
+        {
+            return {};
+        }
+
+        return getAttachments<::armarx::armem::arondto::attachment::ArticulatedObjectAttachment, ::armarx::armem::attachment::ArticulatedObjectAttachment>(qResult.memory);
+    }
+
+
+
+}  // namespace armarx::armem::attachment
\ No newline at end of file
diff --git a/source/RobotAPI/libraries/armem_objects/client/attachment/Reader.h b/source/RobotAPI/libraries/armem_objects/client/attachment/Reader.h
new file mode 100644
index 0000000000000000000000000000000000000000..bcfb3d1a135a2446f255a0038a2aaad85c2a3412
--- /dev/null
+++ b/source/RobotAPI/libraries/armem_objects/client/attachment/Reader.h
@@ -0,0 +1,66 @@
+/*
+ * This file is part of ArmarX.
+ *
+ * ArmarX is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * ArmarX is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * @author     Fabian Reister ( fabian dot reister at kit dot edu )
+ * @date       2021
+ * @copyright  http://www.gnu.org/licenses/gpl-2.0.txt
+ *             GNU General Public License
+ */
+
+#pragma once
+
+#include <mutex>
+#include <optional>
+
+#include "RobotAPI/libraries/armem/client.h"
+#include "RobotAPI/libraries/armem/client/Reader.h"
+#include "RobotAPI/libraries/armem_objects/types.h"
+
+namespace armarx::armem::attachment
+{
+    class Reader
+    {
+    public:
+        Reader(armem::ClientReaderComponentPluginUser& component);
+        virtual ~Reader() = default;
+
+        void registerPropertyDefinitions(armarx::PropertyDefinitionsPtr& def);
+        void connect();
+
+        std::vector<ObjectAttachment> queryObjectAttachments(const armem::Time& timestamp) const;
+        std::vector<ObjectAttachment> queryObjectAttachments(const armem::Time& timestamp, const std::string& providerName) const;
+
+        std::vector<ArticulatedObjectAttachment> queryArticulatedObjectAttachments(const armem::Time& timestamp) const;
+        std::vector<ArticulatedObjectAttachment> queryArticulatedObjectAttachments(const armem::Time& timestamp, const std::string& providerName) const;
+
+    private:
+
+
+        struct Properties
+        {
+            std::string memoryName                  = "Object";
+            std::string coreAttachmentsSegmentName  = "Attachments";
+        } properties;
+
+        const std::string propertyPrefix = "mem.obj.attachment.";
+
+        armem::client::Reader memoryReader;
+        std::mutex memoryWriterMutex;
+
+        armem::ClientReaderComponentPluginUser& component;
+    };
+
+
+}  // namespace armarx::armem::attachment
\ No newline at end of file
diff --git a/source/RobotAPI/libraries/armem_objects/client/attachment/Writer.cpp b/source/RobotAPI/libraries/armem_objects/client/attachment/Writer.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..f4d16070b84e4d29aca1742ce0356fb0c69ea5b0
--- /dev/null
+++ b/source/RobotAPI/libraries/armem_objects/client/attachment/Writer.cpp
@@ -0,0 +1,144 @@
+#include "Writer.h"
+
+#include <IceUtil/Time.h>
+#include <SimoxUtility/algorithm/get_map_keys_values.h>
+#include <mutex>
+#include <optional>
+
+#include "ArmarXCore/core/logging/Logging.h"
+
+#include "RobotAPI/libraries/armem/core/MemoryID.h"
+#include "RobotAPI/libraries/armem_objects/aron_conversions.h"
+#include "RobotAPI/libraries/armem_robot/aron_conversions.h"
+#include <RobotAPI/libraries/armem_robot/aron/RobotDescription.aron.generated.h>
+#include <RobotAPI/libraries/armem_robot/aron/Robot.aron.generated.h>
+#include <RobotAPI/libraries/armem/core/aron_conversions.h>
+#include "RobotAPI/libraries/armem_robot/robot_conversions.h"
+
+
+namespace armarx::armem::attachment
+{
+    Writer::Writer(armem::ClientComponentPluginUser& component): component(component) {}
+
+    void Writer::registerPropertyDefinitions(armarx::PropertyDefinitionsPtr& def)
+    {
+        ARMARX_DEBUG << "Writer: registerPropertyDefinitions";
+
+        const std::string prefix = propertyPrefix;
+
+        def->optional(properties.memoryName, prefix + "MemoryName");
+
+        def->optional(properties.coreAttachmentsSegmentName,
+                      prefix + "CoreSegment",
+                      "Name of the memory core segment to use for object attachments.");
+        def->optional(properties.providerName, prefix + "ProviderName");
+    }
+
+    void Writer::connect()
+    {
+        // Wait for the memory to become available and add it as dependency.
+        ARMARX_IMPORTANT << "Writer: Waiting for memory '" << properties.memoryName << "' ...";
+        auto result = component.useMemory(properties.memoryName);
+        if (not result.success)
+        {
+            ARMARX_ERROR << result.errorMessage;
+            return;
+        }
+
+        ARMARX_IMPORTANT << "Writer: Connected to memory '" << properties.memoryName;
+
+        memoryWriter.setWritingMemory(result.proxy);
+        memoryReader.setReadingMemory(result.proxy);
+    }
+
+
+    std::optional<armem::MemoryID> Writer::commit(const ObjectAttachment& attachment)
+    {
+        std::lock_guard g{memoryWriterMutex};
+
+        const auto result = memoryWriter.addSegment(properties.coreAttachmentsSegmentName, properties.providerName);
+
+        if (not result.success)
+        {
+            ARMARX_ERROR << "Creating core segment failed. Reason: " << result.errorMessage;
+            return std::nullopt;
+        }
+
+        const auto& timestamp = attachment.timestamp;
+
+        const auto providerId = armem::MemoryID(result.segmentID);
+        const auto entityID =
+            providerId
+            .withEntityName(attachment.object.entityName) // TODO check if meaningful
+            .withTimestamp(timestamp);
+
+        armem::EntityUpdate update;
+        update.entityID = entityID;
+
+        arondto::attachment::ObjectAttachment aronAttachment;
+        toAron(aronAttachment, attachment);
+
+        update.instancesData = {aronAttachment.toAron()};
+        update.timeCreated   = timestamp;
+
+        ARMARX_DEBUG << "Committing " << update << " at time " << timestamp;
+        armem::EntityUpdateResult updateResult = memoryWriter.commit(update);
+
+        ARMARX_DEBUG << updateResult;
+
+        if (not updateResult.success)
+        {
+            ARMARX_ERROR << updateResult.errorMessage;
+            return std::nullopt;
+        }
+
+        return updateResult.snapshotID;
+
+    }
+
+    std::optional<armem::MemoryID> Writer::commit(const ArticulatedObjectAttachment& attachment)
+    {
+        std::lock_guard g{memoryWriterMutex};
+
+        const auto result = memoryWriter.addSegment(properties.coreAttachmentsSegmentName, properties.providerName);
+
+        if (not result.success)
+        {
+            ARMARX_ERROR << "Creating core segment failed. Reason: " << result.errorMessage;
+            return std::nullopt;
+        }
+
+        const auto& timestamp = attachment.timestamp;
+
+        const auto providerId = armem::MemoryID(result.segmentID);
+        const auto entityID =
+            providerId
+            .withEntityName(attachment.object.id.entityName) // TODO check if meaningful
+            .withTimestamp(timestamp);
+
+        armem::EntityUpdate update;
+        update.entityID = entityID;
+
+        arondto::attachment::ArticulatedObjectAttachment aronAttachment;
+        toAron(aronAttachment, attachment);
+
+        update.instancesData = {aronAttachment.toAron()};
+        update.timeCreated   = timestamp;
+
+        ARMARX_DEBUG << "Committing " << update << " at time " << timestamp;
+        armem::EntityUpdateResult updateResult = memoryWriter.commit(update);
+
+        ARMARX_DEBUG << updateResult;
+
+        if (not updateResult.success)
+        {
+            ARMARX_ERROR << updateResult.errorMessage;
+            return std::nullopt;
+        }
+
+        return updateResult.snapshotID;
+    }
+
+
+
+}  // namespace armarx::armem::attachment
\ No newline at end of file
diff --git a/source/RobotAPI/libraries/armem_objects/client/attachment/Writer.h b/source/RobotAPI/libraries/armem_objects/client/attachment/Writer.h
new file mode 100644
index 0000000000000000000000000000000000000000..f20421d4b27d9e2fc10e106e238a9684fca9d2cf
--- /dev/null
+++ b/source/RobotAPI/libraries/armem_objects/client/attachment/Writer.h
@@ -0,0 +1,73 @@
+/*
+ * This file is part of ArmarX.
+ *
+ * ArmarX is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * ArmarX is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * @author     Fabian Reister ( fabian dot reister at kit dot edu )
+ * @date       2021
+ * @copyright  http://www.gnu.org/licenses/gpl-2.0.txt
+ *             GNU General Public License
+ */
+
+#pragma once
+
+#include <mutex>
+
+#include "RobotAPI/libraries/armem/client/Reader.h"
+#include "RobotAPI/libraries/armem/client/Writer.h"
+#include "RobotAPI/libraries/armem/client.h"
+
+#include "RobotAPI/libraries/armem_robot_state/client/common/RobotReader.h"
+
+#include "RobotAPI/libraries/armem_objects/types.h"
+
+namespace armarx::armem::attachment
+{
+
+    class Writer
+    {
+    public:
+        Writer(armem::ClientComponentPluginUser& component);
+        virtual ~Writer() = default;
+
+
+        void registerPropertyDefinitions(armarx::PropertyDefinitionsPtr& def);
+        void connect();
+
+        std::optional<armem::MemoryID> commit(const ObjectAttachment& attachment);
+        std::optional<armem::MemoryID> commit(const ArticulatedObjectAttachment&);
+
+    private:
+
+        struct Properties
+        {
+            std::string memoryName                  = "Object";
+            std::string coreAttachmentsSegmentName  = "Attachments";
+            std::string providerName                = "AttachmentProvider";
+
+            bool allowClassCreation                 = false;
+        } properties;
+
+        const std::string propertyPrefix = "mem.obj.articulated.";
+
+        armem::client::Writer memoryWriter;
+        std::mutex memoryWriterMutex;
+
+        armem::client::Reader memoryReader;
+        std::mutex memoryReaderMutex;
+
+        armem::ClientComponentPluginUser& component;
+    };
+
+
+}  // namespace armarx::armem::attachment
\ No newline at end of file
diff --git a/source/RobotAPI/libraries/armem_objects/server/attachments/Segment.cpp b/source/RobotAPI/libraries/armem_objects/server/attachments/Segment.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..7f46c9b4509c54430eb2ddca0a10426d7ceab227
--- /dev/null
+++ b/source/RobotAPI/libraries/armem_objects/server/attachments/Segment.cpp
@@ -0,0 +1,127 @@
+#include "Segment.h"
+
+#include <sstream>
+
+#include <ArmarXCore/core/time/TimeUtil.h>
+#include "ArmarXCore/core/logging/Logging.h"
+
+#include "RobotAPI/libraries/armem/util/util.h"
+#include "RobotAPI/libraries/aron/common/aron_conversions.h"
+
+#include <RobotAPI/libraries/armem/core/aron_conversions.h>
+#include <RobotAPI/libraries/armem/core/workingmemory/Visitor.h>
+#include "RobotAPI/libraries/armem/core/MemoryID.h"
+#include <RobotAPI/libraries/armem/client/Writer.h>
+#include <RobotAPI/libraries/armem/client/query/Builder.h>
+#include <RobotAPI/libraries/armem/client/query/query_fns.h>
+#include <RobotAPI/libraries/armem/server/MemoryToIceAdapter.h>
+
+#include <RobotAPI/libraries/armem_objects/aron/Robot.aron.generated.h>
+#include <RobotAPI/libraries/armem_objects/aron_conversions.h>
+#include <RobotAPI/libraries/armem_objects/aron/Attachment.aron.generated.h>
+
+
+namespace armarx::armem::server::obj::attachments
+{
+
+    Segment::Segment(armem::server::MemoryToIceAdapter& memoryToIceAdapter, std::mutex& memoryMutex) :
+        iceMemory(memoryToIceAdapter),
+        memoryMutex(memoryMutex)
+    {
+        Logging::setTag("Attachments");
+    }
+
+    Segment::~Segment() = default;
+
+    void Segment::defineProperties(armarx::PropertyDefinitionsPtr defs, const std::string& prefix)
+    {
+        defs->optional(p.coreClassSegmentName, prefix + "CoreSegmentName", "Name of the object instance core segment.");
+        defs->optional(p.maxHistorySize, prefix + "MaxHistorySize", "Maximal size of object poses history (-1 for infinite).");
+    }
+
+    void Segment::init()
+    {
+        ARMARX_CHECK_NOT_NULL(iceMemory.workingMemory);
+
+        coreSegment = &iceMemory.workingMemory->addCoreSegment(p.coreClassSegmentName, arondto::Robot::toInitialAronType());
+        coreSegment->setMaxHistorySize(p.maxHistorySize);
+    }
+
+    void Segment::connect(viz::Client arviz)
+    {
+        // this->visu = std::make_unique<Visu>(arviz, *this);
+    }
+
+    std::vector<armarx::armem::attachment::ObjectAttachment> Segment::getAttachments(const armem::Time& timestamp) const
+    {
+        std::vector<armarx::armem::attachment::ObjectAttachment> attachments;
+
+        for (const auto& [_, provSeg] : iceMemory.workingMemory->getCoreSegment(p.coreClassSegmentName))
+        {
+            for (const auto& [name, entity] :  provSeg.entities())
+            {
+                const auto& entityInstance = entity.getLatestSnapshot().getInstance(0);
+                const auto aronAttachment = tryCast<armarx::armem::arondto::attachment::ObjectAttachment>(entityInstance);
+
+                if (not aronAttachment)
+                {
+                    ARMARX_WARNING << "Could not convert entity instance to 'ObjectAttachment'";
+                    continue;
+                }
+
+                ARMARX_DEBUG << "Key is " << armem::MemoryID(entity.id());
+
+                armarx::armem::attachment::ObjectAttachment attachment;
+                fromAron(*aronAttachment, attachment);
+
+                attachments.push_back(attachment);
+            }
+        }
+
+        return attachments;
+    }
+
+
+    // void Segment::RemoteGui::setup(const Segment& data)
+    // {
+    //     using namespace armarx::RemoteGui::Client;
+
+    //     maxHistorySize.setValue(std::max(1, int(data.p.maxHistorySize)));
+    //     maxHistorySize.setRange(1, 1e6);
+    //     infiniteHistory.setValue(data.p.maxHistorySize == -1);
+    //     discardSnapshotsWhileAttached.setValue(data.p.discardSnapshotsWhileAttached);
+
+    //     GridLayout grid;
+    //     int row = 0;
+    //     grid.add(Label("Max History Size"), {row, 0}).add(maxHistorySize, {row, 1});
+    //     row++;
+    //     grid.add(Label("Infinite History Size"), {row, 0}).add(infiniteHistory, {row, 1});
+    //     row++;
+    //     grid.add(Label("Discard Snapshots while Attached"), {row, 0}).add(discardSnapshotsWhileAttached, {row, 1});
+    //     row++;
+
+    //     group.setLabel("Data");
+    //     group.addChild(grid);
+    // }
+
+    // void Segment::RemoteGui::update(Segment& data)
+    // {
+    //     if (infiniteHistory.hasValueChanged() || maxHistorySize.hasValueChanged()
+    //         || discardSnapshotsWhileAttached.hasValueChanged())
+    //     {
+    //         std::scoped_lock lock(data.memoryMutex);
+
+    //         if (infiniteHistory.hasValueChanged() || maxHistorySize.hasValueChanged())
+    //         {
+    //             data.p.maxHistorySize = infiniteHistory.getValue() ? -1 : maxHistorySize.getValue();
+    //             if (data.coreSegment)
+    //             {
+    //                 data.coreSegment->setMaxHistorySize(long(data.p.maxHistorySize));
+    //             }
+    //         }
+
+    //         data.p.discardSnapshotsWhileAttached = discardSnapshotsWhileAttached.getValue();
+    //     }
+    // }
+
+}  // namespace armarx::armem::server::obj::attachments
diff --git a/source/RobotAPI/libraries/armem_objects/server/attachments/Segment.h b/source/RobotAPI/libraries/armem_objects/server/attachments/Segment.h
new file mode 100644
index 0000000000000000000000000000000000000000..3817bc22a51227422848ebbe1e4296aa570fee24
--- /dev/null
+++ b/source/RobotAPI/libraries/armem_objects/server/attachments/Segment.h
@@ -0,0 +1,107 @@
+/*
+ * This file is part of ArmarX.
+ *
+ * ArmarX is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * ArmarX is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * @author     Fabian Reister ( fabian dot reister at kit dot edu )
+ * @date       2021
+ * @copyright  http://www.gnu.org/licenses/gpl-2.0.txt
+ *             GNU General Public License
+ */
+
+#pragma once
+
+#include <string>
+#include <optional>
+#include <mutex>
+#include <unordered_map>
+
+#include <ArmarXCore/core/logging/Logging.h>
+#include "ArmarXCore/core/application/properties/PropertyDefinitionContainer.h"
+
+// #include "ArmarXGui/libraries/RemoteGui/Client/Widgets.h"
+
+#include "RobotAPI/components/ArViz/Client/Client.h"
+
+#include "RobotAPI/libraries/armem/core/MemoryID.h"
+#include "RobotAPI/libraries/armem/core/Time.h"
+#include "RobotAPI/libraries/armem_objects/types.h"
+
+namespace armarx::armem
+{
+    namespace server
+    {
+        class MemoryToIceAdapter;
+    }
+
+    namespace wm
+    {
+        class CoreSegment;
+    }
+}  // namespace armarx::armem
+
+
+namespace armarx::armem::server::obj::attachments
+{
+    class Visu;
+
+
+    class Segment : public armarx::Logging
+    {
+    public:
+        Segment(server::MemoryToIceAdapter& iceMemory,
+                std::mutex& memoryMutex);
+
+        virtual ~Segment();
+
+        void connect(viz::Client arviz);
+
+        void defineProperties(armarx::PropertyDefinitionsPtr defs, const std::string& prefix = "");
+
+        void init();
+
+        std::vector<armarx::armem::attachment::ObjectAttachment> getAttachments(const armem::Time& timestamp) const;
+
+
+    private:
+
+        server::MemoryToIceAdapter& iceMemory;
+        wm::CoreSegment* coreSegment = nullptr;
+        std::mutex& memoryMutex;
+
+        struct Properties
+        {
+            std::string coreClassSegmentName = "Attachments";
+            int64_t maxHistorySize = -1;
+        };
+        Properties p;
+
+        // std::unique_ptr<Visu> visu;
+
+    public:
+
+        // struct RemoteGui
+        // {
+        //     armarx::RemoteGui::Client::GroupBox group;
+
+        //     armarx::RemoteGui::Client::IntSpinBox maxHistorySize;
+        //     armarx::RemoteGui::Client::CheckBox infiniteHistory;
+        //     armarx::RemoteGui::Client::CheckBox discardSnapshotsWhileAttached;
+
+        //     void setup(const Segment& data);
+        //     void update(Segment& data);
+        // };
+
+    };
+
+}  // namespace armarx::armem::server::obj::attachments
diff --git a/source/RobotAPI/libraries/armem_objects/types.h b/source/RobotAPI/libraries/armem_objects/types.h
index 855c855c4d36d5cf02785b6e34d652b1f82b1272..976f438e7c39009fd5d37fb6afdf19378da488c4 100644
--- a/source/RobotAPI/libraries/armem_objects/types.h
+++ b/source/RobotAPI/libraries/armem_objects/types.h
@@ -21,9 +21,75 @@
 
 #pragma once
 
+#include "RobotAPI/libraries/armem/core/Time.h"
 #include <vector>
 
+#include <Eigen/Geometry>
+
 #include <RobotAPI/libraries/armem_robot/types.h>
+#include <RobotAPI/libraries/armem/core/MemoryID.h>
+
+
+namespace armarx::armem::attachment
+{
+    using AgentID = armem::MemoryID;
+    using ObjectID = armem::MemoryID;
+
+    struct AgentDescription
+    {
+        /**
+         * @brief id either pointing to a arondto::Robot or arondto::ArticulatedObject
+         *
+         */
+        AgentID id;
+
+        std::string frame;
+    };
+
+    /**
+     * @brief ObjectAttachment describes a fixed transformation between an agent and an object.
+     *
+     *  The transformation is defined as follows:
+     *
+     *      agent.frame -> object root frame
+     *
+     */
+    struct ObjectAttachment
+    {
+        AgentDescription agent;
+
+        Eigen::Affine3f transformation;
+
+        ObjectID object;
+
+        armem::Time timestamp;
+
+        bool active;
+    };
+
+    /**
+     * @brief ArticulatedObjectAttachment describes a fixed transformation between an agent and an articulated object.
+     *
+     *  The transformation is defined as follows:
+     *
+     *      agent.frame -> object.frame
+     *
+     */
+    struct ArticulatedObjectAttachment
+    {
+        AgentDescription agent;
+
+        Eigen::Affine3f transformation;
+
+        AgentDescription object;
+
+        armem::Time timestamp;
+
+        bool active;
+
+    };
+
+}  // namespace armarx::armem::attachment
 
 namespace armarx::armem::articulated_object
 {
diff --git a/source/RobotAPI/libraries/armem_robot_state/CMakeLists.txt b/source/RobotAPI/libraries/armem_robot_state/CMakeLists.txt
index 2eead70ac6845aedad5d4f1e5c69e9c0d8522347..6484c97ca0695848fc92dcb34008fc5b1d7c70f9 100644
--- a/source/RobotAPI/libraries/armem_robot_state/CMakeLists.txt
+++ b/source/RobotAPI/libraries/armem_robot_state/CMakeLists.txt
@@ -43,6 +43,7 @@ armarx_add_library(
 
 
         ./aron_conversions.h
+        ./utils.h
     SOURCES
         ./common/localization/TransformHelper.cpp
 
@@ -64,6 +65,8 @@ armarx_add_library(
         ./server/description/Segment.cpp
 
         ./aron_conversions.cpp
+        ./utils.cpp
+
 )
 
 
diff --git a/source/RobotAPI/libraries/armem_robot_state/utils.cpp b/source/RobotAPI/libraries/armem_robot_state/utils.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..9f4b84fdfbee87a4ca768837aa41039f1970115e
--- /dev/null
+++ b/source/RobotAPI/libraries/armem_robot_state/utils.cpp
@@ -0,0 +1,11 @@
+#include "utils.h"
+
+namespace armarx::armem::robot_state
+{
+    armarx::armem::MemoryID makeMemoryID(const robot::RobotDescription& desc)
+    {
+        return MemoryID("RobotState/Description")
+               .withProviderSegmentName(desc.name)
+               .withEntityName("description");
+    }
+}
\ No newline at end of file
diff --git a/source/RobotAPI/libraries/armem_robot_state/utils.h b/source/RobotAPI/libraries/armem_robot_state/utils.h
new file mode 100644
index 0000000000000000000000000000000000000000..239e0ddb2d1b99a513ed97a3e1b8fb63122a4c70
--- /dev/null
+++ b/source/RobotAPI/libraries/armem_robot_state/utils.h
@@ -0,0 +1,10 @@
+#pragma once
+
+#include "RobotAPI/libraries/armem/core/MemoryID.h"
+#include "RobotAPI/libraries/armem_robot/types.h"
+
+namespace armarx::armem::robot_state
+{
+    armarx::armem::MemoryID makeMemoryID(const robot::RobotDescription& desc);
+}
+