diff --git a/source/armarx/control/CMakeLists.txt b/source/armarx/control/CMakeLists.txt
index 0d3500e9d8af19f8e460ad43186d374dcf4547d2..b6c7c54705e00ae685bedd82df947d5c7622a615 100644
--- a/source/armarx/control/CMakeLists.txt
+++ b/source/armarx/control/CMakeLists.txt
@@ -25,3 +25,5 @@ add_subdirectory(ui)
 
 # Components
 add_subdirectory(components)
+
+add_subdirectory(retrieve_hand)
\ No newline at end of file
diff --git a/source/armarx/control/components/CMakeLists.txt b/source/armarx/control/components/CMakeLists.txt
index 495560d4bff62d77101514636ce5a8d9be57f81d..45667854a85723795ab6e3635b9cc89cee4561ac 100644
--- a/source/armarx/control/components/CMakeLists.txt
+++ b/source/armarx/control/components/CMakeLists.txt
@@ -3,4 +3,5 @@ add_subdirectory(control_memory)
 add_subdirectory(example_component_plugin_user)
 
 add_subdirectory(controller_creator)
-add_subdirectory(control_skill_provider)
\ No newline at end of file
+add_subdirectory(control_skill_provider)
+add_subdirectory(retrieve_hand_skill_provider)
\ No newline at end of file
diff --git a/source/armarx/control/components/retrieve_hand_skill_provider/CMakeLists.txt b/source/armarx/control/components/retrieve_hand_skill_provider/CMakeLists.txt
new file mode 100644
index 0000000000000000000000000000000000000000..b1057e36ced1783f253271fcf964ec66796a9cb3
--- /dev/null
+++ b/source/armarx/control/components/retrieve_hand_skill_provider/CMakeLists.txt
@@ -0,0 +1,39 @@
+armarx_add_component(retrieve_hand_skill_provider
+    ICE_FILES
+        ComponentInterface.ice
+
+    ICE_DEPENDENCIES
+        ArmarXCoreInterfaces
+        RobotAPIInterfaces
+
+    # ARON_FILES
+        # aron/my_type.xml
+
+    SOURCES
+        Component.cpp
+
+    HEADERS
+        Component.h
+
+    DEPENDENCIES
+        # ArmarXCore
+        ArmarXCore
+        ## ArmarXCoreComponentPlugins  # For DebugObserver plugin.
+        # ArmarXGui
+        ## ArmarXGuiComponentPlugins  # For RemoteGui plugin.
+        # RobotAPI
+        ## RobotAPICore
+        ## RobotAPIInterfaces
+        ## RobotAPIComponentPlugins  # For ArViz and other plugins.
+        RobotAPISkills
+
+        # armarx_control
+        armarx_control::retrieve_hand
+
+    # DEPENDENCIES_LEGACY
+        ## Add libraries that do not provide any targets but ${FOO_*} variables.
+        # FOO
+
+    # If you need a separate shared component library you can enable it with the following flag.
+    # SHARED_COMPONENT_LIBRARY
+)
diff --git a/source/armarx/control/components/retrieve_hand_skill_provider/Component.cpp b/source/armarx/control/components/retrieve_hand_skill_provider/Component.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..1e39204a6c27d0c7c06b71ce58566a38222d8e0d
--- /dev/null
+++ b/source/armarx/control/components/retrieve_hand_skill_provider/Component.cpp
@@ -0,0 +1,249 @@
+/**
+ * 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    control::ArmarXObjects::retrieve_hand_skill_provider
+ * @author     Jianfeng Gao ( jianfeng dot gao at kit dot edu )
+ * @date       2023
+ * @copyright  http://www.gnu.org/licenses/gpl-2.0.txt
+ *             GNU General Public License
+ */
+
+
+#include "Component.h"
+
+// Include headers you only need in function definitions in the .cpp.
+
+// #include <Eigen/Core>
+
+// #include <SimoxUtility/color/Color.h>
+
+#include <ArmarXCore/libraries/DecoupledSingleComponent/Decoupled.h>
+
+#include <armarx/control/retrieve_hand/skills/RetrieveHand.h>
+
+
+namespace armarx::control::components::retrieve_hand_skill_provider
+{
+
+    const std::string
+    Component::defaultName = "retrieve_hand_skill_provider";
+
+
+    ::armarx::PropertyDefinitionsPtr
+    Component::createPropertyDefinitions()
+    {
+        ::armarx::PropertyDefinitionsPtr def = new ::armarx::ComponentPropertyDefinitions(getConfigIdentifier());
+
+        def->component(remote.robotUnit, "Armar7Unit");
+        def->optional(properties.retrieveHandSkillProviderName, "retrieveHandSkillProvider");
+        // Publish to a topic (passing the TopicListenerPrx).
+        // def->topic(myTopicListener);
+
+        // Subscribe to a topic (passing the topic name).
+        // def->topic<PlatformUnitListener>("MyTopic");
+
+        // Use (and depend on) another component (passing the ComponentInterfacePrx).
+        // def->component(myComponentProxy)
+
+
+        // Add a required property. (The component won't start without a value being set.)
+        // def->required(properties.boxLayerName, "p.box.LayerName", "Name of the box layer in ArViz.");
+
+        // Add an optional property.
+        // def->optional(properties.boxLayerName, "p.box.LayerName", "Name of the box layer in ArViz.");
+        // def->optional(properties.numBoxes, "p.box.Number", "Number of boxes to draw in ArViz.");
+
+        return def;
+    }
+
+
+    void
+    Component::onInitComponent()
+    {
+        // Topics and properties defined above are automagically registered.
+
+        // Keep debug observer data until calling `sendDebugObserverBatch()`.
+        // (Requires the armarx::DebugObserverComponentPluginUser.)
+        // setDebugObserverBatchModeEnabled(true);
+    }
+
+
+    void
+    Component::onConnectComponent()
+    {
+        // Do things after connecting to topics and components.
+
+        namespace rh = ::armarx::control::retrieve_hand::skills;
+
+
+        rh::skills::RetrieveHand::Remote r;
+
+        // r.arviz = this->arviz;
+        r.robotUnit = remote.robotUnit;
+        r.memoryNameSystem = memoryNameSystem();
+
+        // rh::skills::RetrieveHand::Properties p;
+        // p.robotName =
+        // = properties.retrieveHandSkillProviderName;
+        // p.viewSelectionSkillProviderName = properties.viewSelectionSkillProviderName;
+
+        // addSkillFactory<ho::skills::HandOverObjectToHuman>(r, p);
+
+        // Option 1: Simply add a new instance of the skill.
+        addSkillFactory<skills::RetrieveHand>(r);
+        /* Option 2: Initialize skill after creation, e.g. set parameters, pass remote proxies.
+        {
+            skills::RetrieveHand* skill = addSkill<skills::RetrieveHand>();
+            skill->connectTo(...);
+        }
+        */
+
+        /* (Requires the armarx::DebugObserverComponentPluginUser.)
+        // Use the debug observer to log data over time.
+        // The data can be viewed in the ObserverView and the LivePlotter.
+        // (Before starting any threads, we don't need to lock mutexes.)
+        {
+            setDebugObserverDatafield("numBoxes", properties.numBoxes);
+            setDebugObserverDatafield("boxLayerName", properties.boxLayerName);
+            sendDebugObserverBatch();
+        }
+        */
+
+        /* (Requires the armarx::ArVizComponentPluginUser.)
+        // Draw boxes in ArViz.
+        // (Before starting any threads, we don't need to lock mutexes.)
+        drawBoxes(properties, arviz);
+        */
+
+        /* (Requires the armarx::LightweightRemoteGuiComponentPluginUser.)
+        // Setup the remote GUI.
+        {
+            createRemoteGuiTab();
+            RemoteGui_startRunningTask();
+        }
+        */
+    }
+
+
+    void
+    Component::onDisconnectComponent()
+    {
+    }
+
+
+    void
+    Component::onExitComponent()
+    {
+    }
+
+
+    std::string
+    Component::getDefaultName() const
+    {
+        return Component::defaultName;
+    }
+
+
+    std::string
+    Component::GetDefaultName()
+    {
+        return Component::defaultName;
+    }
+
+
+    /* (Requires the armarx::LightweightRemoteGuiComponentPluginUser.)
+    void
+    Component::createRemoteGuiTab()
+    {
+        using namespace armarx::RemoteGui::Client;
+
+        // Setup the widgets.
+
+        tab.boxLayerName.setValue(properties.boxLayerName);
+
+        tab.numBoxes.setValue(properties.numBoxes);
+        tab.numBoxes.setRange(0, 100);
+
+        tab.drawBoxes.setLabel("Draw Boxes");
+
+        // Setup the layout.
+
+        GridLayout grid;
+        int row = 0;
+        {
+            grid.add(Label("Box Layer"), {row, 0}).add(tab.boxLayerName, {row, 1});
+            ++row;
+
+            grid.add(Label("Num Boxes"), {row, 0}).add(tab.numBoxes, {row, 1});
+            ++row;
+
+            grid.add(tab.drawBoxes, {row, 0}, {2, 1});
+            ++row;
+        }
+
+        VBoxLayout root = {grid, VSpacer()};
+        RemoteGui_createTab(getName(), root, &tab);
+    }
+
+
+    void
+    Component::RemoteGui_update()
+    {
+        if (tab.boxLayerName.hasValueChanged() || tab.numBoxes.hasValueChanged())
+        {
+            std::scoped_lock lock(propertiesMutex);
+            properties.boxLayerName = tab.boxLayerName.getValue();
+            properties.numBoxes = tab.numBoxes.getValue();
+
+            {
+                setDebugObserverDatafield("numBoxes", properties.numBoxes);
+                setDebugObserverDatafield("boxLayerName", properties.boxLayerName);
+                sendDebugObserverBatch();
+            }
+        }
+        if (tab.drawBoxes.wasClicked())
+        {
+            // Lock shared variables in methods running in separate threads
+            // and pass them to functions. This way, the called functions do
+            // not need to think about locking.
+            std::scoped_lock lock(propertiesMutex);
+            drawBoxes(properties, arviz);
+        }
+    }
+    */
+
+
+    /* (Requires the armarx::ArVizComponentPluginUser.)
+    void
+    Component::drawBoxes(const Component::Properties& p, viz::Client& arviz)
+    {
+        // Draw something in ArViz (requires the armarx::ArVizComponentPluginUser.
+        // See the ArVizExample in RobotAPI for more examples.
+
+        viz::Layer layer = arviz.layer(p.boxLayerName);
+        for (int i = 0; i < p.numBoxes; ++i)
+        {
+            layer.add(viz::Box("box_" + std::to_string(i))
+                      .position(Eigen::Vector3f(i * 100, 0, 0))
+                      .size(20).color(simox::Color::blue()));
+        }
+        arviz.commit(layer);
+    }
+    */
+
+
+    ARMARX_REGISTER_COMPONENT_EXECUTABLE(Component, Component::GetDefaultName());
+
+}  // namespace armarx::control::components::retrieve_hand_skill_provider
diff --git a/source/armarx/control/components/retrieve_hand_skill_provider/Component.h b/source/armarx/control/components/retrieve_hand_skill_provider/Component.h
new file mode 100644
index 0000000000000000000000000000000000000000..79c988c52155eb0c8e50f5487ea04836ed17f9b6
--- /dev/null
+++ b/source/armarx/control/components/retrieve_hand_skill_provider/Component.h
@@ -0,0 +1,149 @@
+/**
+ * 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    control::ArmarXObjects::retrieve_hand
+ * @author     Jianfeng Gao ( jianfeng dot gao at kit dot edu )
+ * @date       2023
+ * @copyright  http://www.gnu.org/licenses/gpl-2.0.txt
+ *             GNU General Public License
+ */
+
+
+#pragma once
+
+
+// #include <mutex>
+
+#include <ArmarXCore/core/Component.h>
+
+// #include <ArmarXCore/libraries/ArmarXCoreComponentPlugins/DebugObserverComponentPlugin.h>
+
+// #include <ArmarXGui/libraries/ArmarXGuiComponentPlugins/LightweightRemoteGuiComponentPlugin.h>
+
+// #include <RobotAPI/libraries/RobotAPIComponentPlugins/ArVizComponentPlugin.h>
+#include <RobotAPI/libraries/armem/client/plugins/PluginUser.h>
+#include <RobotAPI/libraries/skills/provider/SkillProviderComponentPlugin.h>
+
+#include <armarx/control/components/retrieve_hand_skill_provider/ComponentInterface.h>
+
+
+namespace armarx::control::components::retrieve_hand_skill_provider
+{
+
+    class Component :
+        virtual public ::armarx::Component
+        , virtual public ::armarx::control::components::retrieve_hand_skill_provider::ComponentInterface
+        , virtual public ::armarx::SkillProviderComponentPluginUser
+        , virtual public armarx::armem::client::plugins::PluginUser
+
+    // , virtual public armarx::DebugObserverComponentPluginUser
+        // , virtual public armarx::LightweightRemoteGuiComponentPluginUser
+        // , virtual public armarx::ArVizComponentPluginUser
+    {
+    public:
+
+        /// @see armarx::ManagedIceObject::getDefaultName()
+        std::string getDefaultName() const override;
+
+        /// Get the component's default name.
+        static std::string GetDefaultName();
+
+
+    protected:
+
+        /// @see PropertyUser::createPropertyDefinitions()
+        ::armarx::PropertyDefinitionsPtr createPropertyDefinitions() override;
+
+        /// @see armarx::ManagedIceObject::onInitComponent()
+        void onInitComponent() override;
+
+        /// @see armarx::ManagedIceObject::onConnectComponent()
+        void onConnectComponent() override;
+
+        /// @see armarx::ManagedIceObject::onDisconnectComponent()
+        void onDisconnectComponent() override;
+
+        /// @see armarx::ManagedIceObject::onExitComponent()
+        void onExitComponent() override;
+
+
+        /* (Requires armarx::LightweightRemoteGuiComponentPluginUser.)
+        /// This function should be called once in onConnect() or when you
+        /// need to re-create the Remote GUI tab.
+        void createRemoteGuiTab();
+
+        /// After calling `RemoteGui_startRunningTask`, this function is
+        /// called periodically in a separate thread. If you update variables,
+        /// make sure to synchronize access to them.
+        void RemoteGui_update() override;
+        */
+
+
+    private:
+
+        // Private methods go here.
+
+        // Forward declare `Properties` if you used it before its defined.
+        // struct Properties;
+
+        /* (Requires the armarx::ArVizComponentPluginUser.)
+        /// Draw some boxes in ArViz.
+        void drawBoxes(const Properties& p, viz::Client& arviz);
+        */
+
+
+    private:
+
+        static const std::string defaultName;
+
+
+        // Private member variables go here.
+
+
+        /// Properties shown in the Scenario GUI.
+        struct Properties
+        {
+            std::string retrieveHandSkillProviderName = "retrieveHandSkillProvider";
+        };
+
+        Properties properties;
+
+        struct Remote
+        {
+            armarx::RobotUnitInterfacePrx robotUnit;
+        };
+
+        Remote remote;
+        /* Use a mutex if you access variables from different threads
+         * (e.g. ice functions and RemoteGui_update()).
+        std::mutex propertiesMutex;
+        */
+
+
+        /* (Requires the armarx::LightweightRemoteGuiComponentPluginUser.)
+        /// Tab shown in the Remote GUI.
+        struct RemoteGuiTab : armarx::RemoteGui::Client::Tab
+        {
+            armarx::RemoteGui::Client::LineEdit boxLayerName;
+            armarx::RemoteGui::Client::IntSpinBox numBoxes;
+
+            armarx::RemoteGui::Client::Button drawBoxes;
+        };
+        RemoteGuiTab tab;
+        */
+
+    };
+
+}  // namespace armarx::control::components::retrieve_hand_skill_provider
diff --git a/source/armarx/control/components/retrieve_hand_skill_provider/ComponentInterface.ice b/source/armarx/control/components/retrieve_hand_skill_provider/ComponentInterface.ice
new file mode 100644
index 0000000000000000000000000000000000000000..2e4a661780a70a53580c8a9078bee4b29a8eb910
--- /dev/null
+++ b/source/armarx/control/components/retrieve_hand_skill_provider/ComponentInterface.ice
@@ -0,0 +1,37 @@
+/*
+ * 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    control::components::retrieve_hand_skill_provider
+ * author     Jianfeng Gao ( jianfeng dot gao at kit dot edu )
+ * date       2023
+ * copyright  http://www.gnu.org/licenses/gpl-2.0.txt
+ *            GNU General Public License
+ */
+
+
+#pragma once
+
+#include <RobotAPI/interface/skills/SkillProviderInterface.ice>
+
+
+module armarx {  module control {  module components {  module retrieve_hand_skill_provider
+{
+
+    interface ComponentInterface extends ::armarx::skills::provider::dti::SkillProviderInterface
+    {
+	    // Define your interface here.
+    };
+
+};};};};
diff --git a/source/armarx/control/ethercat/RTUtility.cpp b/source/armarx/control/ethercat/RTUtility.cpp
index b839a7fa28903d5b05f7e440079af4cc5485dbe3..1319e97b3b0e8bec5b2b6a96e4e0e3dbe594cedb 100644
--- a/source/armarx/control/ethercat/RTUtility.cpp
+++ b/source/armarx/control/ethercat/RTUtility.cpp
@@ -63,7 +63,7 @@ namespace armarx::control::ethercat
         ARMARX_INFO << "Pinning thread #" << pid << " to CPU #" << cpu;
         cpu_set_t mask;
         CPU_ZERO(&mask);
