From 5634f09b5764b0e337efbfce9827398bf1939983 Mon Sep 17 00:00:00 2001
From: Fabian Peller-Konrad <fabian.peller-konrad@kit.edu>
Date: Tue, 27 Sep 2022 10:59:09 +0200
Subject: [PATCH] switched to armarx::duration for skill descriptions, force
 lambda skills to return a skillstatus, added return structs for init and exit

---
 .../SkillProviderExample.cpp                  | 15 +++---
 .../libraries/skills/provider/LambdaSkill.cpp |  8 +--
 .../libraries/skills/provider/LambdaSkill.h   |  2 +-
 .../libraries/skills/provider/Skill.cpp       | 12 ++---
 .../libraries/skills/provider/Skill.h         |  2 +-
 .../skills/provider/SkillDescription.cpp      |  7 +--
 .../skills/provider/SkillDescription.h        |  7 ++-
 .../skills/provider/SpecializedSkill.h        | 51 +++++++++++++------
 8 files changed, 59 insertions(+), 45 deletions(-)

diff --git a/source/RobotAPI/components/skills/SkillProviderExample/SkillProviderExample.cpp b/source/RobotAPI/components/skills/SkillProviderExample/SkillProviderExample.cpp
index 783821b06..bc50155ed 100644
--- a/source/RobotAPI/components/skills/SkillProviderExample/SkillProviderExample.cpp
+++ b/source/RobotAPI/components/skills/SkillProviderExample/SkillProviderExample.cpp
@@ -25,7 +25,7 @@ namespace armarx::skills::provider
             "HelloWorld",
             "This skill logs a message on ARMARX_IMPORTANT",
             {},
-            1000,
+            armarx::core::time::Duration::MilliSeconds(1000),
             armarx::skills::Example::HelloWorldAcceptedType::ToAronType(),
             default_params.toAron()
         };
@@ -50,7 +50,7 @@ namespace armarx::skills::provider
             "ChainingSkill",
             "This skill calls the HelloWorld skill three times.",
             {},
-            3000,
+            armarx::core::time::Duration::MilliSeconds(3000),
             nullptr
         };
     }
@@ -84,7 +84,7 @@ namespace armarx::skills::provider
             "Timeout",
             "This fails with timeout reached",
             {},
-            1000,
+            armarx::core::time::Duration::MilliSeconds(1000),
             nullptr
         };
     }
@@ -107,7 +107,7 @@ namespace armarx::skills::provider
             "ShowMeCallbacks",
             "This skill does shows callbacks",
             {},
-            1000,
+            armarx::core::time::Duration::MilliSeconds(1000),
             nullptr
         };
     }
@@ -157,8 +157,11 @@ namespace armarx::skills::provider
             fooDesc.acceptedType = nullptr; // accept everything
             fooDesc.description = "This skill does exactly nothing.";
             fooDesc.skillName = "Foo";
-            fooDesc.timeoutMs = 1000;
-            addSkill([](const std::string& clientId, const aron::data::DictPtr&){ std::cout << "Hello from Foo. The skill was called from " << clientId << "." << std::endl; return true; }, fooDesc);
+            fooDesc.timeout = armarx::core::time::Duration::MilliSeconds(1000);
+            addSkill([](const std::string& clientId, const aron::data::DictPtr&){
+                std::cout << "Hello from Foo. The skill was called from " << clientId << "." << std::endl;
+                return TerminatedSkillStatus::Succeeded;
+            }, fooDesc);
         }
 
         // Add another example skill
diff --git a/source/RobotAPI/libraries/skills/provider/LambdaSkill.cpp b/source/RobotAPI/libraries/skills/provider/LambdaSkill.cpp
index e922a69bb..280cdb93e 100644
--- a/source/RobotAPI/libraries/skills/provider/LambdaSkill.cpp
+++ b/source/RobotAPI/libraries/skills/provider/LambdaSkill.cpp
@@ -7,13 +7,9 @@ namespace armarx
 
         Skill::MainResult LambdaSkill::main(const MainInput& in)
         {
-            bool res = fun(in.executorName, in.params);
+            TerminatedSkillStatus res = fun(in.executorName, in.params);
 
-            if (res)
-            {
-                return {TerminatedSkillStatus::Succeeded, nullptr};
-            }
-            return {TerminatedSkillStatus::Failed, nullptr};
+            return {.status = res, .data = nullptr};
         }
     }
 }
