From bf28e9e5b2dc9678c7509f13ea513dbe0da3fc2e Mon Sep 17 00:00:00 2001
From: Fabian Peller <fabian.peller-konrad@kit.edu>
Date: Fri, 6 Oct 2023 14:24:59 +0200
Subject: [PATCH] legacy support old skill api

---
 .../libraries/skills/provider/CMakeLists.txt  |  6 ++
 .../libraries/skills/provider/SimpleSkill.cpp | 55 +++++++++++
 .../libraries/skills/provider/SimpleSkill.h   | 47 +++++++++
 .../{legacy => }/SimpleSpecializedSkill.cpp   |  2 +-
 .../skills/provider/SimpleSpecializedSkill.h  | 97 +++++++++++++++++++
 .../provider/SkillProviderComponentPlugin.cpp | 13 ++-
 .../provider/SkillProviderComponentPlugin.h   | 23 ++++-
 .../skills/provider/SpecializedSkill.h        | 23 +++--
 .../detail/SkillImplementationWrapper.cpp     | 67 +++++++------
 .../detail/SkillImplementationWrapper.h       | 10 +-
 .../skills/provider/legacy/SimpleSkill.cpp    |  6 --
 .../skills/provider/legacy/SimpleSkill.h      | 15 ---
 .../provider/legacy/SimpleSpecializedSkill.h  | 15 ---
 13 files changed, 293 insertions(+), 86 deletions(-)
 create mode 100644 source/RobotAPI/libraries/skills/provider/SimpleSkill.cpp
 create mode 100644 source/RobotAPI/libraries/skills/provider/SimpleSkill.h
 rename source/RobotAPI/libraries/skills/provider/{legacy => }/SimpleSpecializedSkill.cpp (62%)
 create mode 100644 source/RobotAPI/libraries/skills/provider/SimpleSpecializedSkill.h
 delete mode 100644 source/RobotAPI/libraries/skills/provider/legacy/SimpleSkill.cpp
 delete mode 100644 source/RobotAPI/libraries/skills/provider/legacy/SimpleSkill.h
 delete mode 100644 source/RobotAPI/libraries/skills/provider/legacy/SimpleSpecializedSkill.h

