diff --git a/data/RobotAPI/VariantInfo-RobotAPI.xml b/data/RobotAPI/VariantInfo-RobotAPI.xml
index 8b869fe31552807e5b47222e396eefa9d564092f..e09c9aa52c8ab75de5ca845a812fc6fd38aa4d4e 100644
--- a/data/RobotAPI/VariantInfo-RobotAPI.xml
+++ b/data/RobotAPI/VariantInfo-RobotAPI.xml
@@ -17,6 +17,13 @@
         <Variant baseType="::armarx::TrajectoryBase" dataType="::armarx::Trajectory" humanName="Trajectory"  include="RobotAPI/libraries/core/Trajectory.h"/>
     </Lib>
     <Lib name="RobotAPIInterfaces">
+
+        <Class typeName="NJointCartesianWaypointControllerConfig" include="RobotAPI/interface/units/RobotUnit/NJointCartesianWaypointController.h"  />
+        <Class typeName="FramedPoseBase" include="RobotAPI/interface/core/FramedPoseBase.h" />
+        <Class typeName="Vector3Base" include="RobotAPI/libraries/core/Pose.h" />
+        <Class typeName="QuaternionBase" include="RobotAPI/libraries/core/Pose.h" />
+        <Class typeName="armarx::viz::data::Element" include="RobotAPI/interface/ArViz/Elements.h" />
+        <Class typeName="armarx::viz::data::LayerUpdate" include="RobotAPI/interface/ArViz/Component.h" />
         <Proxy include="RobotAPI/interface/units/KinematicUnitInterface.h"
             humanName="Kinematic Unit"
             typeName="KinematicUnitInterfacePrx"
@@ -195,6 +202,16 @@
                 propertyName="NJointTrajectoryControllerName"
                 propertyIsOptional="true"
                 propertyDefaultValue="NJointTrajectoryController" />
+        <Proxy include="RobotAPI/interface/units/RobotUnit/NJointCartesianWaypointController.h"
+                humanName="NJoint Cartesian Waypoint Controller"
+                typeName="NJointCartesianControllerInterfacePrx"
+                memberName="NJointCartesianWaypointController"
+                getterName="getNJointCartesianWaypointController"
+                propertyName="NJointCartesianWaypointControllerName"
+                propertyIsOptional="true"
+                propertyDefaultValue="NJointCartesianWaypointController" />
+ 
+
         <Proxy include="RobotAPI/interface/core/RobotState.h"
             humanName="Robot State Component"
             typeName="RobotStateComponentInterfacePrx"
@@ -264,6 +281,17 @@
             propertyIsOptional="true"
             propertyDefaultValue="ArVizTopic">
         </Topic>
+        <Proxy include="RobotAPI/interface/ArViz/Component.h"
+            humanName="ArViz Storage"
+            typeName="armarx::viz::StorageInterfacePrx"
+            memberName="storageProxy"
+            getterName="getStorageProxy"
+            propertyName="StorageName"
+            propertyIsOptional="true"
+            propertyDefaultValue="ArViz">
+        </Proxy>
+
+
         <Topic include="RobotAPI/interface/speech/SpeechInterface.h"
             humanName="Text to Speech Topic"
             typeName="TextListenerInterfacePrx"
@@ -298,7 +326,7 @@
             propertyDefaultValue="DynamicObstacleManager" />
         <Proxy include="RobotAPI/interface/observers/GraspCandidateObserverInterface.h"
             humanName="Grasp Candidate Observer"
-            typeName="grasping::GraspCandidateObserverInterfacePrx"
+            typeName="armarx::grasping::GraspCandidateObserverInterfacePrx"
             memberName="graspCandidateObserver"
             getterName="getGraspCandidateObserver"
             propertyName="GraspCandidateObserverName"
diff --git a/source/RobotAPI/components/armem/server/CMakeLists.txt b/source/RobotAPI/components/armem/server/CMakeLists.txt
index 58c3758d1ed5e56127d702137a0746ddfcd454a3..7ddc79776f7e56d2c71596f4e3c0c5656f18875f 100644
--- a/source/RobotAPI/components/armem/server/CMakeLists.txt
+++ b/source/RobotAPI/components/armem/server/CMakeLists.txt
@@ -1,6 +1,7 @@
 add_subdirectory(ExampleMemory)
 add_subdirectory(GeneralPurposeMemory)
 add_subdirectory(ObjectMemory)
+add_subdirectory(ReasoningMemory)
 add_subdirectory(RobotStateMemory)
 add_subdirectory(SkillsMemory)
 add_subdirectory(GraspMemory)
