diff --git a/source/RobotAPI/libraries/skills/CMakeLists.txt b/source/RobotAPI/libraries/skills/CMakeLists.txt
index c9d6055a2c24dd0d92b2b8a9eeb5da206d0c43be..107e4a1e6d57efe3eef22371d379bb274ef6834d 100644
--- a/source/RobotAPI/libraries/skills/CMakeLists.txt
+++ b/source/RobotAPI/libraries/skills/CMakeLists.txt
@@ -17,6 +17,7 @@ armarx_add_library(
         ./provider/Skill.cpp
         ./provider/PeriodicSkill.cpp
         ./provider/SpecializedSkill.cpp
+        ./provider/PeriodicSpecializedSkill.cpp
         ./provider/SkillDescription.cpp
         ./provider/SkillStatusUpdate.cpp
         ./provider/helper/LambdaSkillImplementation.cpp
@@ -27,6 +28,7 @@ armarx_add_library(
         ./provider/Skill.h
         ./provider/PeriodicSkill.h
         ./provider/SpecializedSkill.h
+        ./provider/PeriodicSpecializedSkill.h
         ./provider/SkillDescription.h
         ./provider/SkillStatusUpdate.h
         ./provider/helper/LambdaSkillImplementation.h
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
index 2b67a3f49676be6e4d86dfafd68a1ab4144b1fca..b40179c2ae363eff5e0e54d5968c1b39c97cd375 100644
--- a/source/RobotAPI/libraries/skills/provider/PeriodicSpecializedSkill.h
+++ b/source/RobotAPI/libraries/skills/provider/PeriodicSpecializedSkill.h
@@ -21,8 +21,8 @@
 
 #pragma once
 
-#include "ArmarXCore/core/time/Metronome.h"
 #include <ArmarXCore/core/time/Frequency.h>
+#include <ArmarXCore/core/time/Metronome.h>
 
 #include "Skill.h"
 #include "SpecializedSkill.h"
@@ -30,15 +30,69 @@
 namespace armarx::skills
 {
     template <class AronT>
-    class PeriodicSpecializedSkill : virtual public SpecializedSkill<AronT>
+    class PeriodicSpecializedSkill : public SpecializedSkill<AronT>
     {
     public:
+        using Base = SpecializedSkill<AronT>;
+
+        PeriodicSpecializedSkill() = delete;
+
         PeriodicSpecializedSkill(const SkillDescription& skillDescription,
-                                 const armarx::Frequency& frequency);
+                                 const armarx::Frequency& frequency) :
+            Base(skillDescription), frequency(frequency)
+        {
+        }
 
     protected:
-        typename Skill::Status _execute(const AronT& params,
-                                        const Skill::CallbackT& callback) final;
+        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
         {
@@ -59,61 +113,4 @@ namespace armarx::skills
         const armarx::Frequency frequency;
     };
 
-    template <class AronT>
-    PeriodicSpecializedSkill<AronT>::PeriodicSpecializedSkill(const SkillDescription& skillDescription,
-                                 const armarx::Frequency& frequency) :
-        Skill(skillDescription), frequency(frequency)
-    {
-    }
-
-    template <class AronT>
-    Skill::Status
-    PeriodicSpecializedSkill<AronT>::_execute(const AronT& params, const Skill::CallbackT& callback)
-    {
-       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.");
-    }
 } // namespace armarx::skills
diff --git a/source/RobotAPI/libraries/skills/provider/SpecializedSkill.h b/source/RobotAPI/libraries/skills/provider/SpecializedSkill.h
index 5f8e5cfc68f12fcd107b8aedc526f3e29f1d03dc..043ec2df6a2678578f556b5f918f9518873280ac 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;