diff --git a/source/RobotAPI/libraries/skills/core/Skill.cpp b/source/RobotAPI/libraries/skills/core/Skill.cpp
index 0b7a32df224d925ced896414d7d47f540f04a0d5..a01eb4908baed4e5f6dc18c76f5493053d4bb886 100644
--- a/source/RobotAPI/libraries/skills/core/Skill.cpp
+++ b/source/RobotAPI/libraries/skills/core/Skill.cpp
@@ -19,10 +19,22 @@ namespace armarx
         }
 
         std::optional<TerminatedSkillStatusUpdate>
-        Skill::callSubskill(const SkillProxy& prx, const aron::data::DictPtr& params)
+        Skill::callSubskill(const SkillProxy& proxy)
         {
-            auto eid = callSubskillAsync(prx, params);
-            auto ret = prx.join(eid);
+            return callSubskill(proxy, proxy.getRootProfileParameters());
+        }
+
+        std::optional<TerminatedSkillStatusUpdate>
+        Skill::callSubskill(const SkillProxy& proxy, const aron::data::DictPtr& parameters)
+        {
+            auto executionId = callSubskillAsync(proxy, parameters);
+            auto ret = proxy.join(executionId);
+
+            // While the sub skill was running, our skill might also have been aborted.
+            // In this case, the correct behavour would be aborting ourselves.
+            // The caller of callSubskill() can catch the thrown error::SkillAbortedException
+            // if necessary.
+            throwIfSkillShouldTerminate();
             return ret;
         }
 
@@ -37,6 +49,35 @@ namespace armarx
             return eid;
         }
 