diff --git a/source/RobotAPI/components/armem/server/ReasoningMemory/CMakeLists.txt b/source/RobotAPI/components/armem/server/ReasoningMemory/CMakeLists.txt
new file mode 100644
index 0000000000000000000000000000000000000000..6d31cfd8a9646d5df26104efb45cfe855d6a6214
--- /dev/null
+++ b/source/RobotAPI/components/armem/server/ReasoningMemory/CMakeLists.txt
@@ -0,0 +1,28 @@
+armarx_component_set_name("ReasoningMemory")
+
+
+set(COMPONENT_LIBS
+    ArmarXCore ArmarXCoreInterfaces  # for DebugObserverInterface
+    ArmarXGuiComponentPlugins
+    RobotAPICore RobotAPIInterfaces armem_server
+    RobotAPIComponentPlugins  # for ArViz and other plugins
+    armem_reasoning
+    armem_reasoning_server
+)
+
+set(SOURCES
+    ReasoningMemory.cpp
+)
+set(HEADERS
+    ReasoningMemory.h
+)
+
+armarx_add_component("${SOURCES}" "${HEADERS}")
+
+#generate the application
+armarx_generate_and_add_component_executable(
+    COMPONENT_NAMESPACE ::armarx::armem::server
+)
+
+
+
diff --git a/source/RobotAPI/components/armem/server/ReasoningMemory/ReasoningMemory.cpp b/source/RobotAPI/components/armem/server/ReasoningMemory/ReasoningMemory.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..7ea316348abfa01cf08700ea362a6faa57a3afb9
--- /dev/null
+++ b/source/RobotAPI/components/armem/server/ReasoningMemory/ReasoningMemory.cpp
@@ -0,0 +1,77 @@
+/*
+ * This file is part of ArmarX.
+ *
+ * ArmarX is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * ArmarX is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * @package    RobotAPI::ArmarXObjects::ExampleMemory
+ * @author     Markus Grotz ( markus dot grotz at kit dot edu )
+ * @date       2022
+ * @copyright  http://www.gnu.org/licenses/gpl-2.0.txt
+ *             GNU General Public License
+ */
+
+#include "ReasoningMemory.h"
+
+#include <ArmarXCore/core/exceptions/local/ExpressionException.h>
+
+#include <SimoxUtility/algorithm/string.h>
+
+#include <RobotAPI/libraries/armem/server/wm/memory_definitions.h>
+#include <RobotAPI/libraries/armem/core/error.h>
+
+
+namespace armarx::armem::server
+{
+    armarx::PropertyDefinitionsPtr ReasoningMemory::createPropertyDefinitions()
+    {
+        armarx::PropertyDefinitionsPtr defs = new ComponentPropertyDefinitions(getConfigIdentifier());
+
+        setMemoryName("Reasoning");
+        return defs;
+    }
+
+
+    ReasoningMemory::ReasoningMemory() :
+        anticipationSegment(iceAdapter())
+    {
+
+    }
+
+    std::string ReasoningMemory::getDefaultName() const
+    {
+        return "ReasoningMemory";
+    }
+
+    void ReasoningMemory::onInitComponent()
+    {
+	
+	{
+        wm::CoreSegment& cs = workingMemory().addCoreSegment("Anticipation", armarx::reasoning::arondto::Anticipation::ToAronType());
+		cs.setMaxHistorySize(20);
+	}
+
+
+    }
+
+    void ReasoningMemory::onConnectComponent()
+    {
+    }
+
+    void ReasoningMemory::onDisconnectComponent()
+    {
+    }
+
+    void ReasoningMemory::onExitComponent()
+    {
+    }
+}
diff --git a/source/RobotAPI/components/armem/server/ReasoningMemory/ReasoningMemory.h b/source/RobotAPI/components/armem/server/ReasoningMemory/ReasoningMemory.h
new file mode 100644
index 0000000000000000000000000000000000000000..2ad670842bb15e1159326a977d23497af714aaa8
--- /dev/null
+++ b/source/RobotAPI/components/armem/server/ReasoningMemory/ReasoningMemory.h
@@ -0,0 +1,55 @@
+/*
+ * This file is part of ArmarX.
+ *
+ * ArmarX is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * ArmarX is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * @package    RobotAPI::ArmarXObjects::ExampleMemory
+ * @author     Markus Grotz ( markus dot grotz at kit dot edu )
+ * @date       2022
+ * @copyright  http://www.gnu.org/licenses/gpl-2.0.txt
+ *             GNU General Public License
+ */
+
+#pragma once
+
+#include <ArmarXCore/core/Component.h>
+
+#include <RobotAPI/libraries/armem/server/plugins/ReadWritePluginUser.h>
+#include <RobotAPI/libraries/armem_reasoning/server/AnticipationSegment.h>
+
+namespace armarx::armem::server
+{
+    class ReasoningMemory :
+        virtual public armarx::Component, 
+        virtual public armem::server::ReadWritePluginUser
+    {
+    public:
+        ReasoningMemory();
+
+        /// @see armarx::ManagedIceObject::getDefaultName()
+        std::string getDefaultName() const override;
+
+    protected:
+
+        armarx::PropertyDefinitionsPtr createPropertyDefinitions() override;
+
+        void onInitComponent() override;
+        void onConnectComponent() override;
+        void onDisconnectComponent() override;
+        void onExitComponent() override;
+
+
+    private:
+        reasoning::AnticipationSegment anticipationSegment;
+    };
+}
diff --git a/source/RobotAPI/components/units/RobotUnit/NJointControllers/NJointCartesianWaypointController.cpp b/source/RobotAPI/components/units/RobotUnit/NJointControllers/NJointCartesianWaypointController.cpp
index 6ad411f67b743fecaf8ed8fa82a31f0d3e0d0b8c..4658f41d72431535920580dbb6bda4e0c70c0b6e 100644
--- a/source/RobotAPI/components/units/RobotUnit/NJointControllers/NJointCartesianWaypointController.cpp
+++ b/source/RobotAPI/components/units/RobotUnit/NJointControllers/NJointCartesianWaypointController.cpp
@@ -468,4 +468,9 @@ namespace armarx
             }
         }
     }
+
+    int NJointCartesianWaypointController::getCurrentWaypointIndex(const Ice::Current&)
+    {
+        return _publishWpsCur;
+    }
 }
diff --git a/source/RobotAPI/components/units/RobotUnit/NJointControllers/NJointCartesianWaypointController.h b/source/RobotAPI/components/units/RobotUnit/NJointControllers/NJointCartesianWaypointController.h
index 9ed0b775c33ca9bc3a32c239d6635fd9d021044e..4933edd9d22e5138a7ef06d09fa15aa4f908e339 100644
--- a/source/RobotAPI/components/units/RobotUnit/NJointControllers/NJointCartesianWaypointController.h
+++ b/source/RobotAPI/components/units/RobotUnit/NJointControllers/NJointCartesianWaypointController.h
@@ -51,6 +51,7 @@ namespace armarx
     public:
         bool hasReachedTarget(const Ice::Current& = Ice::emptyCurrent) override;
         bool hasReachedForceLimit(const Ice::Current& = Ice::emptyCurrent) override;
+        int getCurrentWaypointIndex(const Ice::Current& = Ice::emptyCurrent) override;
 
         void setConfig(const NJointCartesianWaypointControllerRuntimeConfig& cfg, const Ice::Current& = Ice::emptyCurrent) override;
         void setWaypoints(const std::vector<Eigen::Matrix4f>& wps, const Ice::Current& = Ice::emptyCurrent) override;
diff --git a/source/RobotAPI/gui-plugins/SkillManagerPlugin/CMakeLists.txt b/source/RobotAPI/gui-plugins/SkillManagerPlugin/CMakeLists.txt
index 749a9e26330f60a2ffaee4ae251a65495887f771..1d427101fc58c6b36acf68979ff0a16c2f890bfc 100644
--- a/source/RobotAPI/gui-plugins/SkillManagerPlugin/CMakeLists.txt
+++ b/source/RobotAPI/gui-plugins/SkillManagerPlugin/CMakeLists.txt
@@ -37,7 +37,13 @@ set(GUI_UIS
 )
 
 # Add more libraries you depend on here, e.g. ${QT_LIBRARIES}.
-set(COMPONENT_LIBS RobotAPIInterfaces aron skills aronjsonconverter SimpleConfigDialog)
+set(COMPONENT_LIBS
+    RobotAPIInterfaces
+    aron
+    RobotAPISkills
+    aronjsonconverter
+    SimpleConfigDialog
+)
 
 if(ArmarXGui_FOUND)
     armarx_gui_plugin("${LIB_NAME}" "${SOURCES}" "" "${GUI_UIS}" "" "${COMPONENT_LIBS}")
