diff --git a/source/RobotAPI/components/ObjectPoseObserver/ObjectPoseObserver.cpp b/source/RobotAPI/components/ObjectPoseObserver/ObjectPoseObserver.cpp
index fc2625dfa6faeb3632f787dcff73c98a6f073659..ede848186b52ea4c41008e196f0715fb56915d27 100644
--- a/source/RobotAPI/components/ObjectPoseObserver/ObjectPoseObserver.cpp
+++ b/source/RobotAPI/components/ObjectPoseObserver/ObjectPoseObserver.cpp
@@ -762,16 +762,10 @@ namespace armarx
         return pose;
     }
 
-    objpose::ObjectPose* ObjectPoseObserver::findObjectPoseByID(objpose::ObjectPoseSeq& objectPoses, const ObjectID& id)
     {
-        for (objpose::ObjectPose& pose : objectPoses)
         {
-            if (pose.objectID == id)
             {
-                return &pose;
             }
-        }
-        return nullptr;
     }
 
     bool ObjectPoseObserver::isAttachedCached(objpose::ObjectPose& objectPose) const
@@ -787,28 +781,6 @@ namespace armarx
         return bool(objectPose.attachment);
     }
 
-    objpose::ObjectPose ObjectPoseObserver::applyAttachment(
-        const objpose::ObjectPose& objectPose, VirtualRobot::RobotPtr agent)
-    {
-        ARMARX_CHECK(objectPose.attachment);
-
-        objpose::ObjectPose updated = objectPose;
-        const objpose::ObjectAttachmentInfo& attachment = *updated.attachment;
-
-        ARMARX_CHECK_EQUAL(attachment.agentName, agent->getName());
-
-        VirtualRobot::RobotNodePtr robotNode = agent->getRobotNode(attachment.frameName);
-        ARMARX_CHECK_NOT_NULL(robotNode);
-
-        // Overwrite object pose
-        updated.objectPoseRobot = robotNode->getPoseInRootFrame() * attachment.poseInFrame;
-        updated.objectPoseGlobal = agent->getGlobalPose() * updated.objectPoseRobot;
-
-        updated.robotPose = agent->getGlobalPose();
-        updated.robotConfig = agent->getConfig()->getRobotNodeJointValueMap();
-
-        return updated;
-    }
 
 
     void ObjectPoseObserver::toIceWithAttachments(
diff --git a/source/RobotAPI/components/ObjectPoseObserver/ObjectPoseObserver.h b/source/RobotAPI/components/ObjectPoseObserver/ObjectPoseObserver.h
index 1e1573654bda3f4742076b1e3a298dea276dd2b7..ff26b59f7668ccfd66fbd51d3725ee3b8c4501b5 100644
--- a/source/RobotAPI/components/ObjectPoseObserver/ObjectPoseObserver.h
+++ b/source/RobotAPI/components/ObjectPoseObserver/ObjectPoseObserver.h
@@ -150,11 +150,9 @@ namespace armarx
 
 
         objpose::ObjectPose* findObjectPose(const std::string& providerName, ObjectID& objectID);
-        static objpose::ObjectPose* findObjectPoseByID(objpose::ObjectPoseSeq& objectPoses, const ObjectID& id);
 
 
         bool isAttachedCached(objpose::ObjectPose& objectPose) const;
-        static objpose::ObjectPose applyAttachment(const objpose::ObjectPose& objectPose, VirtualRobot::RobotPtr robot);
 
         void toIceWithAttachments(objpose::ObjectPoseSeq& objectPoses, VirtualRobot::RobotPtr agent,
                                   objpose::data::ObjectPoseSeq& result, bool& synchronized);
diff --git a/source/RobotAPI/libraries/ArmarXObjects/ObjectPose.cpp b/source/RobotAPI/libraries/ArmarXObjects/ObjectPose.cpp
index ddecbed52ac6a14640dc6546bbe8398ec286a5fc..02b04bf6f3961074891472deed1ade625850b467 100644
--- a/source/RobotAPI/libraries/ArmarXObjects/ObjectPose.cpp
+++ b/source/RobotAPI/libraries/ArmarXObjects/ObjectPose.cpp
@@ -119,6 +119,28 @@ namespace armarx::objpose
         return std::nullopt;
     }
 