-        CPU_SET(0, &mask);
+        CPU_SET(cpu, &mask);
         int retval = sched_setaffinity(static_cast<int>(pid), sizeof(mask), &mask);
         if (retval != 0)
         {
@@ -72,7 +72,7 @@ namespace armarx::control::ethercat
         }
         cpu_set_t mask2;
         CPU_ZERO(&mask2);
-        CPU_SET(0, &mask2);
+        CPU_SET(cpu, &mask2);
         sched_getaffinity(static_cast<int>(pid), sizeof(mask2), &mask2);
         bool matches = CPU_EQUAL(&mask, &mask2);
         if (matches)
diff --git a/source/armarx/control/ethercat/bus_io/BusIO.cpp b/source/armarx/control/ethercat/bus_io/BusIO.cpp
index 4055de37d57d37a5cbc0f7ffa0bedd08f745c236..fe949e8a767f20e851dd9912a8c325a461486b67 100644
--- a/source/armarx/control/ethercat/bus_io/BusIO.cpp
+++ b/source/armarx/control/ethercat/bus_io/BusIO.cpp
@@ -18,7 +18,7 @@
 
 namespace armarx::control::ethercat
 {
-    static constexpr int TIMEOUT_UPDATE_PDO_US = 500;
+    static constexpr int TIMEOUT_UPDATE_PDO_US = 600;
 
     BusIO::BusIO()
     {
diff --git a/source/armarx/control/retrieve_hand/CMakeLists.txt b/source/armarx/control/retrieve_hand/CMakeLists.txt
new file mode 100644
index 0000000000000000000000000000000000000000..52d364741e324ef361f60ad686a7ffc75cb8c64c
--- /dev/null
+++ b/source/armarx/control/retrieve_hand/CMakeLists.txt
@@ -0,0 +1,8 @@
+armarx_add_aron_library(retrieve_hand_aron
+    ARON_FILES
+        aron/RetrieveHandParams.xml
+)
+
+add_subdirectory(constants)
+add_subdirectory(core)
+add_subdirectory(skills)
diff --git a/source/armarx/control/retrieve_hand/aron/RetrieveHandParams.xml b/source/armarx/control/retrieve_hand/aron/RetrieveHandParams.xml
new file mode 100644
index 0000000000000000000000000000000000000000..148dafe44f7b8d49bc72a4cb549fcf3d702d0d98
--- /dev/null
+++ b/source/armarx/control/retrieve_hand/aron/RetrieveHandParams.xml
@@ -0,0 +1,56 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<AronTypeDefinition>
+<!--    <AronIncludes>
+        <Include include="<armarx/control/common/mp/aron/MPConfig.xml>" autoinclude="true" />
+    </AronIncludes>-->
+    <GenerateTypes>
+        <Object name="::armarx::control::retrieve_hand::skills::RetrieveHandParams">
+
+            <ObjectChild key="robotName">
+                <String />
+            </ObjectChild>
+
+            <ObjectChild key="targetPose">
+                <Matrix4f />
+            </ObjectChild>
+
+            <ObjectChild key="robotNodeSet">
+                <String />
+            </ObjectChild>
+
+            <ObjectChild key="timeDurationInSec">
+                <Double />
+            </ObjectChild>
+
+            <ObjectChild key="kpLinear">
+                <Float />
+            </ObjectChild>
+
+            <ObjectChild key="kpAngular">
+                <Float />
+            </ObjectChild>
+
+            <ObjectChild key="kdLinear">
+                <Float />
+            </ObjectChild>
+
+            <ObjectChild key="kdAngular">
+                <Float />
+            </ObjectChild>
+
+            <ObjectChild key="fileNames">
+                <List>
+                    <String/>
+                </List>
+            </ObjectChild>
+
+<!--            <ObjectChild key="viaPoints">
+                <List>
+                    <armarx::control::common::mp::arondto::ListViaPoint />
+                </List>
+            </ObjectChild>-->
+
+        </Object>
+    </GenerateTypes>
+
+</AronTypeDefinition>
diff --git a/source/armarx/control/retrieve_hand/constants/CMakeLists.txt b/source/armarx/control/retrieve_hand/constants/CMakeLists.txt
new file mode 100644
index 0000000000000000000000000000000000000000..e0cde9141b2e3a8c5514ae8ac09d1ce1f676ee0e
--- /dev/null
+++ b/source/armarx/control/retrieve_hand/constants/CMakeLists.txt
@@ -0,0 +1,6 @@
+armarx_add_library(retrieve_hand_constants
+    SOURCES
+        constants.cpp
+    HEADERS
+        constants.h
+)
diff --git a/source/armarx/control/retrieve_hand/constants/constants.cpp b/source/armarx/control/retrieve_hand/constants/constants.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..04a2aa68f2d00cfa10540be380d7c22b7f129a0b
--- /dev/null
+++ b/source/armarx/control/retrieve_hand/constants/constants.cpp
@@ -0,0 +1 @@
+#include "constants.h"
diff --git a/source/armarx/control/retrieve_hand/constants/constants.h b/source/armarx/control/retrieve_hand/constants/constants.h
new file mode 100644
index 0000000000000000000000000000000000000000..8905289b0b7966eb84a9ed5e406bd178b2637bfb
--- /dev/null
+++ b/source/armarx/control/retrieve_hand/constants/constants.h
@@ -0,0 +1,7 @@
+#pragma once
+
+namespace armarx::control::retrieve_hand::constants
+{
+	    constexpr auto SKILL_PROVIDER_NAME="retrieve_hand_skill_provider";
+        constexpr auto SKILL_NAME="RetrieveHand";
+}
diff --git a/source/armarx/control/retrieve_hand/core/CMakeLists.txt b/source/armarx/control/retrieve_hand/core/CMakeLists.txt
new file mode 100644
index 0000000000000000000000000000000000000000..fc82912408dad78979f93f9631ad9a0b678d8c72
--- /dev/null
+++ b/source/armarx/control/retrieve_hand/core/CMakeLists.txt
@@ -0,0 +1,40 @@
+armarx_add_library(retrieve_hand_core
+    SOURCES
+        RetrieveHand.cpp
+
+    HEADERS
+        RetrieveHand.h
+
+    DEPENDENCIES_PUBLIC
+        # ArmarXCore
+        ArmarXCoreInterfaces
+        ArmarXCore
+
+        RobotAPIInterfaces
+        RobotAPICore
+
+        armem
+        armem_robot_state
+
+        armarx_control::common
+        armarx_control::deprecated_njoint_mp_controller
+
+    # DEPENDENCIES_PRIVATE
+        # ...
+    # DEPENDENCIES_INTERFACE
+        # ...
+    # DEPENDENCIES_LEGACY_PUBLIC
+        # ...
+    # DEPENDENCIES_LEGACY_PRIVATE
+        # ...
+    # DEPENDENCIES_LEGACY_INTERFACE
+        # ...
+)
+
+# Comment in to enable tests.
+# armarx_add_test(retrieve_hand_test
+#     TEST_FILES
+#         test/retrieve_hand_test.cpp
+#     DEPENDENCIES
+#         control::retrieve_hand
+# )
diff --git a/source/armarx/control/retrieve_hand/core/RetrieveHand.cpp b/source/armarx/control/retrieve_hand/core/RetrieveHand.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..504418055fa99d1df6b53ff052fbb5c2efc45997
--- /dev/null
+++ b/source/armarx/control/retrieve_hand/core/RetrieveHand.cpp
@@ -0,0 +1,137 @@
+/*
+ * 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    control::ArmarXObjects::retrieve_hand
+ * @author     Jianfeng Gao ( jianfeng dot gao at kit dot edu )
+ * @date       2023
+ * @copyright  http://www.gnu.org/licenses/gpl-2.0.txt
+ *             GNU General Public License
+ */
+
+#include "RetrieveHand.h"
+#include <ArmarXCore/core/time/Metronome.h>
+#include <armarx/control/deprecated_njoint_mp_controller/task_space/ControllerInterface.h>
+#include <armarx/control/deprecated_njoint_mp_controller/task_space/NJointTSDMPController.h>
+#include <armarx/control/common/utils.h>
+
+namespace armarx::control::retrieve_hand::core
+{
+    using namespace armarx::control::deprecated_njoint_mp_controller::task_space;
+
+    RetrieveHand::RetrieveHand(
+        const armarx::control::retrieve_hand::core::RetrieveHand::Remote& remote,
+        const armarx::control::retrieve_hand::core::RetrieveHand::Properties& properties) :
+        remote(remote), properties(properties)
+    {
+    }
+
+    bool
+    RetrieveHand::_runTSVMPController()
+    {
+        double phaseL = 100;
+        double phaseK = 1000;
+        double phaseDist0 = 50;
+        double phaseDist1 = 10;
+        double phaseKp = 2;
+        double phaseKd = 1;
+        double posToOriRatio = 10;
+        double amp = 1;
+        double maxLinearVel = 1000;
+        double maxAngularVel = 10;
+
+
+        armarx::NJointTaskSpaceDMPControllerConfigPtr tsConfig =
+            new armarx::NJointTaskSpaceDMPControllerConfig(50,
+                                                           20,
+                                                           1,
+                                                           "Linear",
+                                                           "Discrete",
+                                                           amp,
+                                                           phaseL,
+                                                           phaseK,
+                                                           phaseDist0,
+                                                           phaseDist1,
+                                                           phaseKp,
+                                                           phaseKd,
+                                                           properties.timeDurationInSec,
+                                                           posToOriRatio,
+                                                           properties.robotNodeSet,
+                                                           "",
+                                                           "",
+                                                           NJointTaskSpaceDMPControllerMode::eAll,
+                                                           maxLinearVel,
+                                                           maxAngularVel,
+                                                           50.0,
+                                                           "DMP",
+                                                           properties.kpLinear,
+                                                           properties.kdLinear,
+                                                           properties.kpAngular,
+                                                           properties.kdAngular,
+                                                           1.0,
+                                                           1.0);
+
+        armarx::NJointTaskSpaceDMPControllerInterfacePrx dmpController =
+            armarx::NJointTaskSpaceDMPControllerInterfacePrx::checkedCast(
+                remote.robotUnit->createNJointController(
+                    "NJointTSDMPController", "dmpController_RetrieveHand", tsConfig));
+
+
+        std::vector<std::string> fileNames = properties.fileNames;
+        dmpController->learnDMPFromFiles(fileNames);
+
+        // load robot
+        armarx::armem::robot_state::VirtualRobotReader robotReader;
+        robotReader.connect(remote.memoryNameSystem);
+
+        auto now = armarx::core::time::DateTime::Now();
+        auto r = robotReader.getSynchronizedRobot(properties.robotName, now);
+        ARMARX_CHECK(r.get());
+
+        std::vector<double> goals;
+        //        Eigen::Matrix4f currentPose = r->getRobotNodeSet(properties.robotNodeSet)->getTCP()->getPoseInRootFrame();
+        goals = armarx::control::common::mat4ToDVec(properties.targetPose);
+
+
+        // if (in.isViaPoseListSet() && in.isViaPoseCanValSet() && in.getViaPoseList().size() == in.getViaPoseCanVal().size())
+        // {
+        //     for (size_t i = 0; i < in.getViaPoseList().size(); ++i)
+        //     {
+        //         dmpController->setViaPoints(in.getViaPoseCanVal().at(i), Helpers::pose2dvec(in.getViaPoseList().at(i)->toEigen()));
+        //     }
+        // }
+        //
+        dmpController->activateController();
+
+        dmpController->runDMP(goals, 1.0);
+
+        const auto metronomeTargetPeriod = armarx::Duration::MilliSeconds(10);
+        armarx::Metronome loopScheduler(metronomeTargetPeriod);
+        while (running.load() && not dmpController->isFinished())
+        {
+            loopScheduler.waitForNextTick();
+        }
+
+        dmpController->deactivateController();
+        while (dmpController->isControllerActive())
+        {
+            loopScheduler.waitForNextTick();
+        }
+        dmpController->deleteController();
+
+        running.store(false);
+        return true;
+    }
+
+} // namespace armarx::control::retrieve_hand::core
diff --git a/source/armarx/control/retrieve_hand/core/RetrieveHand.h b/source/armarx/control/retrieve_hand/core/RetrieveHand.h
new file mode 100644
index 0000000000000000000000000000000000000000..a3da0e31fbe78c2e3716b547698bb6900eb2df87
--- /dev/null
+++ b/source/armarx/control/retrieve_hand/core/RetrieveHand.h
@@ -0,0 +1,103 @@
+/*
+ * 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    control::ArmarXObjects::retrieve_hand
+ * @author     Jianfeng Gao ( jianfeng dot gao at kit dot edu )
+ * @date       2023
+ * @copyright  http://www.gnu.org/licenses/gpl-2.0.txt
+ *             GNU General Public License
+ */
+
+#pragma once
+
+#include <RobotAPI/libraries/armem_objects/client/attachment/Reader.h>
+#include <RobotAPI/libraries/armem_objects/client/attachment/Writer.h>
+#include <RobotAPI/libraries/armem_robot_state/client/common/VirtualRobotReader.h>
+#include <RobotAPI/libraries/robot_name_service/core/Robot.h>
+
+
+namespace armarx::control::retrieve_hand::core
+{
+    /**
+    * @defgroup Library-retrieve_hand retrieve_hand
+    * @ingroup control
+    * A description of the library retrieve_hand.
+    *
+    * @class retrieve_hand
+    * @ingroup Library-retrieve_hand
+    * @brief Brief description of class retrieve_hand.
+    *
+    * Detailed description of class retrieve_hand.
+    */
+    class RetrieveHand
+    {
+    public:
+
+        struct Remote
+        {
+            // armarx::viz::Client arviz;
+            armarx::armem::client::MemoryNameSystem memoryNameSystem;
+
+            armarx::RobotUnitInterfacePrx robotUnit;
+        };
+
+        struct Properties
+        {
+            std::string robotName;
+            std::string robotNodeSet;
+            double timeDurationInSec;
+            Eigen::Matrix4f targetPose;
+            float kpLinear = 10.0f;
+            float kpAngular = 10.0f;
+            float kdLinear = 1.0f;
+            float kdAngular = 1.0f;
+
+            std::vector<std::string> fileNames;
+        };
+
+        struct Subskills
+        {
+            std::function<bool(const Eigen::Vector3f&)> lookAt;
+            std::function<bool()> openHand;
+            std::function<bool()> closeHand;
+        };
+
+        RetrieveHand(const Remote&, const Properties&);
+        virtual ~RetrieveHand() = default;
+
+        void
+        stop()
+        {
+            running.store(false);
+        }
+
+        bool execute()
+        {
+            std::scoped_lock l(executionMutex);
+            running.store(true);
+            return _runTSVMPController();
+        }
+
+    protected:
+        Remote remote;
+        Properties properties;
+
+    private:
+        bool _runTSVMPController();
+        mutable std::mutex executionMutex;
+        std::atomic_bool running = false;
+    };
+
+}
diff --git a/source/armarx/control/retrieve_hand/skills/CMakeLists.txt b/source/armarx/control/retrieve_hand/skills/CMakeLists.txt
new file mode 100644
index 0000000000000000000000000000000000000000..84f8ae276bb591ff578325043a54959f8b3d3903
--- /dev/null
+++ b/source/armarx/control/retrieve_hand/skills/CMakeLists.txt
@@ -0,0 +1,39 @@
+armarx_add_library(retrieve_hand_skills
+    SOURCES
+        RetrieveHand.cpp
+
+    HEADERS
+        RetrieveHand.h
+
+    DEPENDENCIES_PUBLIC
+        # ArmarXCore
+        ArmarXCoreInterfaces
+        ArmarXCore
+
+        # RobotAPI
+        RobotAPISkills
+
+        # armarx_control
+        armarx_control::retrieve_hand_constants
+        armarx_control::retrieve_hand_core
+        armarx_control::retrieve_hand_aron
+
+    # DEPENDENCIES_PRIVATE
+        # ...
+    # DEPENDENCIES_INTERFACE
+        # ...
+    # DEPENDENCIES_LEGACY_PUBLIC
+        # ...
+    # DEPENDENCIES_LEGACY_PRIVATE
+        # ...
+    # DEPENDENCIES_LEGACY_INTERFACE
+        # ...
+)
+
+# Comment in to enable tests.
+# armarx_add_test(retrieve_hand_test
+#     TEST_FILES
+#         test/retrieve_hand_test.cpp
+#     DEPENDENCIES
+#         control::retrieve_hand
+# )
diff --git a/source/armarx/control/retrieve_hand/skills/RetrieveHand.cpp b/source/armarx/control/retrieve_hand/skills/RetrieveHand.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..2aeed21478dab22bdf159787467afb340f10295c
--- /dev/null
+++ b/source/armarx/control/retrieve_hand/skills/RetrieveHand.cpp
@@ -0,0 +1,85 @@
+#include "RetrieveHand.h"
+
+#include <armarx/control/retrieve_hand/constants/constants.h>
+#include <armarx/control/deprecated_njoint_mp_controller/task_space/ControllerInterface.h>
+
+namespace armarx::control::retrieve_hand::skills
+{
+
+    ::armarx::skills::SkillDescription
+    RetrieveHand::GetSkillDescription()
+    {
+        ParamType defaultParams;
+        // defaultParams.exampleStringParam = "exampleDefaultValue";
+
+        auto skillId = armarx::skills::SkillID{.skillName = armarx::control::retrieve_hand::constants::SKILL_NAME};
+
+        return ::armarx::skills::SkillDescription{
+            .skillId = skillId,
+            .description = "TODO: Description of skill RetrieveHand.",
+            .rootProfileDefaults = defaultParams.toAron(),
+            .timeout = ::armarx::Duration::MilliSeconds(1000),
+            .parametersType = ParamType::ToAronType()};
+    }
+
+    RetrieveHand::RetrieveHand(const Remote& r) :
+            Base(GetSkillDescription()), remote(r)
+
+    {
+    }
+
+
+    RetrieveHand::RetrieveHand() :
+        Base(GetSkillDescription())
+    {
+    }
+
+    /*
+    ::armarx::skills::Skill::InitResult
+    RetrieveHand::init(const SpecializedInitInput&)
+    {
+        return InitResult{.status = ::armarx::skills::TerminatedSkillStatus::Succeeded};
+    }
+    */
+
+
+    ::armarx::skills::Skill::MainResult
+    RetrieveHand::main(const SpecializedMainInput& in)
+    {
+        // Enter main code of the skill here.
+        core::RetrieveHand::Remote rem{
+                .memoryNameSystem = remote.memoryNameSystem,
+                .robotUnit = remote.robotUnit};
+
+        core::RetrieveHand::Properties props{
+                .robotName = in.parameters.robotName,
+                .robotNodeSet = in.parameters.robotNodeSet,
+                .timeDurationInSec = in.parameters.timeDurationInSec,
+                .targetPose = in.parameters.targetPose,
+                .kpLinear = in.parameters.kpLinear,
+                .kpAngular = in.parameters.kpAngular,
+                .kdLinear = in.parameters.kdLinear,
+                .kdAngular = in.parameters.kdAngular,
+                .fileNames = in.parameters.fileNames,
+        };
+
+
+        impl = std::make_unique<core::RetrieveHand>(rem, props);
+
+        auto res = impl->execute();
+        if (res)
+        {
+            return MakeSucceededResult();
+        }
+        return MakeFailedResult();
+    }
+
+    /*
+    ::armarx::skills::Skill::ExitResult
+    RetrieveHand::exit(const SpecializedExitInput&)
+    {
+        return ExitResult{.status = ::armarx::skills::TerminatedSkillStatus::Succeeded};
+    }
+    */
+
+}
diff --git a/source/armarx/control/retrieve_hand/skills/RetrieveHand.h b/source/armarx/control/retrieve_hand/skills/RetrieveHand.h
new file mode 100644
index 0000000000000000000000000000000000000000..6bfc9897c5d9f7409de640d54a39352f54e2ca2a
--- /dev/null
+++ b/source/armarx/control/retrieve_hand/skills/RetrieveHand.h
@@ -0,0 +1,63 @@
+#pragma once
+
+#include <RobotAPI/libraries/skills/provider/SimpleSpecializedSkill.h>
+#include <armarx/control/retrieve_hand/core/RetrieveHand.h>
+#include <armarx/control/retrieve_hand/aron/RetrieveHandParams.aron.generated.h>
+
+
+namespace armarx::control::retrieve_hand::skills
+{
+
+    /**
+    * @class RetrieveHand
+    * @ingroup Library-retrieve_hand
+    * @brief Brief description of class retrieve_hand.
+    *
+    * Detailed description of class retrieve_hand.
+    */
+    class RetrieveHand : public ::armarx::skills::SimpleSpecializedSkill<RetrieveHandParams>
+    {
+    public:
+        using Base = ::armarx::skills::SimpleSpecializedSkill<RetrieveHandParams>;
+        static ::armarx::skills::SkillDescription GetSkillDescription();
+        struct Remote
+        {
+            // armarx::viz::Client arviz;
+            armarx::armem::client::MemoryNameSystem memoryNameSystem;
+
+            armarx::RobotUnitInterfacePrx robotUnit;
+        };
+
+        struct Properties
+        {
+            std::string robotName;
+            // std::string robotNodeSet;
+            // std::optional<armarx::ObjectID> objectId = std::nullopt;
+        };
+
+        RetrieveHand(const Remote& r);
+
+        struct Subskills
+        {
+            std::function<bool(const Eigen::Vector3f&)> lookAt;
+            std::function<bool()> openHand;
+            std::function<bool()> closeHand;
+        };
+
+    public:
+        RetrieveHand();
+
+        // SpecializedSkill interface
+        // Enable each function you want to override.
+        // ::armarx::skills::Skill::InitResult init(const SpecializedInitInput&) override;
+        ::armarx::skills::Skill::MainResult main(const SpecializedMainInput& in) override;
+    private:
+        Remote remote;
+        Properties properties;
+        // ::armarx::skills::Skill::ExitResult exit(const SpecializedExitInput&) override;
+
+        std::unique_ptr<armarx::control::retrieve_hand::core::RetrieveHand> impl;
+
+    };
+
+}
diff --git a/source/armarx/control/retrieve_hand/test/retrieve_hand_test.cpp b/source/armarx/control/retrieve_hand/test/retrieve_hand_test.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..06e14af7f800dc80ea016072d5469692ad6cc842
--- /dev/null
+++ b/source/armarx/control/retrieve_hand/test/retrieve_hand_test.cpp
@@ -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/>.
+ *
+ * @package    control::ArmarXObjects::retrieve_hand
+ * @author     Jianfeng Gao ( jianfeng dot gao at kit dot edu )
+ * @date       2023
+ * @copyright  http://www.gnu.org/licenses/gpl-2.0.txt
+ *             GNU General Public License
+ */
+
+#define BOOST_TEST_MODULE control::ArmarXLibraries::retrieve_hand
+
+#define ARMARX_BOOST_TEST
+
+#include <control/Test.h>
+#include "../retrieve_hand.h"
+
+#include <iostream>
+
+BOOST_AUTO_TEST_CASE(testExample)
+{
+
+    BOOST_CHECK_EQUAL(true, true);
+}