diff --git a/source/RobotAPI/libraries/skills/provider/LambdaSkill.h b/source/RobotAPI/libraries/skills/provider/LambdaSkill.h
index e73206e45..01e3a3897 100644
--- a/source/RobotAPI/libraries/skills/provider/LambdaSkill.h
+++ b/source/RobotAPI/libraries/skills/provider/LambdaSkill.h
@@ -9,7 +9,7 @@ namespace armarx
         class LambdaSkill : public Skill
         {
         public:
-            using FunT = std::function<bool(const std::string clientId, const aron::data::DictPtr&)>;
+            using FunT = std::function<TerminatedSkillStatus(const std::string clientId, const aron::data::DictPtr&)>;
 
             LambdaSkill() = delete;
             LambdaSkill(const FunT& f, const SkillDescription& desc) :
diff --git a/source/RobotAPI/libraries/skills/provider/Skill.cpp b/source/RobotAPI/libraries/skills/provider/Skill.cpp
index 9cb924865..21b32da1a 100644
--- a/source/RobotAPI/libraries/skills/provider/Skill.cpp
+++ b/source/RobotAPI/libraries/skills/provider/Skill.cpp
@@ -62,7 +62,7 @@ namespace armarx
 
             // install timeout condition
             installConditionWithCallback(
-                        [&](){ return (armarx::core::time::DateTime::Now().toMilliSecondsSinceEpoch() - started.toMilliSecondsSinceEpoch()) >= description.timeoutMs; },
+                        [&](){ return (armarx::core::time::DateTime::Now() >= (started + description.timeout)); },
                         [&](){ notifyTimeoutReached(); }
             );
 
@@ -166,29 +166,29 @@ namespace armarx
         Skill::InitResult Skill::init(const InitInput&)
         {
             // Default nothing to init
-            return {TerminatedSkillStatus::Succeeded};
+            return {.status = TerminatedSkillStatus::Succeeded};
         }
 
         // always called after execute or if skill fails (should not take longer than 100ms)
         Skill::ExitResult Skill::exit(const ExitInput&)
         {
             // Default nothing to exit
-            return {TerminatedSkillStatus::Succeeded};
+            return {.status = TerminatedSkillStatus::Succeeded};
         }
 
         Skill::MainResult Skill::main(const MainInput& in)
         {
             // This is just a dummy implementation
             ARMARX_IMPORTANT << "Dummy executing skill '" << description.skillName << "'. Please overwrite this method.";
-            return {TerminatedSkillStatus::Succeeded, nullptr};
+            return {.status = TerminatedSkillStatus::Succeeded, .data = nullptr};
         }
 
         Skill::MainResult Skill::executeFullSkill(const MainInput& in)
         {
             this->resetSkill();
-            this->initSkill(InitInput{in.executorName, in.params});
+            this->initSkill(InitInput{.executorName = in.executorName, .params = in.params});
             auto ret = this->mainOfSkill(in);
-            this->exitSkill(ExitInput{in.executorName, in.params});
+            this->exitSkill(ExitInput{.executorName = in.executorName, .params = in.params});
             return ret;
         }
     }
diff --git a/source/RobotAPI/libraries/skills/provider/Skill.h b/source/RobotAPI/libraries/skills/provider/Skill.h
index 2152c1941..0522191bf 100644
--- a/source/RobotAPI/libraries/skills/provider/Skill.h
+++ b/source/RobotAPI/libraries/skills/provider/Skill.h
@@ -52,7 +52,7 @@ namespace armarx
             struct MainResult
             {
                 TerminatedSkillStatus status;
-                aron::data::DictPtr data;
+                aron::data::DictPtr data = nullptr;
             };
 
             struct ExitResult
diff --git a/source/RobotAPI/libraries/skills/provider/SkillDescription.cpp b/source/RobotAPI/libraries/skills/provider/SkillDescription.cpp
index 3256f3e11..4e195f39e 100644
--- a/source/RobotAPI/libraries/skills/provider/SkillDescription.cpp
+++ b/source/RobotAPI/libraries/skills/provider/SkillDescription.cpp
@@ -4,11 +4,6 @@ namespace armarx
 {
     namespace skills
     {
-        SkillDescription::SkillDescription(const std::string& name, const std::string& desc, const std::vector<std::string>& r, long timeoutMs, const aron::type::ObjectPtr& type, const aron::data::DictPtr& def) :
-            skillName(name), description(desc), robots(r), timeoutMs(timeoutMs), acceptedType(type), defaultParams(def)
-        {
-        }
-
         provider::dto::SkillDescription SkillDescription::toIce() const
         {
             provider::dto::SkillDescription ret;
@@ -16,7 +11,7 @@ namespace armarx
             ret.description = description;
             ret.skillName = skillName;
             ret.robots = robots;
-            ret.timeoutMs = timeoutMs;
+            ret.timeoutMs = timeout.toMilliSeconds();
             ret.defaultParams = aron::data::Dict::ToAronDictDTO(defaultParams);
             return ret;
         }
diff --git a/source/RobotAPI/libraries/skills/provider/SkillDescription.h b/source/RobotAPI/libraries/skills/provider/SkillDescription.h
index 0eaea7570..57c3c93b1 100644
--- a/source/RobotAPI/libraries/skills/provider/SkillDescription.h
+++ b/source/RobotAPI/libraries/skills/provider/SkillDescription.h
@@ -3,6 +3,8 @@
 #include <string>
 #include <vector>
 
+#include <ArmarXCore/core/time/Duration.h>
+
 #include <RobotAPI/interface/skills/SkillProviderInterface.h>
 #include <RobotAPI/libraries/aron/core/data/variant/container/Dict.h>
 #include <RobotAPI/libraries/aron/core/type/variant/container/Object.h>
@@ -16,13 +18,10 @@ namespace armarx
             std::string                        skillName = "NOT INITIALIZED YET";
             std::string                        description = "NOT INITIALIZED YET";
             std::vector<std::string>           robots = {};
-            long                               timeoutMs = -1;
+            armarx::core::time::Duration       timeout = armarx::core::time::Duration::MilliSeconds(-1);
             aron::type::ObjectPtr              acceptedType = nullptr;
             aron::data::DictPtr                defaultParams = nullptr;
 
-            SkillDescription() = default;
-            SkillDescription(const std::string&, const std::string&, const std::vector<std::string>&, long, const aron::type::ObjectPtr&, const aron::data::DictPtr& = nullptr);
-
             provider::dto::SkillDescription toIce() const;
         };
     }