+    objpose::ObjectPose ObjectPose::getAttached(VirtualRobot::RobotPtr agent)
+    {
+        ARMARX_CHECK(attachment);
+
+        objpose::ObjectPose updated = *this;
+        const objpose::ObjectAttachmentInfo& attachment = *updated.attachment;
+
+        ARMARX_CHECK_EQUAL(attachment.agentName, agent->getName());
+
+        VirtualRobot::RobotNodePtr robotNode = agent->getRobotNode(attachment.frameName);
+        ARMARX_CHECK_NOT_NULL(robotNode);
+
+        // Overwrite object pose
+        updated.objectPoseRobot = robotNode->getPoseInRootFrame() * attachment.poseInFrame;
+        updated.objectPoseGlobal = agent->getGlobalPose() * updated.objectPoseRobot;
+
+        updated.robotPose = agent->getGlobalPose();
+        updated.robotConfig = agent->getConfig()->getRobotNodeJointValueMap();
+
+        return updated;
+    }
+
 }
 
 namespace armarx
@@ -239,5 +261,31 @@ namespace armarx
         return ice;
     }
 
+
+    objpose::ObjectPose* objpose::findObjectPoseByID(ObjectPoseSeq& objectPoses, const ObjectID& id)
+    {
+        for (objpose::ObjectPose& pose : objectPoses)
+        {
+            if (pose.objectID == id)
+            {
+                return &pose;
+            }
+        }
+        return nullptr;
+    }
+
+    const objpose::ObjectPose* objpose::findObjectPoseByID(const ObjectPoseSeq& objectPoses, const ObjectID& id)
+    {
+        for (const objpose::ObjectPose& pose : objectPoses)
+        {
+            if (pose.objectID == id)
+            {
+                return &pose;
+            }
+        }
+        return nullptr;
+    }
 }
 
+
+
diff --git a/source/RobotAPI/libraries/ArmarXObjects/ObjectPose.h b/source/RobotAPI/libraries/ArmarXObjects/ObjectPose.h
index cdfd1cfdece0570cf77162549de5da7d443c0e26..4f107d549e87d1b523d032349e1c1743071df4b5 100644
--- a/source/RobotAPI/libraries/ArmarXObjects/ObjectPose.h
+++ b/source/RobotAPI/libraries/ArmarXObjects/ObjectPose.h
@@ -73,6 +73,8 @@ namespace armarx::objpose
         /// Get the OOBB in the global frame (according to `objectPoseGlobal`).
         std::optional<simox::OrientedBoxf> oobbGlobal() const;
 
+        /// Get `*this` with applied attachment.
+        objpose::ObjectPose getAttached(VirtualRobot::RobotPtr agent);
     };
     using ObjectPoseSeq = std::vector<ObjectPose>;
 
@@ -98,4 +100,17 @@ namespace armarx::objpose
     void toIce(data::ObjectPoseSeq& ice, const ObjectPoseSeq& poses);
     data::ObjectPoseSeq toIce(const ObjectPoseSeq& poses);
 
+
+    // Operations on ObjectPoseSeq
+
+    /**
+     * @brief Find an object pose by the object ID. Return nullptr if not found.
+     * @param objectPoses The object poses.
+     * @param id The object ID.
+     * @return A pointer to the (first) object pose with objectID == id, or nullptr if none is found.
+     */
+    ObjectPose* findObjectPoseByID(ObjectPoseSeq& objectPoses, const ObjectID& id);
+    const ObjectPose* findObjectPoseByID(const ObjectPoseSeq& objectPoses, const ObjectID& id);
+
+
 }