From 38288bc20e5c0131c6f547a4d13695694182191b Mon Sep 17 00:00:00 2001 From: Fabian Peller-Konrad <fabian.peller-konrad@kit.edu> Date: Thu, 2 Jun 2022 13:41:43 +0200 Subject: [PATCH] skill provider updates --- .../server/SkillsMemory/SkillsMemory.cpp | 4 +- .../armem/server/SkillsMemory/SkillsMemory.h | 2 +- .../SkillProviderExample.cpp | 9 +- .../SkillManagerMonitorWidgetController.cpp | 7 +- .../skills/SkillManagerInterface.ice | 9 +- .../skills/SkillProviderInterface.ice | 34 ++++--- .../libraries/armem_skills/aron/Skill.xml | 4 +- .../segment/ExecutableSkillLibrarySegment.cpp | 2 +- .../server/segment/SkillEventSegment.cpp | 8 +- .../segment/SkillExecutionRequestSegment.cpp | 6 +- .../segment/SkillExecutionRequestSegment.h | 4 +- .../RobotAPI/libraries/skills/CMakeLists.txt | 2 + .../libraries/skills/error/Exception.cpp | 2 + .../libraries/skills/error/Exception.h | 65 +++++++++++++ .../manager/SkillManagerComponentPlugin.cpp | 12 +-- .../manager/SkillManagerComponentPlugin.h | 6 +- .../libraries/skills/provider/Skill.h | 5 +- .../skills/provider/SkillDescription.cpp | 2 +- .../skills/provider/SkillDescription.h | 2 +- .../provider/SkillProviderComponentPlugin.cpp | 91 +++++++++++-------- .../provider/SkillProviderComponentPlugin.h | 11 ++- .../skills/provider/SkillStatusUpdate.cpp | 10 +- .../skills/provider/SkillStatusUpdate.h | 5 +- 23 files changed, 196 insertions(+), 106 deletions(-) create mode 100644 source/RobotAPI/libraries/skills/error/Exception.cpp create mode 100644 source/RobotAPI/libraries/skills/error/Exception.h diff --git a/source/RobotAPI/components/armem/server/SkillsMemory/SkillsMemory.cpp b/source/RobotAPI/components/armem/server/SkillsMemory/SkillsMemory.cpp index 3fbb33eac..d740b5f23 100644 --- a/source/RobotAPI/components/armem/server/SkillsMemory/SkillsMemory.cpp +++ b/source/RobotAPI/components/armem/server/SkillsMemory/SkillsMemory.cpp @@ -113,7 +113,7 @@ namespace armarx { ARMARX_CHECK_NOT_NULL(instance); - skills::manager::dto::SkillExecutionInfo exInfo = skillExecutionRequestCoreSegment.convertCommit(instance); + skills::manager::dto::SkillExecutionRequest exInfo = skillExecutionRequestCoreSegment.convertCommit(instance); SkillManagerComponentPluginUser::executeSkill(exInfo, current); } } @@ -138,7 +138,7 @@ namespace armarx SkillManagerComponentPluginUser::removeProvider(skillProviderName, current); } - void SkillsMemory::executeSkill(const skills::manager::dto::SkillExecutionInfo& info, const Ice::Current ¤t) + void SkillsMemory::executeSkill(const skills::manager::dto::SkillExecutionRequest& info, const Ice::Current ¤t) { skillExecutionRequestCoreSegment.addSkillExecutionRequest(info); SkillManagerComponentPluginUser::executeSkill(info, current); diff --git a/source/RobotAPI/components/armem/server/SkillsMemory/SkillsMemory.h b/source/RobotAPI/components/armem/server/SkillsMemory/SkillsMemory.h index d609be37f..a71fcb498 100644 --- a/source/RobotAPI/components/armem/server/SkillsMemory/SkillsMemory.h +++ b/source/RobotAPI/components/armem/server/SkillsMemory/SkillsMemory.h @@ -76,7 +76,7 @@ namespace armarx // Override SkillManager to add memory functions void addProvider(const skills::manager::dto::ProviderInfo& info, const Ice::Current ¤t) override; void removeProvider(const std::string&, const Ice::Current ¤t) override; - void executeSkill(const skills::manager::dto::SkillExecutionInfo& info, const Ice::Current ¤t) override; + void executeSkill(const skills::manager::dto::SkillExecutionRequest& info, const Ice::Current ¤t) override; void updateStatusForSkill(const skills::provider::dto::SkillStatusUpdate& statusUpdate, const Ice::Current ¤t) override; // WritingInterface interface diff --git a/source/RobotAPI/components/skills/SkillProviderExample/SkillProviderExample.cpp b/source/RobotAPI/components/skills/SkillProviderExample/SkillProviderExample.cpp index ab6944e97..cbfbc89cc 100644 --- a/source/RobotAPI/components/skills/SkillProviderExample/SkillProviderExample.cpp +++ b/source/RobotAPI/components/skills/SkillProviderExample/SkillProviderExample.cpp @@ -47,19 +47,18 @@ namespace armarx::skills::provider exec2.some_text = "Hello from the ChainingSkill 2"; exec3.some_text = "Hello from the ChainingSkill 3"; - manager::dto::SkillExecutionInfo exec; + manager::dto::SkillExecutionRequest exec; exec.providerName = "SkillProviderExample"; exec.skillName = "HelloWorld"; - exec.waitUntilSkillFinished = false; exec.params = exec1.toAron()->toAronDictDTO(); - ownerManager->executeSkill(exec); + manager->executeSkill(exec); exec.params = exec2.toAron()->toAronDictDTO(); - ownerManager->executeSkill(exec); + manager->executeSkill(exec); exec.params = exec3.toAron()->toAronDictDTO(); - ownerManager->executeSkill(exec); + manager->executeSkill(exec); return Skill::Status::Succeeded; } diff --git a/source/RobotAPI/gui-plugins/SkillManagerPlugin/SkillManagerMonitorWidgetController.cpp b/source/RobotAPI/gui-plugins/SkillManagerPlugin/SkillManagerMonitorWidgetController.cpp index e9942f7ec..c29af8fca 100644 --- a/source/RobotAPI/gui-plugins/SkillManagerPlugin/SkillManagerMonitorWidgetController.cpp +++ b/source/RobotAPI/gui-plugins/SkillManagerPlugin/SkillManagerMonitorWidgetController.cpp @@ -238,7 +238,7 @@ namespace armarx auto& providerPrx = skills.at(providerName).skillProviderPrx; auto statusUpdate = providerPrx->getSkillExecutionStatus(skillName); - skillItem->setText(2, QString::fromStdString(ExecutionStatus2String.at(statusUpdate.status))); + skillItem->setText(2, QString::fromStdString(ExecutionStatus2String.at(statusUpdate.header.status))); } } catch (const std::exception& e) @@ -265,8 +265,7 @@ namespace armarx auto data = getConfigAsAron(); - skills::manager::dto::SkillExecutionInfo exInfo; - exInfo.waitUntilSkillFinished = false; + skills::manager::dto::SkillExecutionRequest exInfo; exInfo.providerName = selectedSkill.providerName; exInfo.skillName = selectedSkill.skillName; exInfo.params = aron::data::Dict::ToAronDictDTO(data); @@ -341,7 +340,7 @@ namespace armarx { auto it = new QTreeWidgetItem(widget.treeWidgetSkillDetails, - {QString::fromStdString("Robot"), QString::fromStdString(simox::alg::join(skillDesc.targets, ", "))}); + {QString::fromStdString("Robot"), QString::fromStdString(simox::alg::join(skillDesc.robots, ", "))}); widget.treeWidgetSkillDetails->addTopLevelItem(it); } diff --git a/source/RobotAPI/interface/skills/SkillManagerInterface.ice b/source/RobotAPI/interface/skills/SkillManagerInterface.ice index 9f6bd7314..e35bb3e34 100644 --- a/source/RobotAPI/interface/skills/SkillManagerInterface.ice +++ b/source/RobotAPI/interface/skills/SkillManagerInterface.ice @@ -34,12 +34,11 @@ module armarx module dto { // Inputs - struct SkillExecutionInfo + struct SkillExecutionRequest { string providerName; string skillName; aron::data::dto::Dict params; - bool waitUntilSkillFinished; }; struct ProviderInfo @@ -48,6 +47,8 @@ module armarx provider::dti::SkillProviderInterface* provider; provider::dto::SkillDescriptionMap providedSkills; }; + + dictionary<string, provider::dto::SkillDescriptionMap> SkillDescriptionMapMap; } module dti @@ -56,8 +57,8 @@ module armarx { void addProvider(dto::ProviderInfo providerInfo); void removeProvider(string providerName); - provider::dti::SkillProviderMap getSkillProviders(); - void executeSkill(dto::SkillExecutionInfo skillExecutionInfo); + dto::SkillDescriptionMapMap getSkillDescriptions(); + void executeSkill(dto::SkillExecutionRequest skillExecutionInfo); void abortSkill(string providerName, string skillName); }; } diff --git a/source/RobotAPI/interface/skills/SkillProviderInterface.ice b/source/RobotAPI/interface/skills/SkillProviderInterface.ice index c6eec5736..b21e5135e 100644 --- a/source/RobotAPI/interface/skills/SkillProviderInterface.ice +++ b/source/RobotAPI/interface/skills/SkillProviderInterface.ice @@ -51,24 +51,24 @@ module armarx sequence<string> StringList; // Description of a skill. Needs to be sent to a skill manager or memory - // A skill is nothing but a executable thing, which can be executed on one or more 'targets' (empty means all) + // A skill is nothing but a executable thing, which can be executed on one or more 'robots' (empty means all) struct SkillDescription { string skillName; // the name of the skill string description; // a human readable description of what the skill does - StringList targets; // see above + StringList robots; // see above long timeoutMs; // in milliseconds aron::type::dto::AronObject acceptedType; // the name of the object is irrelevant and only used in GUI }; dictionary<string, SkillDescription> SkillDescriptionMap; // Inputs - struct SkillExecutionInfo + struct SkillExecutionRequest { string skillName; + string requesterName; aron::data::dto::Dict params; callback::dti::SkillProviderCallbackInterface* callbackInterface; // use nullptr if you do not want to have callbacks - bool waitUntilSkillFinished; }; // The status enum of a skill @@ -76,7 +76,7 @@ module armarx { enum Status { - Idle, + Idle, // a skill can only be idled if it has never been scheduled Scheduled, Running, @@ -88,13 +88,18 @@ module armarx } // Status updates of a skill - struct SkillStatusUpdate + struct SkillStatusUpdateHeader { - string providerName; + string providerName; // the name of the provider the skill is currently running on string skillName; aron::data::dto::Dict usedParams; callback::dti::SkillProviderCallbackInterface* usedCallbackInterface; Execution::Status status; + }; + + struct SkillStatusUpdate + { + SkillStatusUpdateHeader header; aron::data::dto::Dict data; // can be anything }; @@ -106,13 +111,18 @@ module armarx interface SkillProviderInterface { - dto::SkillDescriptionMap getSkills(); + dto::SkillDescription getSkillDescription(string name); + dto::SkillDescriptionMap getSkillDescriptions(); dto::SkillStatusUpdate getSkillExecutionStatus(string name); - void executeSkill(dto::SkillExecutionInfo executionInfo); - void abortSkill(string skill, bool waitUntilSkillFinished); - }; + dto::SkillStatusUpdateMap getSkillExecutionStatuses(); - dictionary<string, SkillProviderInterface*> SkillProviderMap; + // execute skill will ALWAYS fully execute the skill and wait, until the skill is finished. + // Use the _begin() method, if you want to call a skill async + void executeSkill(dto::SkillExecutionRequest executionInfo); + + // try to kill a skill as soon as possible. When the skill is stopped depends on the implementation. + void abortSkill(string skill); + }; } } } diff --git a/source/RobotAPI/libraries/armem_skills/aron/Skill.xml b/source/RobotAPI/libraries/armem_skills/aron/Skill.xml index b546afb89..b84f79b64 100644 --- a/source/RobotAPI/libraries/armem_skills/aron/Skill.xml +++ b/source/RobotAPI/libraries/armem_skills/aron/Skill.xml @@ -16,7 +16,7 @@ The memory should look like the following: <String /> </ObjectChild> - <ObjectChild key='targets'> + <ObjectChild key='robots'> <List> <String /> </List> @@ -35,7 +35,7 @@ The memory should look like the following: </ObjectChild> <ObjectChild key='acceptedType'> - <string /> + <string /> <!-- TODO REPLACE! --> </ObjectChild> </Object> diff --git a/source/RobotAPI/libraries/armem_skills/server/segment/ExecutableSkillLibrarySegment.cpp b/source/RobotAPI/libraries/armem_skills/server/segment/ExecutableSkillLibrarySegment.cpp index 745968174..ec84a4f91 100644 --- a/source/RobotAPI/libraries/armem_skills/server/segment/ExecutableSkillLibrarySegment.cpp +++ b/source/RobotAPI/libraries/armem_skills/server/segment/ExecutableSkillLibrarySegment.cpp @@ -37,7 +37,7 @@ namespace armarx::skills::segment skillDescription.skillName = desc.skillName; skillDescription.description = desc.description; skillDescription.iceInfo = info.provider->ice_toString(); - skillDescription.targets = desc.targets; + skillDescription.robots = desc.robots; skillDescription.timeoutMs = desc.timeoutMs; if (desc.acceptedType) diff --git a/source/RobotAPI/libraries/armem_skills/server/segment/SkillEventSegment.cpp b/source/RobotAPI/libraries/armem_skills/server/segment/SkillEventSegment.cpp index af8af24c2..0181e2729 100644 --- a/source/RobotAPI/libraries/armem_skills/server/segment/SkillEventSegment.cpp +++ b/source/RobotAPI/libraries/armem_skills/server/segment/SkillEventSegment.cpp @@ -39,10 +39,10 @@ namespace armarx::skills::segment // create commit about new update armarx::skills::arondto::SkillExecutionEvent event; - event.providerName = update.providerName; - event.skillName = update.skillName; - event.status = ExecutionStatus2String.at(update.status); - event.params = aron::data::Dict::FromAronDictDTO(update.usedParams); + event.providerName = update.header.providerName; + event.skillName = update.header.skillName; + event.status = ExecutionStatus2String.at(update.header.status); + event.params = aron::data::Dict::FromAronDictDTO(update.header.usedParams); event.data = aron::data::Dict::FromAronDictDTO(update.data); armem::MemoryID commitId = id(); diff --git a/source/RobotAPI/libraries/armem_skills/server/segment/SkillExecutionRequestSegment.cpp b/source/RobotAPI/libraries/armem_skills/server/segment/SkillExecutionRequestSegment.cpp index 9c43b717a..8a60cb668 100644 --- a/source/RobotAPI/libraries/armem_skills/server/segment/SkillExecutionRequestSegment.cpp +++ b/source/RobotAPI/libraries/armem_skills/server/segment/SkillExecutionRequestSegment.cpp @@ -27,7 +27,7 @@ namespace armarx::skills::segment } - skills::manager::dto::SkillExecutionInfo SkillExecutionRequestCoreSegment::convertCommit(const aron::data::dto::DictPtr& commitData) + skills::manager::dto::SkillExecutionRequest SkillExecutionRequestCoreSegment::convertCommit(const aron::data::dto::DictPtr& commitData) { // convert ice commitData to aron auto commitDataAron = std::make_shared<aron::data::Dict>(commitData); @@ -36,7 +36,7 @@ namespace armarx::skills::segment skills::arondto::SkillExecutionRequest request; request.fromAron(commitDataAron); - skills::manager::dto::SkillExecutionInfo info; + skills::manager::dto::SkillExecutionRequest info; info.providerName = request.providerName; info.skillName = request.skillName; info.params = request.params->toAronDictDTO(); @@ -44,7 +44,7 @@ namespace armarx::skills::segment } - void SkillExecutionRequestCoreSegment::addSkillExecutionRequest(const skills::manager::dto::SkillExecutionInfo& info) + void SkillExecutionRequestCoreSegment::addSkillExecutionRequest(const skills::manager::dto::SkillExecutionRequest& info) { // override directly execution to add a request to the memory armem::Commit comm; diff --git a/source/RobotAPI/libraries/armem_skills/server/segment/SkillExecutionRequestSegment.h b/source/RobotAPI/libraries/armem_skills/server/segment/SkillExecutionRequestSegment.h index 08b6f6b56..262bc829b 100644 --- a/source/RobotAPI/libraries/armem_skills/server/segment/SkillExecutionRequestSegment.h +++ b/source/RobotAPI/libraries/armem_skills/server/segment/SkillExecutionRequestSegment.h @@ -26,8 +26,8 @@ namespace armarx::skills::segment void defineProperties(PropertyDefinitionsPtr defs, const std::string &prefix); void init(); - skills::manager::dto::SkillExecutionInfo convertCommit(const aron::data::dto::DictPtr& commitData); + skills::manager::dto::SkillExecutionRequest convertCommit(const aron::data::dto::DictPtr& commitData); - void addSkillExecutionRequest(const skills::manager::dto::SkillExecutionInfo& info); + void addSkillExecutionRequest(const skills::manager::dto::SkillExecutionRequest& info); }; } diff --git a/source/RobotAPI/libraries/skills/CMakeLists.txt b/source/RobotAPI/libraries/skills/CMakeLists.txt index bbf9d1d35..7368c8d63 100644 --- a/source/RobotAPI/libraries/skills/CMakeLists.txt +++ b/source/RobotAPI/libraries/skills/CMakeLists.txt @@ -12,6 +12,7 @@ armarx_add_library( RobotAPI::Core aronjsonconverter SOURCES + ./error/Exception.cpp ./manager/SkillManagerComponentPlugin.cpp ./provider/SkillProviderComponentPlugin.cpp ./provider/Skill.cpp @@ -24,6 +25,7 @@ armarx_add_library( ./provider/helper/LambdaSkillImplementation.cpp ./provider/detail/SkillImplementationWrapper.cpp HEADERS + ./error/Exception.h ./manager/SkillManagerComponentPlugin.h ./provider/SkillProviderComponentPlugin.h ./provider/Skill.h diff --git a/source/RobotAPI/libraries/skills/error/Exception.cpp b/source/RobotAPI/libraries/skills/error/Exception.cpp new file mode 100644 index 000000000..32521fede --- /dev/null +++ b/source/RobotAPI/libraries/skills/error/Exception.cpp @@ -0,0 +1,2 @@ + +#include "Exception.h" diff --git a/source/RobotAPI/libraries/skills/error/Exception.h b/source/RobotAPI/libraries/skills/error/Exception.h new file mode 100644 index 000000000..b73ccbf1e --- /dev/null +++ b/source/RobotAPI/libraries/skills/error/Exception.h @@ -0,0 +1,65 @@ +/* + * This file is part of ArmarX. + * + * Copyright (C) 2012-2016, High Performance Humanoid Technologies (H2T), + * Karlsruhe Institute of Technology (KIT), all rights reserved. + * + * 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 Peller-Konrad (fabian dot peller-konrad at kit dot edu) + * @copyright http://www.gnu.org/licenses/gpl-2.0.txt + * GNU General Public License + */ + +#pragma once + +// STD/STL +#include <string> +#include <vector> +#include <map> + +// ArmarX +#include <ArmarXCore/core/exceptions/local/ExpressionException.h> +#include <ArmarXCore/core/exceptions/Exception.h> + + +namespace armarx::skills::error +{ + /** + * @brief A base class for aron exceptions. All aron exceptions inherit from this class + */ + class SkillException : + public armarx::LocalException + { + public: + SkillException() = delete; + SkillException(const std::string& prettymethod, const std::string& reason) : + LocalException(prettymethod + ": " + reason + ".") + { + } + }; + + /** + * @brief The NotImplementedYetException class + */ + class NotImplementedYetException : + public SkillException + { + public: + NotImplementedYetException() = delete; + NotImplementedYetException(const std::string& prettymethod) : + SkillException(prettymethod, "This method is not yet implemented!") + { + } + }; +} diff --git a/source/RobotAPI/libraries/skills/manager/SkillManagerComponentPlugin.cpp b/source/RobotAPI/libraries/skills/manager/SkillManagerComponentPlugin.cpp index 1b97951eb..76347bf5a 100644 --- a/source/RobotAPI/libraries/skills/manager/SkillManagerComponentPlugin.cpp +++ b/source/RobotAPI/libraries/skills/manager/SkillManagerComponentPlugin.cpp @@ -50,23 +50,17 @@ namespace armarx } } - skills::provider::dti::SkillProviderMap SkillManagerComponentPluginUser::getSkillProviders(const Ice::Current&) - { - return skillProviderMap; - } - - void SkillManagerComponentPluginUser::executeSkill(const skills::manager::dto::SkillExecutionInfo& info, const Ice::Current&) + void SkillManagerComponentPluginUser::executeSkill(const skills::manager::dto::SkillExecutionRequest& info, const Ice::Current&) { if (auto it = skillProviderMap.find(info.providerName); it != skillProviderMap.end()) { skills::callback::dti::SkillProviderCallbackInterfacePrx myPrx; getProxy(myPrx, -1); - skills::provider::dto::SkillExecutionInfo exInfo; + skills::provider::dto::SkillExecutionRequest exInfo; exInfo.skillName = info.skillName; exInfo.callbackInterface = myPrx; exInfo.params = info.params; - exInfo.waitUntilSkillFinished = info.waitUntilSkillFinished; it->second->executeSkill(exInfo); } @@ -80,7 +74,7 @@ namespace armarx { if (auto it = skillProviderMap.find(providerName); it != skillProviderMap.end()) { - it->second->abortSkill(skillName, false); + it->second->abortSkill(skillName); } } diff --git a/source/RobotAPI/libraries/skills/manager/SkillManagerComponentPlugin.h b/source/RobotAPI/libraries/skills/manager/SkillManagerComponentPlugin.h index 5c59564f6..ba27d2bc1 100644 --- a/source/RobotAPI/libraries/skills/manager/SkillManagerComponentPlugin.h +++ b/source/RobotAPI/libraries/skills/manager/SkillManagerComponentPlugin.h @@ -33,8 +33,8 @@ namespace armarx void addProvider(const skills::manager::dto::ProviderInfo& providerInfo, const Ice::Current ¤t) override; void removeProvider(const std::string&, const Ice::Current ¤t) override; - skills::provider::dti::SkillProviderMap getSkillProviders(const Ice::Current ¤t) override; - void executeSkill(const skills::manager::dto::SkillExecutionInfo& info, const Ice::Current ¤t) override; + + void executeSkill(const skills::manager::dto::SkillExecutionRequest& info, const Ice::Current ¤t) override; void updateStatusForSkill(const skills::provider::dto::SkillStatusUpdate& update, const Ice::Current ¤t) override; void abortSkill(const std::string& providerName, const std::string& skillName, const Ice::Current ¤t) override; @@ -43,6 +43,6 @@ namespace armarx protected: std::mutex skillProviderMapMutex; - skills::provider::dti::SkillProviderMap skillProviderMap; + std::map<std::string, skills::provider::dti::SkillProviderInterfacePrx> skillProviderMap; }; } diff --git a/source/RobotAPI/libraries/skills/provider/Skill.h b/source/RobotAPI/libraries/skills/provider/Skill.h index d4fe0e5cf..90a923ce3 100644 --- a/source/RobotAPI/libraries/skills/provider/Skill.h +++ b/source/RobotAPI/libraries/skills/provider/Skill.h @@ -69,11 +69,10 @@ namespace armarx IceUtil::Time exited = IceUtil::Time::milliSeconds(-1); /// proxies that called the skills. Will be set from provider and is const afterwards - provider::dti::SkillProviderInterfacePrx ownerProvider = nullptr; - manager::dti::SkillManagerInterfacePrx ownerManager = nullptr; + manager::dti::SkillManagerInterfacePrx manager = nullptr; protected: - /// Use conditions during runtime this way + /// Use conditions managerme this way std::atomic_bool running = true; std::atomic_bool stopped = false; std::atomic_bool timeoutReached = false; diff --git a/source/RobotAPI/libraries/skills/provider/SkillDescription.cpp b/source/RobotAPI/libraries/skills/provider/SkillDescription.cpp index 5295057be..547cb389c 100644 --- a/source/RobotAPI/libraries/skills/provider/SkillDescription.cpp +++ b/source/RobotAPI/libraries/skills/provider/SkillDescription.cpp @@ -10,7 +10,7 @@ namespace armarx ret.acceptedType = aron::type::Object::ToAronObjectDTO(acceptedType); ret.description = description; ret.skillName = skillName; - ret.targets = targets; + ret.robots = robots; ret.timeoutMs = timeoutMs; return ret; } diff --git a/source/RobotAPI/libraries/skills/provider/SkillDescription.h b/source/RobotAPI/libraries/skills/provider/SkillDescription.h index 2bf9707c2..70b294b11 100644 --- a/source/RobotAPI/libraries/skills/provider/SkillDescription.h +++ b/source/RobotAPI/libraries/skills/provider/SkillDescription.h @@ -14,7 +14,7 @@ namespace armarx { std::string skillName; std::string description; - std::vector<std::string> targets; + std::vector<std::string> robots; long timeoutMs; aron::type::ObjectPtr acceptedType; diff --git a/source/RobotAPI/libraries/skills/provider/SkillProviderComponentPlugin.cpp b/source/RobotAPI/libraries/skills/provider/SkillProviderComponentPlugin.cpp index 638de458a..a17411d10 100644 --- a/source/RobotAPI/libraries/skills/provider/SkillProviderComponentPlugin.cpp +++ b/source/RobotAPI/libraries/skills/provider/SkillProviderComponentPlugin.cpp @@ -25,8 +25,7 @@ namespace armarx::plugins // update skill ownership for (auto& [skillName, impl] : p.skillImplementations) { - impl.skill->ownerProvider = myPrx; - impl.skill->ownerManager = ownedBySkillManager; + impl.skill->manager = manager; impl.statusUpdate.providerName = p.getName(); impl.statusUpdate.skillName = skillName; @@ -36,8 +35,8 @@ namespace armarx::plugins skills::manager::dto::ProviderInfo i; i.provider = myPrx; i.providerName = providerName; - i.providedSkills = p.getSkills(); - ownedBySkillManager->addProvider(i); + i.providedSkills = p.getSkillDescriptions(); + manager->addProvider(i); p.connected = true; } @@ -47,13 +46,13 @@ namespace armarx::plugins auto& p = parent<SkillProviderComponentPluginUser>(); std::string providerName = p.getName(); - ownedBySkillManager->removeProvider(providerName); + manager->removeProvider(providerName); } void SkillProviderComponentPlugin::postCreatePropertyDefinitions(PropertyDefinitionsPtr& properties) { std::string prefix = "skill."; - properties->component(ownedBySkillManager, "SkillMemory", prefix + "SkillManager", "The name of the SkillManager (or SkillMemory) proxy this provider belongs to."); + properties->component(manager, "SkillMemory", prefix + "SkillManager", "The name of the SkillManager (or SkillMemory) proxy this provider belongs to."); } } @@ -72,15 +71,15 @@ namespace armarx return; } + std::string skillName = skill->description.skillName; if (connected) { - ARMARX_WARNING << "The SkillProvider already registered to a manager. The skill '" + skill->description.skillName + "' therefore cannot be added anymore."; + ARMARX_WARNING << "The SkillProvider already registered to a manager. The skill '" + skillName + "' therefore cannot be added anymore. Please only add skills in the onInit method."; return; } + // lock skills map std::unique_lock l(skillsMutex); - - std::string skillName = skill->description.skillName; if (skillImplementations.find(skillName) != skillImplementations.end()) { ARMARX_WARNING << "Try to add a skill '" + skillName + "' which already exists in list. Ignoring this skill."; @@ -97,7 +96,14 @@ namespace armarx addSkill(std::move(lambda)); } - skills::provider::dto::SkillDescriptionMap SkillProviderComponentPluginUser::getSkills(const Ice::Current ¤t) + skills::provider::dto::SkillDescription SkillProviderComponentPluginUser::getSkillDescription(const std::string& name, const Ice::Current &) + { + std::shared_lock l(skillsMutex); + const auto& skillWrapper = skillImplementations.at(name); + return skillWrapper.skill->description.toIce(); + } + + skills::provider::dto::SkillDescriptionMap SkillProviderComponentPluginUser::getSkillDescriptions(const Ice::Current &) { std::shared_lock l(skillsMutex); skills::provider::dto::SkillDescriptionMap skillDesciptions; @@ -108,7 +114,7 @@ namespace armarx return skillDesciptions; } - skills::provider::dto::SkillStatusUpdate SkillProviderComponentPluginUser::getSkillExecutionStatus(const std::string& skill, const Ice::Current ¤t) + skills::provider::dto::SkillStatusUpdate SkillProviderComponentPluginUser::getSkillExecutionStatus(const std::string& skill, const Ice::Current &) { std::shared_lock l(skillsMutex); auto& skillWrapper = skillImplementations.at(skill); @@ -117,47 +123,54 @@ namespace armarx return skillWrapper.statusUpdate.toIce(); } - // Please not that this method waits until the skill can be scheduled! - void SkillProviderComponentPluginUser::executeSkill(const skills::provider::dto::SkillExecutionInfo& info, const Ice::Current ¤t) + skills::provider::dto::SkillStatusUpdateMap SkillProviderComponentPluginUser::getSkillExecutionStatuses(const Ice::Current &) { std::shared_lock l(skillsMutex); - std::string skillName = info.skillName; - ARMARX_CHECK_EXPRESSION(skillImplementations.count(skillName) > 0); - - auto& wrapper = skillImplementations.at(skillName); - - skills::SkillParameterization usedParameterization; - usedParameterization.usedCallbackInterface = info.callbackInterface; - usedParameterization.usedInputParams = aron::data::Dict::FromAronDictDTO(info.params); - - // We have to wait until the last task is finished - if (wrapper.task.joinable()) + skills::provider::dto::SkillStatusUpdateMap skillUpdates; + for (const auto& [key, skillWrapper] : skillImplementations) { - wrapper.task.join(); + std::shared_lock l2(skillWrapper.skillStatusMutex); + skillUpdates.insert({key, skillWrapper.statusUpdate.toIce()}); } + return skillUpdates; + } - // recreate thread and execute skill. A skill can only be executed once - wrapper.task = std::thread{ [&] { wrapper.execute(usedParameterization);}}; - std::this_thread::sleep_for(std::chrono::milliseconds(50)); // somehow we need to wait, otherwise it chrashes - - - if (info.waitUntilSkillFinished && wrapper.task.joinable()) + // Please not that this method waits until the skill can be scheduled! + void SkillProviderComponentPluginUser::executeSkill(const skills::provider::dto::SkillExecutionRequest& info, const Ice::Current &) + { + std::thread execution; + { + std::shared_lock l(skillsMutex); + std::string skillName = info.skillName; + ARMARX_CHECK_EXPRESSION(skillImplementations.count(skillName) > 0); + + // get reference of the wrapper + auto& wrapper = skillImplementations.at(skillName); + + // setup input args + skills::SkillParameterization usedParameterization; + usedParameterization.usedCallbackInterface = info.callbackInterface; + usedParameterization.usedInputParams = aron::data::Dict::FromAronDictDTO(info.params); + + // async start execution. But we wait for the execution to finish at the end of this method + execution = std::thread([&](){ + // execute waits until the previous execution finishes. + wrapper.execute(usedParameterization); + }); + } // release lock. We don't know how long the skill needs to finish and we have to releasethe lock for being able to abort the execution + + if(execution.joinable()) { - // wait until task is finished. We hold the shared lock for the whole time. - wrapper.task.join(); + execution.join(); } } - void SkillProviderComponentPluginUser::abortSkill(const std::string& skillName, bool waitUntilSkillFinished, const Ice::Current ¤t) + void SkillProviderComponentPluginUser::abortSkill(const std::string& skillName, const Ice::Current &) { std::shared_lock l(skillsMutex); ARMARX_CHECK_EXPRESSION(skillImplementations.count(skillName) > 0); auto& wrapper = skillImplementations.at(skillName); - if (waitUntilSkillFinished && !wrapper.skill->stopRequested() && wrapper.task.joinable()) - { - wrapper.skill->notifyStopped(); - wrapper.task.join(); - } + wrapper.skill->notifyStopped(); } } diff --git a/source/RobotAPI/libraries/skills/provider/SkillProviderComponentPlugin.h b/source/RobotAPI/libraries/skills/provider/SkillProviderComponentPlugin.h index 58895250b..a96960095 100644 --- a/source/RobotAPI/libraries/skills/provider/SkillProviderComponentPlugin.h +++ b/source/RobotAPI/libraries/skills/provider/SkillProviderComponentPlugin.h @@ -33,7 +33,7 @@ namespace armarx::plugins void preOnDisconnectComponent() override; private: - skills::manager::dti::SkillManagerInterfacePrx ownedBySkillManager; + skills::manager::dti::SkillManagerInterfacePrx manager; skills::provider::dti::SkillProviderInterfacePrx myPrx; }; } @@ -47,10 +47,13 @@ namespace armarx public: SkillProviderComponentPluginUser(); - skills::provider::dto::SkillDescriptionMap getSkills(const Ice::Current ¤t = Ice::Current()) override; + skills::provider::dto::SkillDescription getSkillDescription(const std::string&, const Ice::Current ¤t = Ice::Current()) override; + skills::provider::dto::SkillDescriptionMap getSkillDescriptions(const Ice::Current ¤t = Ice::Current()) override; skills::provider::dto::SkillStatusUpdate getSkillExecutionStatus(const std::string& skill, const Ice::Current ¤t = Ice::Current()) override; - void executeSkill(const skills::provider::dto::SkillExecutionInfo& executionInfo, const Ice::Current ¤t = Ice::Current()) override; - void abortSkill(const std::string &skill, bool waitUntilSkillFinished, const Ice::Current ¤t = Ice::Current()) override; + skills::provider::dto::SkillStatusUpdateMap getSkillExecutionStatuses(const Ice::Current ¤t = Ice::Current()) override; + + void executeSkill(const skills::provider::dto::SkillExecutionRequest& executionInfo, const Ice::Current ¤t = Ice::Current()) override; + void abortSkill(const std::string& name, const Ice::Current ¤t = Ice::Current()) override; protected: void addSkill(const skills::helper::LambdaSkill::FunT&, const skills::SkillDescription&); diff --git a/source/RobotAPI/libraries/skills/provider/SkillStatusUpdate.cpp b/source/RobotAPI/libraries/skills/provider/SkillStatusUpdate.cpp index eb98bb0b0..fa9695b62 100644 --- a/source/RobotAPI/libraries/skills/provider/SkillStatusUpdate.cpp +++ b/source/RobotAPI/libraries/skills/provider/SkillStatusUpdate.cpp @@ -7,12 +7,12 @@ namespace armarx provider::dto::SkillStatusUpdate SkillStatusUpdate::toIce() const { provider::dto::SkillStatusUpdate ret; - ret.providerName = providerName; - ret.skillName = skillName; + ret.header.providerName = providerName; + ret.header.skillName = skillName; ret.data = aron::data::Dict::ToAronDictDTO(data); - ret.status = status; - ret.usedCallbackInterface = usedParameterization.usedCallbackInterface; - ret.usedParams = aron::data::Dict::ToAronDictDTO(usedParameterization.usedInputParams); + ret.header.status = status; + ret.header.usedCallbackInterface = usedParameterization.usedCallbackInterface; + ret.header.usedParams = aron::data::Dict::ToAronDictDTO(usedParameterization.usedInputParams); return ret; } } diff --git a/source/RobotAPI/libraries/skills/provider/SkillStatusUpdate.h b/source/RobotAPI/libraries/skills/provider/SkillStatusUpdate.h index 2b69c7e5d..41a138832 100644 --- a/source/RobotAPI/libraries/skills/provider/SkillStatusUpdate.h +++ b/source/RobotAPI/libraries/skills/provider/SkillStatusUpdate.h @@ -14,12 +14,15 @@ namespace armarx { struct SkillStatusUpdate { + // header std::string providerName = ""; std::string skillName = ""; provider::dto::Execution::Status status = provider::dto::Execution::Status::Idle; - aron::data::DictPtr data = nullptr; SkillParameterization usedParameterization; + // data + aron::data::DictPtr data = nullptr; + provider::dto::SkillStatusUpdate toIce() const; }; } -- GitLab