diff --git a/source/RobotAPI/libraries/skills/provider/CMakeLists.txt b/source/RobotAPI/libraries/skills/provider/CMakeLists.txt
index 4ba71803f..e5df87081 100644
--- a/source/RobotAPI/libraries/skills/provider/CMakeLists.txt
+++ b/source/RobotAPI/libraries/skills/provider/CMakeLists.txt
@@ -19,17 +19,22 @@ armarx_add_library(
         SkillProviderComponentPlugin.cpp
         SkillFactory.cpp
         LambdaSkill.cpp
+        SimpleSkill.cpp
+        SimpleSpecializedSkill.cpp
         SkillProxy.cpp
         PeriodicSkill.cpp
         SpecializedSkill.cpp
         PeriodicSpecializedSkill.cpp
         detail/SkillImplementationWrapper.cpp
         SkillContext.cpp
+
         
     HEADERS
         SkillProviderComponentPlugin.h
         SkillFactory.h
         LambdaSkill.h
+        SimpleSkill.h
+        SimpleSpecializedSkill.h
         SkillProxy.h
         PeriodicSkill.h
         SpecializedSkill.h
@@ -37,6 +42,7 @@ armarx_add_library(
         detail/SkillImplementationWrapper.h
         SkillContext.h
 
+
         mixins/All.h
         mixins/ArvizSkillMixin.h
         mixins/MNSSkillMixin.h
diff --git a/source/RobotAPI/libraries/skills/provider/SimpleSkill.cpp b/source/RobotAPI/libraries/skills/provider/SimpleSkill.cpp
new file mode 100644
index 000000000..96ec83917
--- /dev/null
+++ b/source/RobotAPI/libraries/skills/provider/SimpleSkill.cpp
@@ -0,0 +1,55 @@
+#include "SimpleSkill.h"
+
+namespace armarx::skills
+{
+    Skill::InitResult
+    SimpleSKill::init()
+    {
+        InitInput i;
+        i.executorName = this->executorName;
+        i.params = this->parameters;
+        return this->init(i);
+    }
+
+    Skill::MainResult
+    SimpleSKill::main()
+    {
+        MainInput i;
+        i.executorName = this->executorName;
+        i.params = this->parameters;
+        i.callback = this->callback;
+        return this->main(i);
+    }
+
+    Skill::ExitResult
+    SimpleSKill::exit()
+    {
+        ExitInput i;
+        i.executorName = this->executorName;
+        i.params = this->parameters;
+        return this->exit(i);
+    }
+
+    Skill::InitResult
+    SimpleSKill::init(const InitInput& in)
+    {
+        // Default nothing to init
+        return {.status = TerminatedSkillStatus::Succeeded};
+    }
+
+    Skill::MainResult
+    SimpleSKill::main(const MainInput& in)
+    {
+        // This is just a dummy implementation
+        ARMARX_IMPORTANT << "Dummy executing skill '" << description.skillId
+                         << "'. Please overwrite this method.";
+        return {.status = TerminatedSkillStatus::Succeeded, .data = nullptr};
+    }
+
+    Skill::ExitResult
+    SimpleSKill::exit(const ExitInput& in)
+    {
+        // Default nothing to exit
+        return {.status = TerminatedSkillStatus::Succeeded};
+    }
+} // namespace armarx::skills
diff --git a/source/RobotAPI/libraries/skills/provider/SimpleSkill.h b/source/RobotAPI/libraries/skills/provider/SimpleSkill.h
new file mode 100644
index 000000000..c4b736dfb
--- /dev/null
+++ b/source/RobotAPI/libraries/skills/provider/SimpleSkill.h
@@ -0,0 +1,47 @@
+#pragma once
+
+#include <RobotAPI/libraries/skills/core/Skill.h>
+
+namespace armarx
+{
+    namespace skills
+    {
+        class SimpleSKill : public Skill
+        {
+        public:
+            using Skill::Skill;
+
+            struct InitInput
+            {
+                std::string executorName;
+                aron::data::DictPtr params;
+            };
+
+            struct MainInput
+            {
+                std::string executorName;
+                aron::data::DictPtr params;
+                CallbackT callback;
+            };
+
+            struct ExitInput
+            {
+                std::string executorName;
+                aron::data::DictPtr params;
+            };
+
+
+        protected:
+            // legacy methods
+            virtual InitResult init(const InitInput& in);
+            virtual MainResult main(const MainInput& in);
+            virtual ExitResult exit(const ExitInput& in);
+
+            InitResult init() final;
+            MainResult main() final;
+            ExitResult exit() final;
+
+        private:
+        };
+    } // namespace skills
+} // namespace armarx
diff --git a/source/RobotAPI/libraries/skills/provider/legacy/SimpleSpecializedSkill.cpp b/source/RobotAPI/libraries/skills/provider/SimpleSpecializedSkill.cpp
similarity index 62%
rename from source/RobotAPI/libraries/skills/provider/legacy/SimpleSpecializedSkill.cpp
rename to source/RobotAPI/libraries/skills/provider/SimpleSpecializedSkill.cpp
index 4b272f291..49a5c2e49 100644
--- a/source/RobotAPI/libraries/skills/provider/legacy/SimpleSpecializedSkill.cpp
+++ b/source/RobotAPI/libraries/skills/provider/SimpleSpecializedSkill.cpp
@@ -1,6 +1,6 @@
 #include "SimpleSpecializedSkill.h"
 
-namespace armarx
+namespace armarx::skills
 {
 
 }
diff --git a/source/RobotAPI/libraries/skills/provider/SimpleSpecializedSkill.h b/source/RobotAPI/libraries/skills/provider/SimpleSpecializedSkill.h
new file mode 100644
index 000000000..a62ca4ae5
--- /dev/null
+++ b/source/RobotAPI/libraries/skills/provider/SimpleSpecializedSkill.h
@@ -0,0 +1,97 @@
+#pragma once
+
+#include <RobotAPI/libraries/skills/core/Skill.h>
+
+namespace armarx
+{
+    namespace skills
+    {
+        template <class AronT>
+        class SimpleSpecializedSkill : public Skill
+        {
+        public:
+            using ParamType = AronT;
+            using Skill::Skill;
+
+            struct SpecializedInitInput
+            {
+                std::string executorName;
+                AronT params;
+            };
+
+            struct SpecializedMainInput
+            {
+                std::string executorName;
+                AronT params;
+                CallbackT callback;
+            };
+
+            struct SpecializedExitInput
+            {
+                std::string executorName;
+                AronT params;
+            };
+
+
+        protected:
+            // legacy methods
+            virtual InitResult
+            init(const SpecializedInitInput& in)
+            {
+                return InitResult{.status = TerminatedSkillStatus::Succeeded};
+            }
+
+            virtual MainResult
+            main(const SpecializedMainInput& in)
+            {
+                ARMARX_IMPORTANT << "Dummy executing skill '" << description.skillId
+                                 << "'. Please overwrite this method.";
+                return Skill::MainResult{.status = TerminatedSkillStatus::Succeeded,
+                                         .data = nullptr};
+            }
+
+            virtual ExitResult
+            exit(const SpecializedExitInput& in)
+            {
+                return ExitResult{.status = TerminatedSkillStatus::Succeeded};
+            }
+
+            InitResult
+            init() final
+            {
+                AronT p;
+                p.fromAron(this->parameters);
+
+                SpecializedInitInput i;
+                i.executorName = this->executorName;
+                i.params = p;
+                return this->init(i);
+            }
+
+            MainResult
+            main() final
+            {
+                AronT p;
+                p.fromAron(this->parameters);
+
+                SpecializedMainInput i;
+                i.executorName = this->executorName;
+                i.callback = this->callback;
+                i.params = p;
+                return this->main(i);
+            }
+
+            ExitResult
+            exit() final
+            {
+                AronT p;
+                p.fromAron(this->parameters);
+
+                SpecializedExitInput i;
+                i.executorName = this->executorName;
+                i.params = p;
+                return this->exit(i);
+            }
+        };
+    } // namespace skills
+} // namespace armarx
diff --git a/source/RobotAPI/libraries/skills/provider/SkillProviderComponentPlugin.cpp b/source/RobotAPI/libraries/skills/provider/SkillProviderComponentPlugin.cpp
index c187b4ad4..d24535a22 100644
--- a/source/RobotAPI/libraries/skills/provider/SkillProviderComponentPlugin.cpp
+++ b/source/RobotAPI/libraries/skills/provider/SkillProviderComponentPlugin.cpp
@@ -103,8 +103,11 @@ namespace armarx::plugins
         // NON BLOCKING: WE ASSERT THAT THE LOCK IS ALREADY TAKEN
         ARMARX_CHECK(skillId.fullySpecified());
 
-        ARMARX_CHECK_GREATER(skillFactories.count(skillId), 0)
-            << "Skill '" + skillId.toString() + "' not found.";
+        if (skillFactories.count(skillId) == 0)
+        {
+            ARMARX_INFO << "Could not find a skill factory for id: " << skillId;
+            return nullptr;
+        }
 
         auto* facPtr = skillFactories.at(skillId).get();
         return static_cast<skills::SkillFactory*>(facPtr);
@@ -191,6 +194,7 @@ namespace armarx::plugins
             auto l1 = std::unique_lock{skillFactoriesMutex};
 
             const auto& fac = getSkillFactory(executionRequest.skillId);
+            ARMARX_CHECK(fac) << "Could not find a factory for skill " << executionRequest.skillId;
 
             // async start execution. But we wait for the execution to finish at the end of this method
             execution = std::thread(
@@ -202,7 +206,7 @@ namespace armarx::plugins
                         auto it = skillExecutions.emplace(
                             std::piecewise_construct,
                             std::make_tuple(executionId),
-                            std::make_tuple(fac, executionId, usedParameterization));
+                            std::make_tuple(*fac, executionId, usedParameterization));
 
                         ARMARX_CHECK(it.second)
                             << "For some reason a skill '" << executionId.skillId.toString()
@@ -257,6 +261,7 @@ namespace armarx::plugins
             auto l1 = std::unique_lock{skillFactoriesMutex};
 
             const auto& fac = getSkillFactory(executionRequest.skillId);
+            ARMARX_CHECK(fac) << "Could not find a factory for skill " << executionRequest.skillId;
 
             // async start execution. But we wait for the execution to finish at the end of this method
             execution = std::thread(
@@ -268,7 +273,7 @@ namespace armarx::plugins
                         auto it = skillExecutions.emplace(
                             std::piecewise_construct,
                             std::make_tuple(executionId),
-                            std::make_tuple(fac, executionId, usedParameterization));
+                            std::make_tuple(*fac, executionId, usedParameterization));
 
                         ARMARX_CHECK(it.second)
                             << "For some reason a skill '" << executionId.skillId.toString()
diff --git a/source/RobotAPI/libraries/skills/provider/SkillProviderComponentPlugin.h b/source/RobotAPI/libraries/skills/provider/SkillProviderComponentPlugin.h
index 9550dec64..e03d73e26 100644
--- a/source/RobotAPI/libraries/skills/provider/SkillProviderComponentPlugin.h
+++ b/source/RobotAPI/libraries/skills/provider/SkillProviderComponentPlugin.h
@@ -157,7 +157,28 @@ namespace armarx
         getSkillProviderPlugin() const;
 
     protected:
-        // utility
+        // -----------------------------------------------------------------------------------------
+        // LEGACY, TODO: NEEDS TESTING
+        // -----------------------------------------------------------------------------------------
+        template <class _Skill>
+
+        requires skills::isSkill<_Skill> skills::SkillFactory*
+        addSkill(std::unique_ptr<_Skill>&& s)
+        {
+            return addSkillFactory<_Skill>();
+        }
+
+        template <class _Skill, typename... Args>
+
+        requires skills::isSkill<_Skill> skills::SkillFactory*
+        addSkill(Args&&... args)
+        {
+            return addSkillFactory<_Skill>(std::forward<Args>(args)...);
+        }
+
+        // -----------------------------------------------------------------------------------------
+        // New
+        // -----------------------------------------------------------------------------------------
         skills::SkillFactory*
         addSkillFactory(const skills::SkillDescription& desc, const skills::LambdaSkill::FunT& f)
         {
diff --git a/source/RobotAPI/libraries/skills/provider/SpecializedSkill.h b/source/RobotAPI/libraries/skills/provider/SpecializedSkill.h
index 9fc2beba6..d551bd88d 100644
--- a/source/RobotAPI/libraries/skills/provider/SpecializedSkill.h
+++ b/source/RobotAPI/libraries/skills/provider/SpecializedSkill.h
@@ -17,16 +17,25 @@ namespace armarx
             using Base = Skill;
             using ParamType = AronT;
 
-            struct SpecializedMainInput
-            {
-                std::string executorName;
-                AronT params;
-                CallbackT callback;
-            };
-
             using Skill::Skill;
             virtual ~SpecializedSkill() = default;
 
+            void
+            setParameters(const AronT& d)
+            {
+                std::scoped_lock l(this->parametersMutex);
+                this->parameters = d;
+
+                Base::setParameters(d.toAron());
+            }
+
+            AronT
+            getParameters() const
+            {
+                std::scoped_lock l(this->parametersMutex);
+                return this->parameters;
+            }
+
             /// returns the accepted type of the skill
             static armarx::aron::type::ObjectPtr
             GetAcceptedType()
diff --git a/source/RobotAPI/libraries/skills/provider/detail/SkillImplementationWrapper.cpp b/source/RobotAPI/libraries/skills/provider/detail/SkillImplementationWrapper.cpp
index 6846cca66..41679d93a 100644
--- a/source/RobotAPI/libraries/skills/provider/detail/SkillImplementationWrapper.cpp
+++ b/source/RobotAPI/libraries/skills/provider/detail/SkillImplementationWrapper.cpp
@@ -5,22 +5,23 @@ namespace armarx
     namespace skills::detail
     {
         SkillImplementationWrapper::SkillImplementationWrapper(
-            const skills::SkillFactory* fac,
+            const skills::SkillFactory& fac,
             const skills::SkillExecutionID& execId,
             const skills::SkillParameterization& param) :
             factory(fac), statusUpdate(execId, param)
         {
-            ARMARX_CHECK_NOT_NULL(this->factory);
         }
 
         // ask a skill to stop
         void
         SkillImplementationWrapper::stopSkill()
         {
-            if (this->skill == nullptr)
+            while (this->skill == nullptr)
             {
-                // skill has not started yet.
-                return;
+                ARMARX_INFO << deactivateSpam()
+                            << "Trying to stop a skill that has not been constructed yet... "
+                               "Waiting until construction...";
+                std::this_thread::sleep_for(std::chrono::milliseconds(100));
             }
 
             this->skill->notifySkillToStopASAP();
@@ -29,10 +30,12 @@ namespace armarx
         void
         SkillImplementationWrapper::addSkillParameters(const aron::data::DictPtr& i)
         {
-            if (this->skill == nullptr)
+            while (this->skill == nullptr)
             {
-                // skill has not started yet
-                return;
+                ARMARX_INFO << deactivateSpam()
+                            << "Trying to add params to a skill that has not been constructed "
+                               "yet... Waiting until construction...";
+                std::this_thread::sleep_for(std::chrono::milliseconds(100));
             }
 
             this->skill->addParameters(i);
@@ -41,14 +44,10 @@ namespace armarx
         TerminatedSkillStatusUpdate
         SkillImplementationWrapper::executeSkill()
         {
+            std::scoped_lock l(this->executionMutex);
             // -------------------------------------------------------------------------------------
             // sanity check
             // -------------------------------------------------------------------------------------
-            ARMARX_CHECK(!has_been_called)
-                << "A SKILL HAS ALREADY BEEN CALLED. THIS SHOULD NOT HAPPEN!!";
-
-            has_been_called = true;
-
             ARMARX_CHECK(this->skill == nullptr)
                 << "A SKILL HAS ALREADY BEEN CONSTRUCTED. THIS SHOULD NOT HAPPEN!!";
 
@@ -59,12 +58,12 @@ namespace armarx
             // actually we should lock... however this is only read access and the members are const throughout the execution...
             ARMARX_CHECK(statusUpdate.executionId.skillId.fullySpecified());
 
-            const auto initial_aron_params = statusUpdate.usedParameterization.parameterization;
-            const auto callback_interface = statusUpdate.usedParameterization.callbackInterface;
-            const auto skillId = statusUpdate.executionId.skillId;
-            const auto skillName = skillId.skillName;
-            const auto providerId = *skillId.providerId;
-            const auto executorName = statusUpdate.executionId.executorName;
+            const auto& initial_aron_params = statusUpdate.usedParameterization.parameterization;
+            const auto& callback_interface = statusUpdate.usedParameterization.callbackInterface;
+            const auto& skillId = statusUpdate.executionId.skillId;
+            const auto& skillName = skillId.skillName;
+            const auto& providerId = *skillId.providerId;
+            const auto& executorName = statusUpdate.executionId.executorName;
 
             ARMARX_INFO_S << "Executing skill: " << skillName;
 
@@ -116,11 +115,17 @@ namespace armarx
             // construct skill
             // -------------------------------------------------------------------------------------
             updateStatus(SkillStatus::Constructing);
-            this->skill = this->factory->createSkill(providerId);
+            this->skill = this->factory.createSkill(providerId);
             this->skill->executorName = (executorName);
+            this->skill->manager = skills::manager::dti::SkillManagerInterfacePrx::checkedCast(
+                callback_interface); // ugly. Get managerPrx from manager!
+            ;
             this->skill->callback = [&](const SkillStatus s, const armarx::aron::data::DictPtr& d)
             { updateStatus(s, d); };
 
+            // set initial parameters that were attached to the execution request (only add as we are not sure whether some updates already arrived)
+            skill->addParameters(initial_aron_params);
+
 
             auto makeTerminationResult = [&](const std::string& message)
             {
@@ -185,9 +190,6 @@ namespace armarx
             try
             {
                 updateStatus(SkillStatus::Preparing);
-
-                // set initial parameters that were attached to the execution request
-                skill->addParameters(initial_aron_params);
                 auto prepareRet = skill->prepareSkill();
                 while (prepareRet.status == ActiveOrTerminatedSkillStatus::Running)
                 {
@@ -270,16 +272,17 @@ namespace armarx
 
 
             // All succeeded!
-            updateStatus(SkillStatus::Succeeded);
-
-            // return result of main method
-            std::unique_lock l(skillStatusesMutex);
-            TerminatedSkillStatusUpdate ret(statusUpdate.executionId,
-                                            statusUpdate.usedParameterization);
-            ret.data = mainRet.data;
-            ret.status = TerminatedSkillStatus::Succeeded;
+            {
+                updateStatus(SkillStatus::Succeeded);
 
-            return ret;
+                // return result of main method
+                std::unique_lock l(skillStatusesMutex);
+                TerminatedSkillStatusUpdate ret(statusUpdate.executionId,
+                                                statusUpdate.usedParameterization);
+                ret.data = mainRet.data;
+                ret.status = TerminatedSkillStatus::Succeeded;
+                return ret;
+            }
         }
     } // namespace skills::detail
 } // namespace armarx
diff --git a/source/RobotAPI/libraries/skills/provider/detail/SkillImplementationWrapper.h b/source/RobotAPI/libraries/skills/provider/detail/SkillImplementationWrapper.h
index c57a05485..45108724d 100644
--- a/source/RobotAPI/libraries/skills/provider/detail/SkillImplementationWrapper.h
+++ b/source/RobotAPI/libraries/skills/provider/detail/SkillImplementationWrapper.h
@@ -18,11 +18,10 @@ namespace armarx
             class SkillImplementationWrapper
             {
             private:
-                const skills::SkillFactory* factory;
+                const skills::SkillFactory& factory;
 
                 std::unique_ptr<Skill> skill;
-
-                std::atomic_bool has_been_called = false; // sanitize
+                mutable std::mutex executionMutex;
 
             public:
                 // Current execution statuses. Changes during execution
@@ -31,7 +30,7 @@ namespace armarx
                 SkillStatusUpdate statusUpdate;
 
                 // ctor
-                SkillImplementationWrapper(const skills::SkillFactory* fac,
+                SkillImplementationWrapper(const skills::SkillFactory& fac,
                                            const skills::SkillExecutionID&,
                                            const skills::SkillParameterization&);
 
@@ -39,9 +38,10 @@ namespace armarx
                 // the return type additionally contains the input configuration (similar to the status updates used in callbacks)
                 TerminatedSkillStatusUpdate executeSkill();
 
-                // ask a skill to stop
+                // ask a skill to stop. Must be concurrent to execute skill
                 void stopSkill();
 
+                // add parameters to a skill. Must be concurrent to execute skill
                 void addSkillParameters(const aron::data::DictPtr& i);
             };
         } // namespace detail
diff --git a/source/RobotAPI/libraries/skills/provider/legacy/SimpleSkill.cpp b/source/RobotAPI/libraries/skills/provider/legacy/SimpleSkill.cpp
deleted file mode 100644
index 3d4a52403..000000000
--- a/source/RobotAPI/libraries/skills/provider/legacy/SimpleSkill.cpp
+++ /dev/null
@@ -1,6 +0,0 @@
-#include "SimpleSkill.h"
-
-namespace armarx
-{
-
-}
diff --git a/source/RobotAPI/libraries/skills/provider/legacy/SimpleSkill.h b/source/RobotAPI/libraries/skills/provider/legacy/SimpleSkill.h
deleted file mode 100644
index 5872a11ed..000000000
--- a/source/RobotAPI/libraries/skills/provider/legacy/SimpleSkill.h
+++ /dev/null
@@ -1,15 +0,0 @@
-#pragma once
-
-namespace armarx
-{
-    namespace skills
-    {
-        class SimpleSKill
-        {
-        public:
-            SimpleSKill() = default;
-
-        private:
-        };
-    } // namespace skills
-} // namespace armarx
diff --git a/source/RobotAPI/libraries/skills/provider/legacy/SimpleSpecializedSkill.h b/source/RobotAPI/libraries/skills/provider/legacy/SimpleSpecializedSkill.h
deleted file mode 100644
index 06daeb741..000000000
--- a/source/RobotAPI/libraries/skills/provider/legacy/SimpleSpecializedSkill.h
+++ /dev/null
@@ -1,15 +0,0 @@
-#pragma once
-
-namespace armarx
-{
-    namespace skills
-    {
-        class SimpleSpecializedSkill
-        {
-        public:
-            SimpleSpecializedSkill() = default;
-
-        private:
-        };
-    } // namespace skills
-} // namespace armarx
-- 
GitLab