diff --git a/source/RobotAPI/interface/units/RobotUnit/NJointCartesianWaypointController.ice b/source/RobotAPI/interface/units/RobotUnit/NJointCartesianWaypointController.ice
index 712399c5f77ec1a7c116b3e77b0ad2e4df616a87..bf00909d6f5b95ee23fec2f982aae5d4d6ed6ec8 100644
--- a/source/RobotAPI/interface/units/RobotUnit/NJointCartesianWaypointController.ice
+++ b/source/RobotAPI/interface/units/RobotUnit/NJointCartesianWaypointController.ice
@@ -51,6 +51,7 @@ module armarx
     {
         idempotent bool hasReachedTarget();
         idempotent bool hasReachedForceLimit();
+        idempotent int getCurrentWaypointIndex();
 
         void setConfig(NJointCartesianWaypointControllerRuntimeConfig cfg);
         void setWaypoints(Eigen::Matrix4fSeq wps);
diff --git a/source/RobotAPI/libraries/ArmarXObjects/CMakeLists.txt b/source/RobotAPI/libraries/ArmarXObjects/CMakeLists.txt
index 20f30486fd3249168f6f80a9353d6dd78cc7b2ea..2b2fb5f9d4ea899930351b1234873b2354cb50bf 100644
--- a/source/RobotAPI/libraries/ArmarXObjects/CMakeLists.txt
+++ b/source/RobotAPI/libraries/ArmarXObjects/CMakeLists.txt
@@ -30,6 +30,8 @@ set(LIB_FILES
     plugins/ObjectPoseProviderPlugin.cpp
     plugins/ObjectPoseClientPlugin.cpp
     plugins/RequestedObjects.cpp
+
+    util.cpp
 )
 set(LIB_HEADERS
     ArmarXObjects.h
@@ -54,6 +56,8 @@ set(LIB_HEADERS
     plugins/ObjectPoseProviderPlugin.h
     plugins/ObjectPoseClientPlugin.h
     plugins/RequestedObjects.h
+
+    util.h
 )
 
 armarx_add_library("${LIB_NAME}" "${LIB_FILES}" "${LIB_HEADERS}" "${LIBS}")
diff --git a/source/RobotAPI/libraries/ArmarXObjects/ObjectPoseClient.cpp b/source/RobotAPI/libraries/ArmarXObjects/ObjectPoseClient.cpp
index 8710af33c07522713bd833e53c7f1e982754e3ec..13de0bb80cccb9d9e7a63819907d3b7d81688fbd 100644
--- a/source/RobotAPI/libraries/ArmarXObjects/ObjectPoseClient.cpp
+++ b/source/RobotAPI/libraries/ArmarXObjects/ObjectPoseClient.cpp
@@ -1,4 +1,6 @@
 #include "ObjectPoseClient.h"
+#include <optional>
+#include "RobotAPI/libraries/ArmarXObjects/ObjectPose.h"
 
 
 namespace armarx::objpose
@@ -45,7 +47,8 @@ namespace armarx::objpose
     }
 
 
-    ObjectPoseMap ObjectPoseClient::fetchObjectPosesAsMap()
+    ObjectPoseMap
+    ObjectPoseClient::fetchObjectPosesAsMap()
     {
         ObjectPoseMap map;
         for (auto& pose : fetchObjectPoses())
@@ -54,8 +57,24 @@ namespace armarx::objpose
         }
         return map;
     }
+
     