+        std::optional<TerminatedSkillStatusUpdate>
+        Skill::callSubskill(const SkillID& skillId)
+        {
+            return callSubskill(SkillProxy(manager, skillId));
+        }
+
+        std::optional<TerminatedSkillStatusUpdate>
+        Skill::callSubskill(const SkillID& skillId, const aron::data::DictPtr& parameters)
+        {
+            return callSubskill(SkillProxy(manager, skillId), parameters);
+        }
+
+        std::optional<TerminatedSkillStatusUpdate>
+        Skill::callSubskill(const SkillID& skillId,
+                            std::function<void(aron::data::DictPtr&)> parametersFunction)
+        {
+            SkillProxy proxy(manager, skillId);
+
+            aron::data::DictPtr parameters = proxy.getRootProfileParameters();
+            if (not parameters)
+            {
+                parameters = armarx::aron::make_dict();
+            }
+
+            parametersFunction(parameters);
+
+            return callSubskill(proxy, parameters);
+        }
+
         void
         Skill::updateParameters(const aron::data::DictPtr& d)
         {
diff --git a/source/RobotAPI/libraries/skills/core/Skill.h b/source/RobotAPI/libraries/skills/core/Skill.h
index 5ec80e77d9956e8516ae84ffec16313bab0c9206..9fffd35a6f258e778200351ef387ba9d3b184480 100644
--- a/source/RobotAPI/libraries/skills/core/Skill.h
+++ b/source/RobotAPI/libraries/skills/core/Skill.h
@@ -1,15 +1,11 @@
 #pragma once
 
-// std/stl
 #include <functional>
 #include <mutex>
 #include <queue>
 #include <thread>
 
-// base class
 #include <ArmarXCore/core/logging/Logging.h>
-
-// ArmarX
 #include <ArmarXCore/core/time/DateTime.h>
 #include <ArmarXCore/core/time/Metronome.h>
 
@@ -27,6 +23,9 @@ namespace armarx
 {
     namespace skills
     {
+        /**
+         * @brief Base class for skills.
+         */
         class Skill : public armarx::Logging
         {
         public:
@@ -185,14 +184,136 @@ namespace armarx
             void installConditionWithCallback(std::function<bool()>&& f,
                                               std::function<void()>&& cb);
 
-            /// call a subskill and block until the subskill terminates.
-            /// If you call a subskill this way it will be stopped if the current skill stops.
+            // Calling subskills
+
+            /**
+             * @brief Call a subskill with default parameters and block until the subskill terminates.
+             *
+             * If you call a subskill this way it will be stopped if the current skill stops.
+             *
+             * @param proxy Skill proxy.
+             * @return Terminated skill status update.
+             * @throw armarx::skills::error::SkillAbortedException
+             *      If the calling skill has been aborted.
+             * @throw armarx::skills::error::SkillFailedException
+             *      If the calling skill's timeout was reached.
+             */
+            std::optional<TerminatedSkillStatusUpdate>
+            callSubskill(const skills::SkillProxy& proxy);
+
+            /**
+             * @brief Call a subskill with given parameters and block until the subskill terminates.
+             * @param proxy Skill proxy.
+             * @param parameters Parameters passed to the skill.
+             * @return Terminated skill status update.
+             * @throw armarx::skills::error::SkillAbortedException
+             *      If the calling skill has been aborted.
+             * @throw armarx::skills::error::SkillFailedException
+             *      If the calling skill's timeout was reached.
+             */
             std::optional<TerminatedSkillStatusUpdate>
-            callSubskill(const skills::SkillProxy& prx, const aron::data::DictPtr& = nullptr);
+            callSubskill(const skills::SkillProxy& proxy, const aron::data::DictPtr& parameters);
 
             /// Similar to callSubskill but non-blocking
-            skills::SkillExecutionID callSubskillAsync(const skills::SkillProxy& prx,
-                                                       const aron::data::DictPtr& = nullptr);
+            skills::SkillExecutionID callSubskillAsync(const skills::SkillProxy& proxy);
+
+            /// Similar to callSubskill but non-blocking
+            skills::SkillExecutionID callSubskillAsync(const skills::SkillProxy& proxy,
+                                                       const aron::data::DictPtr& parameters);
+
+            /**
+             * @brief Call a subskill with the given ID and its default parameters.
+             * @param skillId The subskill's ID.
+             * @return The terminated skill status update.
+             * @throw armarx::skills::error::SkillAbortedException
+             *      If the calling skill has been aborted.
+             * @throw armarx::skills::error::SkillFailedException
+             *      If the calling skill's timeout was reached.
+             */
+            std::optional<TerminatedSkillStatusUpdate> callSubskill(const SkillID& skillId);
+
+            /**
+             * @brief Call a subskill with the given ID and parameters.
+             * @param skillId The subskill's ID.
+             * @param parameters The parameters.
+             * @return The terminated skill status update.
+             * @throw armarx::skills::error::SkillAbortedException
+             *      If the calling skill has been aborted.
+             * @throw armarx::skills::error::SkillFailedException
+             *      If the calling skill's timeout was reached.
+             */
+            std::optional<TerminatedSkillStatusUpdate>
+            callSubskill(const SkillID& skillId, const aron::data::DictPtr& parameters);
+
+            /**
+             * @brief Call a subskill with the given ID and parameters.
+             * @param skillId The subskill's ID.
+             * @param parameters The parameters.
+             * @return The terminated skill status update.
+             * @throw armarx::skills::error::SkillAbortedException
+             *      If the calling skill has been aborted.
+             * @throw armarx::skills::error::SkillFailedException
+             *      If the calling skill's timeout was reached.
+             */
+            template <class ParameterT>
+            std::optional<TerminatedSkillStatusUpdate>
+            callSubskill(const SkillID& skillId, const ParameterT& parameters)
+            {
+                return callSubskill(skillId, parameters.toAron());
+            }
+
+            /**
+             * @brief Call a subskill with parameters based on the default parameters.
+             *
+             * Creates the skill's default parameters, and calls `parametersFunction` on them.
+             * This allows the caller to modify the parameters before executing the skill.
+             *
+             * @param skillId The subskill's ID.
+             * @param parametersFunction Function which edits the parameters.
+             * @return The terminated skill status update.
+             * @throw armarx::skills::error::SkillAbortedException
+             *      If the calling skill has been aborted.
+             * @throw armarx::skills::error::SkillFailedException
+             *      If the calling skill's timeout was reached.
+             */
+            std::optional<TerminatedSkillStatusUpdate>
+            callSubskill(const SkillID& skillId,
+                         std::function<void(aron::data::DictPtr& parameters)> parametersFunction);
+
+            /**
+             * @brief Call a subskill with parameters based on the default parameters.
+             *
+             * Creates the skill's default parameters, converts them to `ParameterT`,
+             * and calls `parametersFunction` on them.
+             * This allows the caller to modify the parameters as `ParameterT` before executing
+             * the skill.
+             *
+             * @param skillId The subskill's ID.
+             * @param parametersFunction Function which edits the parameters.
+             * @return The terminated skill status update.
+             * @throw armarx::skills::error::SkillAbortedException
+             *      If the calling skill has been aborted.
+             * @throw armarx::skills::error::SkillFailedException
+             *      If the calling skill's timeout was reached.
+             */
+            template <class ParameterT>
+            std::optional<TerminatedSkillStatusUpdate>
+            callSubskill(const SkillID& skillId,
+                         std::function<void(ParameterT& parameters)> parametersFunction)
+            {
+                SkillProxy proxy(manager, skillId);
+
+                ParameterT parameters;
+                if (auto parametersAron = proxy.getRootProfileParameters())
+                {
+                    parameters = ParameterT::FromAron(parametersAron);
+                }
+
+                parametersFunction(parameters);
+
+                return callSubskill(proxy, parameters.toAron());
+            }
+
 
         public:
             // running params