diff --git a/source/RobotAPI/libraries/skills/provider/SpecializedSkill.h b/source/RobotAPI/libraries/skills/provider/SpecializedSkill.h
index 80752a235..9f554e11e 100644
--- a/source/RobotAPI/libraries/skills/provider/SpecializedSkill.h
+++ b/source/RobotAPI/libraries/skills/provider/SpecializedSkill.h
@@ -45,74 +45,95 @@ namespace armarx
                 return AronT::ToAronType();
             }
 
-            void initSkill(const SpecializedInitInput& in)
+            bool isSkillAvailable(const SpecializedInitInput& in) const
+            {
+                return this->isAvailable();
+            }
+
+            Skill::InitResult initSkill(const SpecializedInitInput& in)
             {
                 Skill::_init();
-                this->init(in);
+                return this->init(in);
             }
             Skill::MainResult mainOfSkill(const SpecializedMainInput& in)
             {
                 Skill::_main();
                 return this->main(in);
             }
-            void exitSkill(const SpecializedExitInput& in)
+            Skill::ExitResult exitSkill(const SpecializedExitInput& in)
             {
                 Skill::_exit();
-                this->exit(in);
+                return this->exit(in);
             }
 
             Skill::MainResult executeFullSkill(const SpecializedMainInput& in)
             {
                 this->resetSkill();
-                this->initSkill(SpecializedInitInput({in.executorName, in.params}));
+                this->initSkill(SpecializedInitInput({.executorName = in.executorName, .params = in.params}));
                 auto ret = this->mainOfSkill(in);
-                this->exit(SpecializedExitInput({in.executorName, in.params}));
+                this->exit(SpecializedExitInput({.executorName = in.executorName, .params = in.params}));
                 return ret;
             }
 
         private:
+            virtual bool isAvailable(const SpecializedInitInput&) const
+            {
+                return true;
+            }
+
             /// Override this method with the actual implementation. The callback is for status updates to the calling instance
-            virtual void init(const SpecializedInitInput&)
+            virtual Skill::InitResult init(const SpecializedInitInput&)
             {
+                return InitResult{.status = TerminatedSkillStatus::Succeeded};
             }
 
             /// Override this method with the actual implementation. The callback is for status updates to the calling instance
             virtual Skill::MainResult main(const SpecializedMainInput& in)
             {
                 ARMARX_IMPORTANT << "Dummy executing skill '" << description.skillName << "'. Please overwrite this method.";
-                return {TerminatedSkillStatus::Succeeded, nullptr};
+                return Skill::MainResult{.status = TerminatedSkillStatus::Succeeded, .data = nullptr};
             }
 
             /// Override this method with the actual implementation. The callback is for status updates to the calling instance
-            virtual void exit(const SpecializedExitInput&)
+            virtual Skill::ExitResult exit(const SpecializedExitInput&)
             {
+                return ExitResult{.status = TerminatedSkillStatus::Succeeded};
             }
 
             /// Do not use anymore
-            Skill::MainResult main(const MainInput& in) final
+            bool isAvailable(const InitInput& in) const final
             {
                 AronT p;
                 p.fromAron(in.params);
 
-                return main(SpecializedMainInput({in.executorName, p, in.callback}));
+                return isAvailable(SpecializedInitInput({.executorName = in.executorName, .params = p}));
             }
 
             /// Do not use anymore
-            void init(const InitInput& in) final
+            Skill::InitResult init(const InitInput& in) final
+            {
+                AronT p;
+                p.fromAron(in.params);
+
+                return init(SpecializedInitInput({.executorName = in.executorName, .params = p}));
+            }
+
+            /// Do not use anymore
+            Skill::MainResult main(const MainInput& in) final
             {
                 AronT p;
                 p.fromAron(in.params);
 
-                return init(SpecializedInitInput({in.executorName, p}));
+                return main(SpecializedMainInput({.executorName = in.executorName, .params = p, .callback = in.callback}));
             }
 
             /// Do not use anymore
-            void exit(const ExitInput& in) final
+            Skill::ExitResult exit(const ExitInput& in) final
             {
                 AronT p;
                 p.fromAron(in.params);
 
-                return exit(SpecializedExitInput({in.executorName, p}));
+                return exit(SpecializedExitInput({.executorName = in.executorName, .params = p}));
             }
         };
     }
-- 
GitLab