-    ObjectPoseSeq ObjectPoseClient::fetchObjectPosesFromProvider(const std::string& providerName) 
+    std::optional<ObjectPose>
+    ObjectPoseClient::fetchObjectPose(const ObjectID& objectID)
+    {
+        const auto *object = findObjectPoseByID(fetchObjectPoses(), objectID);
+
+        if(object != nullptr)
+        {
+            return *object;
+        }
+
+        return std::nullopt;
+    }
+    
+
+    ObjectPoseSeq
+    ObjectPoseClient::fetchObjectPosesFromProvider(const std::string& providerName)
     {
         if (!objectPoseStorage)
         {
@@ -66,7 +85,6 @@ namespace armarx::objpose
     }
 
 
-
     const ObjectPoseStorageInterfacePrx&
     ObjectPoseClient::getObjectPoseStorage() const
     {
diff --git a/source/RobotAPI/libraries/ArmarXObjects/ObjectPoseClient.h b/source/RobotAPI/libraries/ArmarXObjects/ObjectPoseClient.h
index 33f9a6dd7b40fd933a451d50d093afc937a08635..a5b5fd18d7686e0cc46cd7e0154588ca3b13b40f 100644
--- a/source/RobotAPI/libraries/ArmarXObjects/ObjectPoseClient.h
+++ b/source/RobotAPI/libraries/ArmarXObjects/ObjectPoseClient.h
@@ -1,6 +1,9 @@
 #pragma once
 
+#include <optional>
+
 #include <RobotAPI/interface/objectpose/ObjectPoseStorageInterface.h>
+#include <RobotAPI/libraries/ArmarXObjects/ObjectID.h>
 #include <RobotAPI/libraries/ArmarXObjects/ObjectFinder.h>
 #include <RobotAPI/libraries/ArmarXObjects/ObjectPose.h>
 
@@ -16,28 +19,83 @@ namespace armarx::objpose
     {
     public:
 
+        /// Construct a disconnected client.
         ObjectPoseClient();
-        ObjectPoseClient(const ObjectPoseStorageInterfacePrx& objectPoseStorage,
-                         const ObjectFinder& finder = {});
-
-        void connect(const ObjectPoseStorageInterfacePrx& objectPoseStorage);
-
-        bool isConnected() const;
-
-
+        /// Construct a client and connect it to the object pose storage.
+        ObjectPoseClient(
+                const ObjectPoseStorageInterfacePrx& objectPoseStorage,
+                const ObjectFinder& finder = {}
+                );
+
+        /**
+         * @brief Connect to the given object pose storage.
+         *
+         * This function can be used after default-constructing the client.
+         *
+         * @param objectPoseStorage The object pose storage.
+         */
+        void
+        connect(const ObjectPoseStorageInterfacePrx& objectPoseStorage);
+
+        /**
+         * @brief Indicate whether this client is connected to an object pose
+         * storage.
+         *
+         * That is, whether its proxy has been set via the constructor or
+         * `connect()`.
+         *
+         * If false, all `fetch*()` functions will return empty results.
+         *
+         * @return True if connected
+         */
+        bool
+        isConnected() const;
+
+
+        /**
+         * @brief Fetch all known object poses.
+         * @return The known object poses.
+         */
         ObjectPoseSeq
         fetchObjectPoses();
 
+        /**
+         * @brief Fetch all known object poses.
+         * @return The known object poses, with object ID as key.
+         */
         ObjectPoseMap
         fetchObjectPosesAsMap();
 
+        /**
+         * @brief Fetch the pose of a single object.
+         *
+         * This is a network call. If you need multiple object poses, use
+         * `fetchObjectPoses()` instead.
+         *
+         * @param objectID The object's ID.
+         * @return The object's pose, if known.
+         */
+        std::optional<ObjectPose>
+        fetchObjectPose(const ObjectID& objectID);
+
+        /**
+         * @brief Fetch object poses from a specific provider.
+         * @param providerName The provider's name.
+         * @return The object poses from that provider.
+         */
         ObjectPoseSeq
         fetchObjectPosesFromProvider(const std::string& providerName);
 
 
+        /**
+         * @brief Get the object pose storage's proxy.
+         */
         const ObjectPoseStorageInterfacePrx&
         getObjectPoseStorage() const;
 
+        /**
+         * @brief Get the internal object finder.
+         */
         const ObjectFinder&
         getObjectFinder() const;
 
diff --git a/source/RobotAPI/libraries/ArmarXObjects/util.cpp b/source/RobotAPI/libraries/ArmarXObjects/util.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..3dd90c141d81b77fcce1e0b91f8a5963d84a2726
--- /dev/null
+++ b/source/RobotAPI/libraries/ArmarXObjects/util.cpp
@@ -0,0 +1,88 @@
+/**
+ * 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       2022
+ * @copyright  http://www.gnu.org/licenses/gpl-2.0.txt
+ *             GNU General Public License
+ */
+
+#include "util.h"
+
+#include <string>
+
+#include <Eigen/Geometry>
+
+#include <VirtualRobot/ManipulationObject.h>
+#include <VirtualRobot/SceneObjectSet.h>
+
+#include <RobotAPI/libraries/ArmarXObjects/ObjectFinder.h>
+
+namespace armarx::objpose
+{
+
+    objpose::ObjectPoseSeq
+    filterObjects(objpose::ObjectPoseSeq objects, const std::vector<std::string>& datasetBlocklist)
+    {
+        const auto isBlacklisted = [&datasetBlocklist](const objpose::ObjectPose& objectPose)
+        {
+            const auto dataset = objectPose.objectID.dataset();
+
+            return std::find(datasetBlocklist.begin(), datasetBlocklist.end(), dataset) !=
+                   datasetBlocklist.end();
+        };
+
+        objects.erase(std::remove_if(objects.begin(), objects.end(), isBlacklisted), objects.end());
+        return objects;
+    }
+
+
+    VirtualRobot::ManipulationObjectPtr
+    asManipulationObject(const objpose::ObjectPose& objectPose)
+    {
+        ObjectFinder finder;
+
+        VirtualRobot::SceneObjectSetPtr sceneObjects(new VirtualRobot::SceneObjectSet);
+        if (auto obstacle = finder.loadManipulationObject(objectPose))
+        {
+            obstacle->setGlobalPose(objectPose.objectPoseGlobal);
+            return obstacle;
+        }
+
+        ARMARX_WARNING << "Failed to load scene object `" << objectPose.objectID << "`";
+        return nullptr;
+    }
+
+
+    VirtualRobot::SceneObjectSetPtr
+    asSceneObjects(const objpose::ObjectPoseSeq& objectPoses)
+    {
+        ObjectFinder finder;
+
+        VirtualRobot::SceneObjectSetPtr sceneObjects(new VirtualRobot::SceneObjectSet);
+        for (const auto& objectPose : objectPoses)
+        {
+            if (auto obstacle = finder.loadManipulationObject(objectPose))
+            {
+                obstacle->setGlobalPose(objectPose.objectPoseGlobal);
+                sceneObjects->addSceneObject(obstacle);
+            }
+        }
+
+        return sceneObjects;
+    }
+
+
+} // namespace armarx::objpose
diff --git a/source/RobotAPI/libraries/ArmarXObjects/util.h b/source/RobotAPI/libraries/ArmarXObjects/util.h
new file mode 100644
index 0000000000000000000000000000000000000000..bd8ebf0c8397ae1a26b899a8d48c1f9a303377f9
--- /dev/null
+++ b/source/RobotAPI/libraries/ArmarXObjects/util.h
@@ -0,0 +1,36 @@
+/**
+ * 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       2022
+ * @copyright  http://www.gnu.org/licenses/gpl-2.0.txt
+ *             GNU General Public License
+ */
+
+#pragma once
+
+#include <VirtualRobot/VirtualRobot.h>
+
+#include <RobotAPI/libraries/ArmarXObjects/ObjectPose.h>
+
+namespace armarx::objpose
+{
+    objpose::ObjectPoseSeq filterObjects(objpose::ObjectPoseSeq objects,
+                                         const std::vector<std::string>& datasetBlocklist);
+
+    VirtualRobot::ManipulationObjectPtr asManipulationObject(const objpose::ObjectPose& objectPose);
+    VirtualRobot::SceneObjectSetPtr asSceneObjects(const objpose::ObjectPoseSeq& objectPoses);
+  
+} // namespace armarx::objpose
diff --git a/source/RobotAPI/libraries/CMakeLists.txt b/source/RobotAPI/libraries/CMakeLists.txt
index 86bdc8fa48e612b256365f1beb1c43bfd1d09ec2..099ad8b4b981aeed1cc9e274c25672a1014ee120 100644
--- a/source/RobotAPI/libraries/CMakeLists.txt
+++ b/source/RobotAPI/libraries/CMakeLists.txt
@@ -23,6 +23,7 @@ add_subdirectory(armem_gui)
 add_subdirectory(armem_motions)
 add_subdirectory(armem_mps)
 add_subdirectory(armem_objects)
+add_subdirectory(armem_reasoning)
 add_subdirectory(armem_robot)
 add_subdirectory(armem_robot_state)
 add_subdirectory(armem_skills)
diff --git a/source/RobotAPI/libraries/armem_reasoning/CMakeLists.txt b/source/RobotAPI/libraries/armem_reasoning/CMakeLists.txt
new file mode 100644
index 0000000000000000000000000000000000000000..9da6213e75a9c53e041ab5060537dd9122d9a1c2
--- /dev/null
+++ b/source/RobotAPI/libraries/armem_reasoning/CMakeLists.txt
@@ -0,0 +1,25 @@
+set(LIB_NAME       armem_reasoning)
+
+armarx_component_set_name("${LIB_NAME}")
+armarx_set_target("Library: ${LIB_NAME}")
+
+
+armarx_add_library(
+    LIBS
+        ArmarXCoreInterfaces ArmarXCore
+        RobotAPICore aron armem
+
+    SOURCES
+        aron_conversions.cpp
+
+    HEADERS
+        aron_conversions.h
+
+    ARON_FILES
+        aron/Anticipation.xml
+)
+
+
+add_library(RobotAPI::armem_reasoning ALIAS ${LIB_NAME})
+
+add_subdirectory(server)
diff --git a/source/RobotAPI/libraries/armem_reasoning/aron/Anticipation.xml b/source/RobotAPI/libraries/armem_reasoning/aron/Anticipation.xml
new file mode 100644
index 0000000000000000000000000000000000000000..a3f481c630d573970ace675032a13becc9ca57fe
--- /dev/null
+++ b/source/RobotAPI/libraries/armem_reasoning/aron/Anticipation.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<AronTypeDefinition>
+
+    <CodeIncludes>
+        <Include include="<RobotAPI/libraries/armem/aron/MemoryID.aron.generated.h>" />
+    </CodeIncludes>
+    <AronIncludes>
+        <Include include="<RobotAPI/libraries/armem/aron/MemoryID.xml>" autoinclude="true" />
+    </AronIncludes>
+
+    <GenerateTypes>
+        <Object name='armarx::reasoning::arondto::Anticipation'>
+             <ObjectChild key='predictions'>
+                <List optional='true'>
+                    	<string />
+                </List>
+            </ObjectChild>
+        </Object>
+    </GenerateTypes>
+</AronTypeDefinition>
diff --git a/source/RobotAPI/libraries/armem_reasoning/aron_conversions.cpp b/source/RobotAPI/libraries/armem_reasoning/aron_conversions.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..e721f12a9349747d7d2b3c6e69a4bc223e5d76ad
--- /dev/null
+++ b/source/RobotAPI/libraries/armem_reasoning/aron_conversions.cpp
@@ -0,0 +1,28 @@
+/*
+ * This file is part of ArmarX.
+ *
+ * ArmarX is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * ArmarX is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * @package    VisionX::ArmarXObjects::armem_images_server
+ * @author     Markus Grotz ( markus dot grotz at kit dot edu )
+ * @date       2022
+ * @copyright  http://www.gnu.org/licenses/gpl-2.0.txt
+ *             GNU General Public License
+ */
+
+#include "aron_conversions.h"
+
+namespace armarx::armem::server::reasoning
+{
+
+}
diff --git a/source/RobotAPI/libraries/armem_reasoning/aron_conversions.h b/source/RobotAPI/libraries/armem_reasoning/aron_conversions.h
new file mode 100644
index 0000000000000000000000000000000000000000..2e4d7c8bbd2206ed184cfe7e01c2898d81523b04
--- /dev/null
+++ b/source/RobotAPI/libraries/armem_reasoning/aron_conversions.h
@@ -0,0 +1,31 @@
+/*
+ * This file is part of ArmarX.
+ *
+ * ArmarX is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * ArmarX is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * @package    VisionX::ArmarXObjects::armem_images_server
+ * @author     Markus Grotz ( markus dot grotz at kit dot edu )
+ * @date       2022
+ * @copyright  http://www.gnu.org/licenses/gpl-2.0.txt
+ *             GNU General Public License
+ */
+
+#pragma once
+
+#include <RobotAPI/libraries/aron/core/data/variant/forward_declarations.h>
+#include <RobotAPI/libraries/armem_reasoning/aron/Anticipation.aron.generated.h>
+
+namespace armarx::armem::server::reasoning
+{
+
+}
diff --git a/source/RobotAPI/libraries/armem_reasoning/server/AnticipationSegment.cpp b/source/RobotAPI/libraries/armem_reasoning/server/AnticipationSegment.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..bf2d89bb748ccf788288bc9632acf55937877125
--- /dev/null
+++ b/source/RobotAPI/libraries/armem_reasoning/server/AnticipationSegment.cpp
@@ -0,0 +1,39 @@
+/*
+ * This file is part of ArmarX.
+ *
+ * ArmarX is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * ArmarX is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * @package    RobotAPI::ArmarXObjects::armem_images_server
+ * @author     Markus Grotz ( markus dot grotz at kit dot edu )
+ * @date       2022
+ * @copyright  http://www.gnu.org/licenses/gpl-2.0.txt
+ *             GNU General Public License
+ */
+
+#include "AnticipationSegment.h"
+
+#include <ArmarXCore/core/application/properties/PropertyDefinitionContainer.h>
+
+namespace armarx::armem::server::reasoning
+{
+    AnticipationSegment::AnticipationSegment(armem::server::MemoryToIceAdapter& iceMemory) :
+        Base(iceMemory, CORE_SEGMENT_NAME)
+    {
+
+    }
+
+    void AnticipationSegment::defineProperties(armarx::PropertyDefinitionsPtr defs, const std::string& prefix)
+    {
+        Base::defineProperties(defs, prefix);
+    }
+}
diff --git a/source/RobotAPI/libraries/armem_reasoning/server/AnticipationSegment.h b/source/RobotAPI/libraries/armem_reasoning/server/AnticipationSegment.h
new file mode 100644
index 0000000000000000000000000000000000000000..3a05c7adb5b9e7d96d51c2e07a6c18f016bc506a
--- /dev/null
+++ b/source/RobotAPI/libraries/armem_reasoning/server/AnticipationSegment.h
@@ -0,0 +1,46 @@
+/*
+ * This file is part of ArmarX.
+ *
+ * ArmarX is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * ArmarX is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * @package    VisionX::ArmarXObjects::armem_images_server
+ * @author     Markus Grotz ( markus dot grotz at kit dot edu )
+ * @date       2022
+ * @copyright  http://www.gnu.org/licenses/gpl-2.0.txt
+ *             GNU General Public License
+ */
+
+#pragma once
+
+#include <mutex>
+#include <string>
+
+#include <RobotAPI/libraries/armem/server/segment/SpecializedSegment.h>
+
+#include <RobotAPI/libraries/armem_reasoning/aron/Anticipation.aron.generated.h>
+
+namespace armarx::armem::server::reasoning
+{
+    class AnticipationSegment : public armem::server::segment::SpecializedCoreSegment
+    {
+    public:
+        using Base = armem::server::segment::SpecializedCoreSegment;
+
+        AnticipationSegment(armem::server::MemoryToIceAdapter& iceMemory);
+
+        virtual void defineProperties(armarx::PropertyDefinitionsPtr defs, const std::string& prefix = "") override;
+
+    public:
+        const std::string CORE_SEGMENT_NAME = "Anticipation";
+    };
+}
diff --git a/source/RobotAPI/libraries/armem_reasoning/server/CMakeLists.txt b/source/RobotAPI/libraries/armem_reasoning/server/CMakeLists.txt
new file mode 100644
index 0000000000000000000000000000000000000000..21b041702717541f4def5b8b65705c4dd6463185
--- /dev/null
+++ b/source/RobotAPI/libraries/armem_reasoning/server/CMakeLists.txt
@@ -0,0 +1,22 @@
+set(ARMARX_LIB_NAME "" )
+set(ARON_FILES "")
+
+set(LIB_NAME       armem_reasoning_server)
+
+armarx_component_set_name("${LIB_NAME}")
+armarx_set_target("Library: ${LIB_NAME}")
+
+armarx_add_library(
+    LIBS
+        armem_reasoning
+        armem_server
+
+    SOURCES
+	AnticipationSegment.cpp
+
+    HEADERS
+	AnticipationSegment.h
+)
+
+
+add_library(RobotAPI::armem_reasoning_server ALIAS ${LIB_NAME})
diff --git a/source/RobotAPI/libraries/core/CartesianPositionController.cpp b/source/RobotAPI/libraries/core/CartesianPositionController.cpp
index 9681636da9a820a53711ed50f327205216a0fcc8..c34d94957311c775b378bcda7e0dda17f38fe1c3 100644
--- a/source/RobotAPI/libraries/core/CartesianPositionController.cpp
+++ b/source/RobotAPI/libraries/core/CartesianPositionController.cpp
@@ -24,6 +24,7 @@
 #include "CartesianPositionController.h"
 
 #include <RobotAPI/libraries/core/math/MathUtils.h>
+#include <ArmarXCore/util/CPPUtility/trace.h>
 
 namespace armarx
 {
@@ -35,12 +36,14 @@ namespace armarx
 
     Eigen::VectorXf CartesianPositionController::calculate(const Eigen::Matrix4f& targetPose, VirtualRobot::IKSolver::CartesianSelection mode) const
     {
+        ARMARX_TRACE;
         int posLen = mode & VirtualRobot::IKSolver::Position ? 3 : 0;
         int oriLen = mode & VirtualRobot::IKSolver::Orientation ? 3 : 0;
         Eigen::VectorXf cartesianVel(posLen + oriLen);
 
         if (posLen)
         {
+            ARMARX_TRACE;
             Eigen::Vector3f targetPos = targetPose.block<3, 1>(0, 3);
             Eigen::Vector3f currentPos = tcp->getPositionInFrame(referenceFrame);
             Eigen::Vector3f errPos = targetPos - currentPos;
@@ -54,6 +57,7 @@ namespace armarx
 
         if (oriLen)
         {
+            ARMARX_TRACE;
             Eigen::Matrix3f targetOri = targetPose.block<3, 3>(0, 0);
             Eigen::Matrix3f tcpOri = tcp->getPoseInFrame(referenceFrame).block<3, 3>(0, 0);
             Eigen::Matrix3f oriDir = targetOri * tcpOri.inverse();
@@ -72,12 +76,14 @@ namespace armarx
 
     Eigen::VectorXf CartesianPositionController::calculatePos(const Eigen::Vector3f& targetPos) const
     {
+        ARMARX_TRACE;
         Eigen::VectorXf cartesianVel(3);
         Eigen::Vector3f currentPos = tcp->getPositionInFrame(referenceFrame);
         Eigen::Vector3f errPos = targetPos - currentPos;
         Eigen::Vector3f posVel =  errPos * KpPos;
         if (maxPosVel > 0)
         {
+            ARMARX_TRACE;
             posVel = math::MathUtils::LimitTo(posVel, maxPosVel);
         }
         cartesianVel.block<3, 1>(0, 0) = posVel;
@@ -98,6 +104,7 @@ namespace armarx
             const VirtualRobot::RobotNodePtr& tcp,
             const VirtualRobot::RobotNodePtr& referenceFrame)
     {
+        ARMARX_TRACE;
         Eigen::Vector3f targetPos = targetPose.block<3, 1>(0, 3);
         Eigen::Vector3f tcpPos = referenceFrame ? tcp->getPositionInFrame(referenceFrame) : tcp->getPositionInRootFrame();
         Eigen::Vector3f errPos = targetPos - tcpPos;
@@ -108,6 +115,7 @@ namespace armarx
             const VirtualRobot::RobotNodePtr& tcp,
             const VirtualRobot::RobotNodePtr& referenceFrame)
     {
+        ARMARX_TRACE;
         Eigen::Matrix3f targetOri = targetPose.block<3, 3>(0, 0);
         Eigen::Matrix4f tcpPose = referenceFrame ? tcp->getPoseInFrame(referenceFrame) : tcp->getPoseInRootFrame();
         Eigen::Matrix3f tcpOri = tcpPose.block<3, 3>(0, 0);
@@ -129,6 +137,7 @@ namespace armarx
 
     bool CartesianPositionController::reached(const Eigen::Matrix4f& targetPose, VirtualRobot::IKSolver::CartesianSelection mode, float thresholdPosReached, float thresholdOriReached)
     {
+        ARMARX_TRACE;
         if (mode & VirtualRobot::IKSolver::Position)
         {
             if (GetPositionError(targetPose, tcp, referenceFrame) > thresholdPosReached)
@@ -148,6 +157,7 @@ namespace armarx
 
     Eigen::Vector3f CartesianPositionController::getPositionDiff(const Eigen::Matrix4f& targetPose) const
     {
+        ARMARX_TRACE;
         Eigen::Vector3f targetPos = targetPose.block<3, 1>(0, 3);
         return targetPos - tcp->getPositionInFrame(referenceFrame);
     }
@@ -159,6 +169,7 @@ namespace armarx
 
     Eigen::Vector3f CartesianPositionController::getOrientationDiff(const Eigen::Matrix4f& targetPose) const
     {
+        ARMARX_TRACE;
         Eigen::Matrix3f targetOri = targetPose.block<3, 3>(0, 0);
         Eigen::Matrix3f tcpOri = tcp->getPoseInFrame(referenceFrame).block<3, 3>(0, 0);
         Eigen::Matrix3f oriDir = targetOri * tcpOri.inverse();
diff --git a/source/RobotAPI/libraries/core/CartesianVelocityController.cpp b/source/RobotAPI/libraries/core/CartesianVelocityController.cpp
index 9527835a6dd48107f5e11846ec882d30b056c54a..f7a7307bfb316db667d23ff59713d80551cd1e63 100644
--- a/source/RobotAPI/libraries/core/CartesianVelocityController.cpp
+++ b/source/RobotAPI/libraries/core/CartesianVelocityController.cpp
@@ -48,6 +48,7 @@ CartesianVelocityController::CartesianVelocityController(const VirtualRobot::Rob
 
 void CartesianVelocityController::calculateJacobis(VirtualRobot::IKSolver::CartesianSelection mode)
 {
+    ARMARX_TRACE;
     jacobi = ik->getJacobianMatrix(_tcp, mode);
     _jacobiWithCosts = Eigen::MatrixXf(jacobi.rows(), jacobi.cols());
     for (int r = 0; r < jacobi.rows(); r++)
@@ -98,7 +99,7 @@ Eigen::VectorXf CartesianVelocityController::calculate(const Eigen::VectorXf& ca
 
 Eigen::VectorXf CartesianVelocityController::calculate(const Eigen::VectorXf& cartesianVel, const Eigen::VectorXf& nullspaceVel, VirtualRobot::IKSolver::CartesianSelection mode)
 {
-
+    ARMARX_TRACE;
     calculateJacobis(mode);
 
 
@@ -106,6 +107,7 @@ Eigen::VectorXf CartesianVelocityController::calculate(const Eigen::VectorXf& ca
 
     if (nullspaceVel.rows() > 0)
     {
+        ARMARX_TRACE;
         //    ARMARX_IMPORTANT << "nullspaceVel " << nullspaceVel.transpose();
         Eigen::FullPivLU<Eigen::MatrixXf> lu_decomp(_jacobiWithCosts);
         //ARMARX_IMPORTANT << "The rank of the _jacobiWithCosts is " << lu_decomp.rank();
diff --git a/source/RobotAPI/libraries/core/CartesianVelocityControllerWithRamp.cpp b/source/RobotAPI/libraries/core/CartesianVelocityControllerWithRamp.cpp
index a72fe97e50b3249595840b6fe18e1aca8be36542..ee06ab837f18e01764757e98e9aa372fc63e785f 100644
--- a/source/RobotAPI/libraries/core/CartesianVelocityControllerWithRamp.cpp
+++ b/source/RobotAPI/libraries/core/CartesianVelocityControllerWithRamp.cpp
@@ -77,6 +77,7 @@ namespace armarx
 
     Eigen::VectorXf CartesianVelocityControllerWithRamp::calculate(const Eigen::VectorXf& cartesianVel, const Eigen::VectorXf& nullspaceVel, float dt)
     {
+        ARMARX_TRACE;
         return controller.calculate(cartesianVelocityRamp.update(cartesianVel, dt), nullSpaceVelocityRamp.update(nullspaceVel, dt), mode);
     }
 
diff --git a/source/RobotAPI/libraries/core/CartesianWaypointController.cpp b/source/RobotAPI/libraries/core/CartesianWaypointController.cpp
index fe9477986cee0a9d9a9a55b3f94d40206c010e3e..917877b7a5ce1556ece46a9d8353b274dba87465 100644
--- a/source/RobotAPI/libraries/core/CartesianWaypointController.cpp
+++ b/source/RobotAPI/libraries/core/CartesianWaypointController.cpp
@@ -32,6 +32,7 @@
 #include <VirtualRobot/math/Helpers.h>
 #include <VirtualRobot/MathTools.h>
 #include <cfloat>
+#include <ArmarXCore/util/CPPUtility/trace.h>
 
 namespace armarx
 {
@@ -64,21 +65,25 @@ namespace armarx
 
     const Eigen::VectorXf& CartesianWaypointController::calculate(float dt)
     {
+        ARMARX_TRACE;
         //calculate cartesian velocity + some management stuff
         if (!isLastWaypoint() && isCurrentTargetNear())
         {
+            ARMARX_TRACE;
             currentWaypointIndex++;
         }
         cartesianVelocity = ctrlCartesianPos2Vel.calculate(getCurrentTarget(), VirtualRobot::IKSolver::All) + feedForwardVelocity;
 
         if (autoClearFeedForward)
         {
+            ARMARX_TRACE;
             clearFeedForwardVelocity();
         }
 
         //calculate joint velocity
         if (nullSpaceControlEnabled)
         {
+            ARMARX_TRACE;
             //avoid joint limits
             _jnv = KpJointLimitAvoidance * ctrlCartesianVelWithRamps.controller.calculateJointLimitAvoidance() +
                    ctrlCartesianVelWithRamps.controller.calculateNullspaceVelocity(
@@ -89,9 +94,11 @@ namespace armarx
         }
         else
         {
+            ARMARX_TRACE;
             //don't avoid joint limits
             _jnv *= 0;
         }
+        ARMARX_TRACE;
         _out = ctrlCartesianVelWithRamps.calculate(cartesianVelocity, _jnv, dt);
         return _out;
     }
@@ -178,11 +185,13 @@ namespace armarx
 
     const Eigen::Vector3f CartesianWaypointController::getCurrentTargetPosition() const
     {
+        ARMARX_TRACE;
         return ::math::Helpers::GetPosition(waypoints.at(currentWaypointIndex));
     }
 
     size_t CartesianWaypointController::skipToClosestWaypoint(float rad2mmFactor)
     {
+        ARMARX_TRACE;
         float dist = FLT_MAX;
         size_t minIndex = 0;
         for (size_t i = 0; i < waypoints.size(); i++)
diff --git a/source/RobotAPI/libraries/skills/CMakeLists.txt b/source/RobotAPI/libraries/skills/CMakeLists.txt
index 9bcf00c4be232b9a20431287fd04495666d6fd6b..bbf9d1d35d12fff2ceb8b51361e09573986c94a3 100644
--- a/source/RobotAPI/libraries/skills/CMakeLists.txt
+++ b/source/RobotAPI/libraries/skills/CMakeLists.txt
@@ -15,7 +15,9 @@ armarx_add_library(
         ./manager/SkillManagerComponentPlugin.cpp
         ./provider/SkillProviderComponentPlugin.cpp
         ./provider/Skill.cpp
+        ./provider/PeriodicSkill.cpp
         ./provider/SpecializedSkill.cpp
+        ./provider/PeriodicSpecializedSkill.cpp
         ./provider/SkillDescription.cpp
         ./provider/SkillStatusUpdate.cpp
         ./provider/SkillParameterization.cpp
@@ -25,7 +27,9 @@ armarx_add_library(
         ./manager/SkillManagerComponentPlugin.h
         ./provider/SkillProviderComponentPlugin.h
         ./provider/Skill.h
+        ./provider/PeriodicSkill.h
         ./provider/SpecializedSkill.h
+        ./provider/PeriodicSpecializedSkill.h
         ./provider/SkillDescription.h
         ./provider/SkillStatusUpdate.h
         ./provider/SkillParameterization.h
diff --git a/source/RobotAPI/libraries/skills/provider/PeriodicSkill.cpp b/source/RobotAPI/libraries/skills/provider/PeriodicSkill.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..6175015154ea95ecd2229a0b81d16a0035b61265
--- /dev/null
+++ b/source/RobotAPI/libraries/skills/provider/PeriodicSkill.cpp
@@ -0,0 +1,90 @@
+/**
+ * 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       2022
+ * @copyright  http://www.gnu.org/licenses/gpl-2.0.txt
+ *             GNU General Public License
+ */
+
+#include "PeriodicSkill.h"
+
+#include "ArmarXCore/core/exceptions/LocalException.h"
+#include "ArmarXCore/core/logging/Logging.h"
+#include "ArmarXCore/core/time/Frequency.h"
+#include <ArmarXCore/core/time/Metronome.h>
+
+#include "RobotAPI/libraries/skills/provider/Skill.h"
+
+namespace armarx::skills
+{
+    PeriodicSkill::PeriodicSkill(const SkillDescription& skillDescription,
+                                 const armarx::Frequency& frequency) :
+        Skill(skillDescription), frequency(frequency)
+    {
+    }
+
+    Skill::Status
+    PeriodicSkill::execute(const aron::data::DictPtr& params, const CallbackT& callback)
+    {
+        if(not initialize(params))
+        {
+            onFailed();
+            return Skill::Status::Failed;
+        }
+
+        core::time::Metronome metronome(frequency);
+
+        while (not stopped and not timeoutReached)
+        {
+            const auto status = executeOnce(params);
+            switch (status)
+            {
+                case Status::Running:
+                    // nothing to do here
+                    break;
+                case Status::Succeeded:
+                    onSucceeded();
+                    return Skill::Status::Succeeded;
+                case Status::Failed:
+                    onFailed();
+                    return Skill::Status::Failed;
+            }
+
+            const auto sleepDuration = metronome.waitForNextTick();
+            if (not sleepDuration.isPositive())
+            {
+                ARMARX_INFO << deactivateSpam() << "PeriodicSkill: execution took too long ("
+                            << -sleepDuration << " vs " << frequency.toCycleDuration() << ")";
+            }
+        }
+
+        if (stopped)
+        {
+            onStopped();
+            return Skill::Status::Stopped;
+        }
+
+        if (timeoutReached)
+        {
+            onTimeoutReached();
+            return Skill::Status::TimeoutReached;
+        }
+
+        throw armarx::LocalException("should not happen.");
+    }
+
+
+} // namespace armarx::skills
diff --git a/source/RobotAPI/libraries/skills/provider/PeriodicSkill.h b/source/RobotAPI/libraries/skills/provider/PeriodicSkill.h
new file mode 100644
index 0000000000000000000000000000000000000000..8c8f6c81c4d5c1e1718f330803af6d30c61dea7c
--- /dev/null
+++ b/source/RobotAPI/libraries/skills/provider/PeriodicSkill.h
@@ -0,0 +1,62 @@
+/**
+ * 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       2022
+ * @copyright  http://www.gnu.org/licenses/gpl-2.0.txt
+ *             GNU General Public License
+ */
+
+#pragma once
+
+#include <ArmarXCore/core/time/Frequency.h>
+
+#include "Skill.h"
+#include "SpecializedSkill.h"
+
+namespace armarx::skills
+{
+
+    class PeriodicSkill : virtual public Skill
+    {
+    public:
+        PeriodicSkill(const SkillDescription& skillDescription, const armarx::Frequency& frequency);
+
+    protected:
+        typename Skill::Status execute(const aron::data::DictPtr& params,
+                                        const Skill::CallbackT& callback) final;
+
+        enum class Status
+        {
+            Running,
+            Failed,
+            Succeeded
+        };
+
+        virtual bool initialize(const aron::data::DictPtr& params) = 0;
+        virtual Status executeOnce(const aron::data::DictPtr& params) = 0;
+
+        virtual void onSucceeded() = 0;
+        virtual void onStopped() = 0;
+        virtual void onFailed() = 0;
+        virtual void onTimeoutReached() = 0;
+
+    private:
+        const armarx::Frequency frequency;
+    };
+
+
+  
+} // namespace armarx::skills
diff --git a/source/RobotAPI/libraries/skills/provider/PeriodicSpecializedSkill.cpp b/source/RobotAPI/libraries/skills/provider/PeriodicSpecializedSkill.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..4c70437ab37e8fd79fcff3cc373d5b349e1cf9f5
--- /dev/null
+++ b/source/RobotAPI/libraries/skills/provider/PeriodicSpecializedSkill.cpp
@@ -0,0 +1,28 @@
+/**
+ * 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       2022
+ * @copyright  http://www.gnu.org/licenses/gpl-2.0.txt
+ *             GNU General Public License
+ */
+ 
+ #include "PeriodicSpecializedSkill.h"
+ 
+ namespace armarx::skills
+ {
+ 
+ 
+ } // namespace armarx::skills
diff --git a/source/RobotAPI/libraries/skills/provider/PeriodicSpecializedSkill.h b/source/RobotAPI/libraries/skills/provider/PeriodicSpecializedSkill.h
new file mode 100644
index 0000000000000000000000000000000000000000..b40179c2ae363eff5e0e54d5968c1b39c97cd375
--- /dev/null
+++ b/source/RobotAPI/libraries/skills/provider/PeriodicSpecializedSkill.h
@@ -0,0 +1,116 @@
+/**
+ * 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       2022
+ * @copyright  http://www.gnu.org/licenses/gpl-2.0.txt
+ *             GNU General Public License
+ */
+
+#pragma once
+
+#include <ArmarXCore/core/time/Frequency.h>
+#include <ArmarXCore/core/time/Metronome.h>
+
+#include "Skill.h"
+#include "SpecializedSkill.h"
+
+namespace armarx::skills
+{
+    template <class AronT>
+    class PeriodicSpecializedSkill : public SpecializedSkill<AronT>
+    {
+    public:
+        using Base = SpecializedSkill<AronT>;
+
+        PeriodicSpecializedSkill() = delete;
+
+        PeriodicSpecializedSkill(const SkillDescription& skillDescription,
+                                 const armarx::Frequency& frequency) :
+            Base(skillDescription), frequency(frequency)
+        {
+        }
+
+    protected:
+        typename Skill::Status
+        _execute(const AronT& params, const Skill::CallbackT& callback) final
+        {
+            if (not initialize(params))
+            {
+                onFailed();
+                return Skill::Status::Failed;
+            }
+
+            core::time::Metronome metronome(frequency);
+
+            while (not Skill::stopped and not Skill::timeoutReached)
+            {
+                const auto status = executeOnce(params);
+                switch (status)
+                {
+                    case Status::Running:
+                        // nothing to do here
+                        break;
+                    case Status::Succeeded:
+                        onSucceeded();
+                        return Skill::Status::Succeeded;
+                    case Status::Failed:
+                        onFailed();
+                        return Skill::Status::Failed;
+                }
+
+                const auto sleepDuration = metronome.waitForNextTick();
+                if (not sleepDuration.isPositive())
+                {
+                    ARMARX_INFO << deactivateSpam() << "PeriodicSkill: execution took too long ("
+                                << -sleepDuration << " vs " << frequency.toCycleDuration() << ")";
+                }
+            }
+
+            if (Skill::stopped)
+            {
+                onStopped();
+                return Skill::Status::Stopped;
+            }
+
+            if (Skill::timeoutReached)
+            {
+                onTimeoutReached();
+                return Skill::Status::TimeoutReached;
+            }
+
+            throw armarx::LocalException("should not happen.");
+        }
+
+        enum class Status
+        {
+            Running,
+            Failed,
+            Succeeded
+        };
+
+        virtual bool initialize(const AronT& params) = 0;
+        virtual Status executeOnce(const AronT& params) = 0;
+
+        virtual void onSucceeded() = 0;
+        virtual void onStopped() = 0;
+        virtual void onFailed() = 0;
+        virtual void onTimeoutReached() = 0;
+
+    private:
+        const armarx::Frequency frequency;
+    };
+
+} // namespace armarx::skills
diff --git a/source/RobotAPI/libraries/skills/provider/SpecializedSkill.h b/source/RobotAPI/libraries/skills/provider/SpecializedSkill.h
index 19bc9dc5c7d4a7f73604e4022fd0ce9a4d5b6aa0..68711db013a4a463af03429befcee867d924cbdd 100644
--- a/source/RobotAPI/libraries/skills/provider/SpecializedSkill.h
+++ b/source/RobotAPI/libraries/skills/provider/SpecializedSkill.h
@@ -15,6 +15,8 @@ namespace armarx
         class SpecializedSkill : public Skill
         {
         public:
+            using ParamType = AronT;
+
             using Skill::Skill;
             virtual ~SpecializedSkill() = default;