From 847fe14ba8862cc30c95ca610cc5a90b3e853e83 Mon Sep 17 00:00:00 2001 From: Fabian Peller <fabian.peller-konrad@kit.edu> Date: Wed, 4 Oct 2023 16:45:39 +0200 Subject: [PATCH] finished implementation of updated skill api. Works with example skill provider. Needs testing of specialized skills and refactoring of remaining skills. --- .../server/SkillsMemory/SkillsMemory.cpp | 28 +- .../armem/server/SkillsMemory/SkillsMemory.h | 4 +- .../SkillProviderExample.cpp | 79 +++- .../SkillProviderExample.h | 14 + .../SkillManagerPlugin/CMakeLists.txt | 1 + .../SkillManagerMonitorWidget.ui | 58 ++- .../SkillManagerMonitorWidgetController.cpp | 409 ++++++++++-------- .../SkillManagerMonitorWidgetController.h | 65 ++- .../skills/SkillManagerInterface.ice | 68 ++- .../interface/skills/SkillMemoryInterface.ice | 2 +- .../skills/SkillProviderInterface.ice | 130 +++--- .../libraries/armem_skills/aron/Skill.xml | 62 ++- .../armem_skills/aron_conversions.cpp | 191 +++++++- .../libraries/armem_skills/aron_conversions.h | 41 +- .../segment/ExecutableSkillLibrarySegment.cpp | 28 +- .../segment/ExecutableSkillLibrarySegment.h | 13 +- .../server/segment/SkillEventSegment.cpp | 69 +-- .../server/segment/SkillEventSegment.h | 6 +- .../segment/SkillExecutionRequestSegment.cpp | 46 +- .../segment/SkillExecutionRequestSegment.h | 14 +- .../aron/core/data/variant/container/Dict.cpp | 53 +-- .../aron/core/data/variant/container/List.cpp | 33 +- .../libraries/skills/core/ProviderID.cpp | 12 +- .../libraries/skills/core/ProviderID.h | 8 +- .../libraries/skills/core/ProviderInfo.cpp | 21 +- .../libraries/skills/core/ProviderInfo.h | 4 +- .../RobotAPI/libraries/skills/core/Skill.cpp | 78 ++-- source/RobotAPI/libraries/skills/core/Skill.h | 48 +- .../skills/core/SkillDescription.cpp | 33 +- .../libraries/skills/core/SkillDescription.h | 12 +- .../skills/core/SkillExecutionID.cpp | 19 +- .../libraries/skills/core/SkillExecutionID.h | 16 +- .../skills/core/SkillExecutionRequest.cpp | 9 +- .../skills/core/SkillExecutionRequest.h | 12 +- .../libraries/skills/core/SkillID.cpp | 34 +- .../RobotAPI/libraries/skills/core/SkillID.h | 31 +- .../skills/core/SkillStatusUpdate.cpp | 225 ++++++---- .../libraries/skills/core/SkillStatusUpdate.h | 68 ++- .../manager/SkillManagerComponentPlugin.cpp | 270 ++++++++---- .../manager/SkillManagerComponentPlugin.h | 37 +- .../skills/provider/PeriodicSkill.cpp | 2 +- .../libraries/skills/provider/PeriodicSkill.h | 4 +- .../provider/PeriodicSpecializedSkill.h | 11 +- .../libraries/skills/provider/SkillContext.h | 17 +- .../libraries/skills/provider/SkillFactory.h | 66 +-- .../provider/SkillProviderComponentPlugin.cpp | 175 ++++---- .../provider/SkillProviderComponentPlugin.h | 65 ++- .../libraries/skills/provider/SkillProxy.cpp | 63 +-- .../libraries/skills/provider/SkillProxy.h | 33 +- .../skills/provider/SpecializedSkill.h | 28 +- .../detail/SkillImplementationWrapper.cpp | 54 ++- .../detail/SkillImplementationWrapper.h | 2 +- 52 files changed, 1780 insertions(+), 1091 deletions(-) diff --git a/source/RobotAPI/components/armem/server/SkillsMemory/SkillsMemory.cpp b/source/RobotAPI/components/armem/server/SkillsMemory/SkillsMemory.cpp index 00f5da832..02cbe58ce 100644 --- a/source/RobotAPI/components/armem/server/SkillsMemory/SkillsMemory.cpp +++ b/source/RobotAPI/components/armem/server/SkillsMemory/SkillsMemory.cpp @@ -114,9 +114,9 @@ namespace armarx { ARMARX_CHECK_NOT_NULL(instance); - skills::manager::dto::SkillExecutionRequest exInfo = + skills::SkillExecutionRequest exInfo = skillExecutionRequestCoreSegment.convertCommit(instance); - SkillManagerComponentPluginUser::executeSkill(exInfo, current); + SkillManagerComponentPluginUser::executeSkill(exInfo.toManagerIce(), current); } } } @@ -128,10 +128,12 @@ namespace armarx SkillsMemory::addProvider(const skills::manager::dto::ProviderInfo& info, const Ice::Current& current) { + ARMARX_INFO << "Adding provider to skill memory: " << info.providerId.providerName; SkillManagerComponentPluginUser::addProvider(info, current); // log skills to memory - executableSkillCoreSegment.addSkillProvider(info); + auto p = skills::ProviderInfo::FromIce(info); + executableSkillCoreSegment.addSkillProvider(p); } void @@ -148,22 +150,32 @@ namespace armarx SkillsMemory::executeSkill(const skills::manager::dto::SkillExecutionRequest& info, const Ice::Current& current) { - skillExecutionRequestCoreSegment.addSkillExecutionRequest(info); + auto e = skills::SkillExecutionRequest::FromIce(info); + skillExecutionRequestCoreSegment.addSkillExecutionRequest(e); + return SkillManagerComponentPluginUser::executeSkill(info, current); } void SkillsMemory::updateStatusForSkill(const skills::provider::dto::SkillStatusUpdate& update, - const skills::provider::dto::ProviderID& providerId, + const skills::callback::dto::ProviderID& providerId, const Ice::Current& current) { - skillEventCoreSegment.addSkillUpdateEvent(update, providerId.providerName); + auto p = skills::ProviderID::FromIce(providerId); + auto u = skills::SkillStatusUpdate::FromIce(update, p); + skillEventCoreSegment.addSkillUpdateEvent(u); } - skills::provider::dto::SkillStatusUpdateMap + skills::manager::dto::SkillStatusUpdateMap SkillsMemory::getLatestSkillExecutionStatuses(int n, const Ice::Current& current) { - return {}; // TODO + auto m = skillEventCoreSegment.getLatestSkillEvents(n); + skills::manager::dto::SkillStatusUpdateMap ret; + for (const auto& [k, v] : m) + { + ret[k.toManagerIce()] = v.toManagerIce(); + } + return ret; } /* diff --git a/source/RobotAPI/components/armem/server/SkillsMemory/SkillsMemory.h b/source/RobotAPI/components/armem/server/SkillsMemory/SkillsMemory.h index da7e3df47..81109b0bd 100644 --- a/source/RobotAPI/components/armem/server/SkillsMemory/SkillsMemory.h +++ b/source/RobotAPI/components/armem/server/SkillsMemory/SkillsMemory.h @@ -86,10 +86,10 @@ namespace armarx const Ice::Current& current) override; void updateStatusForSkill(const skills::provider::dto::SkillStatusUpdate& update, - const skills::provider::dto::ProviderID& id, + const skills::callback::dto::ProviderID& id, const Ice::Current& current) override; - skills::provider::dto::SkillStatusUpdateMap + skills::manager::dto::SkillStatusUpdateMap getLatestSkillExecutionStatuses(int n, const Ice::Current& current) override; // WritingInterface interface diff --git a/source/RobotAPI/components/skills/SkillProviderExample/SkillProviderExample.cpp b/source/RobotAPI/components/skills/SkillProviderExample/SkillProviderExample.cpp index 401335868..2fbc92142 100644 --- a/source/RobotAPI/components/skills/SkillProviderExample/SkillProviderExample.cpp +++ b/source/RobotAPI/components/skills/SkillProviderExample/SkillProviderExample.cpp @@ -39,10 +39,60 @@ namespace armarx::skills::provider parameters) .dump(2) << "\n" + << "Type fulfilled? " + << parameters->fullfillsType( + armarx::skills::Example::HelloWorldAcceptedType::ToAronType()) + << "\n" << "(executed at: " << IceUtil::Time::now() << ")"; return {TerminatedSkillStatus::Succeeded, nullptr}; } + IncompleteSkill::IncompleteSkill() : Skill(GetSkillDescription()) + { + } + + SkillDescription + IncompleteSkill::GetSkillDescription() + { + auto d = HelloWorldSkill::GetSkillDescription(); + return SkillDescription{{"IncompleteSkill"}, + d.description, + {}, + d.timeout + armarx::core::time::Duration::Seconds(2), + d.acceptedType}; + } + + Skill::PrepareResult + IncompleteSkill::prepare() + { + if (!first_prepared) + { + first_prepared = true; + std::thread foo( + [&]() + { + auto d = HelloWorldSkill::GetSkillDescription(); + std::this_thread::sleep_for(std::chrono::milliseconds(2000)); + this->setParameters(d.rootProfileParameterization); + }); + foo.detach(); + } + + auto s = HelloWorldSkill(); + s.setParameters(this->getParameters()); + s.mainOfSkill(); + + return {.status = ActiveOrTerminatedSkillStatus::Succeeded}; + } + + Skill::MainResult + IncompleteSkill::main() + { + auto s = HelloWorldSkill(); + s.setParameters(this->getParameters()); + return s.mainOfSkill(); + } + ChainingSkill::ChainingSkill() : Skill(GetSkillDescription()) { } @@ -68,11 +118,12 @@ namespace armarx::skills::provider exec2.some_text = "Hello from the ChainingSkill 2"; exec3.some_text = "Hello from the ChainingSkill 3"; - SkillProxy skillExecPrx(manager, {"SkillProviderExample", "HelloWorld"}); + SkillProxy skillExecPrx( + manager, skills::SkillID(skills::ProviderID("SkillProviderExample"), "HelloWorld")); - skillExecPrx.executeFullSkill(getSkillId().toString(), exec1.toAron()); - skillExecPrx.executeFullSkill(getSkillId().toString(), exec2.toAron()); - skillExecPrx.executeFullSkill(getSkillId().toString(), exec3.toAron()); + skillExecPrx.executeSkill(getSkillId().toString(), exec1.toAron()); + skillExecPrx.executeSkill(getSkillId().toString(), exec2.toAron()); + skillExecPrx.executeSkill(getSkillId().toString(), exec3.toAron()); return {TerminatedSkillStatus::Succeeded, nullptr}; } @@ -88,7 +139,7 @@ namespace armarx::skills::provider return SkillDescription{{"Timeout"}, "This fails with timeout reached", {}, - armarx::core::time::Duration::MilliSeconds(1000), + armarx::core::time::Duration::MilliSeconds(5000), nullptr}; } @@ -96,7 +147,7 @@ namespace armarx::skills::provider TimeoutSkill::step() { // do heavy work - std::this_thread::sleep_for(std::chrono::milliseconds(200)); + std::this_thread::sleep_for(std::chrono::milliseconds(500)); return {ActiveOrTerminatedSkillStatus::Running, nullptr}; } @@ -157,7 +208,8 @@ namespace armarx::skills::provider SkillProviderExample::onInitComponent() { // Add example skill - addSkillFactory(SkillFactory::ForSkillDescriptionGetter<HelloWorldSkill>()); + ARMARX_INFO << "Adding skill HelloWorldSkill"; + addSkillFactory<HelloWorldSkill>(); // Add another lambda example skill { @@ -175,13 +227,20 @@ namespace armarx::skills::provider } // Add another example skill - addSkillFactory(SkillFactory::ForSkillDescriptionGetter<CallbackSkill>()); + ARMARX_INFO << "Adding skill CallbackSkill"; + addSkillFactory<CallbackSkill>(); // Add timeout skill - addSkillFactory(SkillFactory::ForSkillDescriptionGetter<TimeoutSkill>()); + ARMARX_INFO << "Adding skill TimeoutSkill"; + addSkillFactory<TimeoutSkill>(); // chaining - addSkillFactory(SkillFactory::ForSkillDescriptionGetter<ChainingSkill>()); + ARMARX_INFO << "Adding skill ChainingSkill"; + addSkillFactory<ChainingSkill>(); + + // incomplete and prepare + ARMARX_INFO << "Adding skill IncompleteSkill"; + addSkillFactory<IncompleteSkill>(); } void diff --git a/source/RobotAPI/components/skills/SkillProviderExample/SkillProviderExample.h b/source/RobotAPI/components/skills/SkillProviderExample/SkillProviderExample.h index ea8f114eb..190dc56a2 100644 --- a/source/RobotAPI/components/skills/SkillProviderExample/SkillProviderExample.h +++ b/source/RobotAPI/components/skills/SkillProviderExample/SkillProviderExample.h @@ -44,6 +44,20 @@ namespace armarx::skills::provider Skill::MainResult main() final; }; + class IncompleteSkill : public Skill + { + public: + IncompleteSkill(); + + static SkillDescription GetSkillDescription(); + + private: + Skill::PrepareResult prepare() final; + Skill::MainResult main() final; + + std::atomic_bool first_prepared = false; + }; + class ChainingSkill : public Skill { public: diff --git a/source/RobotAPI/gui-plugins/SkillManagerPlugin/CMakeLists.txt b/source/RobotAPI/gui-plugins/SkillManagerPlugin/CMakeLists.txt index b40d5a2fc..a6d2ff63c 100644 --- a/source/RobotAPI/gui-plugins/SkillManagerPlugin/CMakeLists.txt +++ b/source/RobotAPI/gui-plugins/SkillManagerPlugin/CMakeLists.txt @@ -63,6 +63,7 @@ set(COMPONENT_LIBS RobotAPIInterfaces aron RobotAPISkills + SkillsMemory aronjsonconverter SimpleConfigDialog ) diff --git a/source/RobotAPI/gui-plugins/SkillManagerPlugin/SkillManagerMonitorWidget.ui b/source/RobotAPI/gui-plugins/SkillManagerPlugin/SkillManagerMonitorWidget.ui index 34d82d1fc..b96d3850e 100644 --- a/source/RobotAPI/gui-plugins/SkillManagerPlugin/SkillManagerMonitorWidget.ui +++ b/source/RobotAPI/gui-plugins/SkillManagerPlugin/SkillManagerMonitorWidget.ui @@ -79,32 +79,42 @@ <widget class="QTreeWidget" name="treeWidgetSkillExecutions"> <column> <property name="text"> - <string>ID</string> + <string>ExecutionID</string> </property> </column> <column> <property name="text"> - <string>Skill</string> + <string>Executor</string> </property> </column> <column> <property name="text"> - <string>Scheduled</string> + <string>SkillID</string> </property> </column> <column> <property name="text"> - <string>Running</string> + <string>IsConstructing</string> </property> </column> <column> <property name="text"> - <string>Finished</string> + <string>IsInitializing</string> </property> </column> <column> <property name="text"> - <string>Executor</string> + <string>IsPreparing</string> + </property> + </column> + <column> + <property name="text"> + <string>IsRunning</string> + </property> + </column> + <column> + <property name="text"> + <string>Finished</string> </property> </column> </widget> @@ -132,7 +142,7 @@ <string>Manager</string> </property> <layout class="QGridLayout" name="gridLayout"> - <item row="4" column="0" colspan="3"> + <item row="5" column="0" colspan="3"> <widget class="QTreeWidget" name="treeWidgetSkills"> <column> <property name="text"> @@ -141,11 +151,30 @@ </column> <column> <property name="text"> - <string>HasType</string> + <string>HasInputType</string> + </property> + </column> + <column> + <property name="text"> + <string>HasOutputType</string> </property> </column> </widget> </item> + <item row="4" column="1"> + <widget class="QPushButton" name="pushButtonSearch"> + <property name="text"> + <string>Search</string> + </property> + </widget> + </item> + <item row="4" column="0"> + <widget class="QLineEdit" name="lineEditSearch"> + <property name="text"> + <string>Search...</string> + </property> + </widget> + </item> </layout> </widget> <widget class="QGroupBox" name="groupBoxSkillDetails"> @@ -176,17 +205,10 @@ </property> </widget> </item> - <item row="8" column="0"> - <widget class="QPushButton" name="pushButtonStopSkill"> - <property name="text"> - <string>Stop current skill</string> - </property> - </widget> - </item> <item row="0" column="3"> <widget class="QPushButton" name="pushButtonReset"> <property name="text"> - <string>Reset args</string> + <string>Reset args to profile</string> </property> </widget> </item> @@ -215,7 +237,7 @@ </column> <column> <property name="text"> - <string>defaultValue</string> + <string>defaultValue (hidden in GUI)</string> </property> </column> </widget> @@ -231,7 +253,7 @@ <widget class="QComboBox" name="comboBoxProfiles"> <item> <property name="text"> - <string><No Profile></string> + <string><No Profile selected. Using root></string> </property> </item> </widget> diff --git a/source/RobotAPI/gui-plugins/SkillManagerPlugin/SkillManagerMonitorWidgetController.cpp b/source/RobotAPI/gui-plugins/SkillManagerPlugin/SkillManagerMonitorWidgetController.cpp index 127db31f0..f48165ab9 100644 --- a/source/RobotAPI/gui-plugins/SkillManagerPlugin/SkillManagerMonitorWidgetController.cpp +++ b/source/RobotAPI/gui-plugins/SkillManagerPlugin/SkillManagerMonitorWidgetController.cpp @@ -38,6 +38,7 @@ #include <QDoubleSpinBox> #include <RobotAPI/libraries/aron/converter/json/NLohmannJSONConverter.h> +#include <RobotAPI/libraries/skills/core/SkillExecutionRequest.h> #include "aronTreeWidget/Data.h" @@ -50,8 +51,8 @@ namespace armarx if (!dialog) { dialog = new SimpleConfigDialog(parent); - dialog->addProxyFinder<skills::manager::dti::SkillManagerInterfacePrx>( - "SkillManager", "", "Skill*"); + dialog->addProxyFinder<skills::dti::SkillMemoryInterfacePrx>( + "SkillMemory", "", "SkillMem*"); } return qobject_cast<SimpleConfigDialog*>(dialog); } @@ -59,25 +60,47 @@ namespace armarx void SkillManagerMonitorWidgetController::configured() { - observerName = dialog->getProxyName("SkillManager"); + observerName = dialog->getProxyName("SkillMemory"); } void SkillManagerMonitorWidgetController::loadSettings(QSettings* settings) { - observerName = settings->value("SkillManager", "SkillManager").toString().toStdString(); + observerName = settings->value("SkillMemory", "SkillMemory").toString().toStdString(); } void SkillManagerMonitorWidgetController::saveSettings(QSettings* settings) { - settings->setValue("SkillManager", QString::fromStdString(observerName)); + settings->setValue("SkillMemory", QString::fromStdString(observerName)); } } // namespace armarx // Others namespace armarx { + SkillExecutionInfoTreeWidgetItem* + SkillExecutionInfoTreeWidgetItem::SearchRecursiveForMatch( + SkillExecutionInfoTreeWidgetItem* haystack, + const skills::SkillExecutionID& needle) + { + if (!haystack) + { + return nullptr; + } + + if (needle == haystack->executionId) + { + return haystack; + } + for (int i = 0; i < haystack->childCount(); ++i) + { + auto el = static_cast<SkillExecutionInfoTreeWidgetItem*>(haystack->child(i)); + return SkillExecutionInfoTreeWidgetItem::SearchRecursiveForMatch(el, needle); + } + return nullptr; + } + SkillManagerMonitorWidgetController::SkillManagerMonitorWidgetController() { widget.setupUi(getWidget()); @@ -115,10 +138,10 @@ namespace armarx &QPushButton::clicked, this, &SkillManagerMonitorWidgetController::executeSkill); - connect(widget.pushButtonStopSkill, - &QPushButton::clicked, - this, - &SkillManagerMonitorWidgetController::stopSkill); + // connect(widget.pushButtonStopSkill, + // &QPushButton::clicked, + // this, + // &SkillManagerMonitorWidgetController::stopSkill); connect(widget.treeWidgetSkills, &QTreeWidget::currentItemChanged, @@ -149,7 +172,7 @@ namespace armarx QAbstractItemView::EditTrigger::NoEditTriggers); widget.treeWidgetSkillDetails->setColumnHidden(3, true); - getProxy(manager, observerName, 1000); + getProxy(memory, observerName, 1000); connected = true; } @@ -157,15 +180,15 @@ namespace armarx SkillManagerMonitorWidgetController::onDisconnectComponent() { connected = false; - manager = nullptr; + memory = nullptr; // reset all skills.clear(); widget.treeWidgetSkills->clear(); widget.treeWidgetSkillDetails->clear(); skillsArgumentsTreeWidgetItem = nullptr; - selectedSkill.providerName = ""; - selectedSkill.skillName = ""; + selectedSkill.skillId.providerId->providerName = skills::SkillID::UNKNOWN; + selectedSkill.skillId.skillName = skills::SkillID::UNKNOWN; } void @@ -188,7 +211,7 @@ namespace armarx void SkillManagerMonitorWidgetController::refreshSkills() { - if (!manager) + if (!memory) { // check if null return; @@ -200,66 +223,104 @@ namespace armarx { std::scoped_lock l(updateMutex); - auto managerSkills = manager->getSkillDescriptions(); + auto managerSkills = memory->getSkillDescriptions(); - std::vector<armarx::skills::manager::dto::SkillID> removedSkills; - for (auto it = skills.begin(); it != skills.end();) + // completely recreate internal skills map + skills.clear(); + for (const auto& [sid, desc] : managerSkills) { - auto pid = it->first; - if (managerSkills.find(pid) == managerSkills.end()) - { - ARMARX_DEBUG << "REMOVE " << pid; - removedSkills.push_back(pid); - it = skills.erase(it); - } - else - { - it++; - } - } + auto description = skills::SkillDescription::FromIce(desc); + auto skillId = skills::SkillID::FromIce(sid); + auto providerId = skills::ProviderID(skillId); - // add new ones - std::vector<armarx::skills::manager::dto::SkillID> newSkills; - for (const auto& [skillID, providerSkills] : managerSkills) - { - if (skills.find(skillID) == skills.end()) - { - skills.insert(std::make_pair(skillID, providerSkills)); - newSkills.push_back(skillID); - } + ARMARX_CHECK(skillId.fullySpecified()); + + auto& providedSkillsMap = skills[providerId]; // create new if not existent + providedSkillsMap.insert({skillId, description}); } - /* UPDATE TREE VIEW */ - // remove providers from tree + // update tree view. Remove non-existing elements int i = 0; while (i < widget.treeWidgetSkills->topLevelItemCount()) { - QTreeWidgetItem* item = widget.treeWidgetSkills->topLevelItem(i); - if (auto it = std::find( - removedSkills.begin(), removedSkills.end(), item->text(0).toStdString()); - it != removedSkills.end()) + auto* providerItem = widget.treeWidgetSkills->topLevelItem(i); + auto providerName = providerItem->text(0).toStdString(); + skills::ProviderID providerId(providerName); + + if (skills.find(providerId) == skills.end()) { - delete widget.treeWidgetSkills->takeTopLevelItem(i); + providerItem = nullptr; // reset + auto remove = widget.treeWidgetSkills->takeTopLevelItem(i); + delete remove; + continue; } - else + + ++i; + auto& providedSkills = skills.at(providerId); + + int j = 0; + while (j < providerItem->childCount()) { - ++i; + auto* skillItem = providerItem->child(j); + auto skillName = skillItem->text(0).toStdString(); + + skills::SkillID skillId(providerName, skillName); + + if (providedSkills.find(skillId) == providedSkills.end()) + { + skillItem = nullptr; + auto remove = providerItem->takeChild(j); + delete remove; + continue; + } + + ++j; } } - // add new providers - for (const auto& [providerName, providerSkills] : skills) + // update tree view. Add new elements + for (const auto& [providerId, providedSkills] : skills) { - if (auto it = std::find(newSkills.begin(), newSkills.end(), providerName); - it != newSkills.end()) + QTreeWidgetItem* providerItem = nullptr; + for (int i = 0; i < widget.treeWidgetSkills->topLevelItemCount(); ++i) + { + auto el = widget.treeWidgetSkills->topLevelItem(i); + auto providerName = el->text(0).toStdString(); + skills::ProviderID elProviderId(providerName); + + if (providerId == elProviderId) + { + providerItem = el; + break; + } + } + + if (!providerItem) { - auto item = new QTreeWidgetItem(widget.treeWidgetSkills); - item->setText(0, QString::fromStdString(providerName)); - for (const auto& [name, sk] : providerSkills) + providerItem = new QTreeWidgetItem(widget.treeWidgetSkills); + providerItem->setText(0, QString::fromStdString(providerId.providerName)); + } + + for (const auto& [skillId, skill] : providedSkills) + { + QTreeWidgetItem* skillItem = nullptr; + for (int i = 0; i < providerItem->childCount(); ++i) + { + auto el = providerItem->child(i); + auto skillName = el->text(0).toStdString(); + skills::SkillID elSkillId(providerId.providerName, skillName); + + if (skillId == elSkillId) + { + skillItem = el; + break; + } + } + + if (!skillItem) { - auto itsk = new QTreeWidgetItem(item); - item->addChild(itsk); - itsk->setText(0, QString::fromStdString(name)); + skillItem = new SkillInfoTreeWidgetItem(skill, providerItem); + skillItem->setText(0, QString::fromStdString(skillId.skillName)); } } } @@ -285,7 +346,7 @@ namespace armarx {skills::SkillStatus::Initializing, "Initializing"}, {skills::SkillStatus::Preparing, "Preparing"}}; - if (!manager) + if (!memory) { // check if null return; @@ -295,74 +356,73 @@ namespace armarx { std::scoped_lock l(updateMutex); - auto currentManagerStatuses = manager->getSkillExecutionStatuses(); + auto currentManagerStatuses = memory->getLatestSkillExecutionStatuses( + 100); // we assume that there are no more than 100 new skills.. - for (const auto& up : currentManagerStatuses) + for (const auto& [k, v] : currentManagerStatuses) { - auto statusUpdate = skills::SkillStatusUpdate::FromIce(up); + auto executionId = skills::SkillExecutionID::FromIce(k); + auto statusUpdate = skills::SkillStatusUpdate::FromIce(v); - if (auto it = pastSkillStatusUpdates.find(statusUpdate.executionId); - it == pastSkillStatusUpdates.end()) + SkillExecutionInfoTreeWidgetItem* found = nullptr; + for (int i = 0; i < widget.treeWidgetSkillExecutions->topLevelItemCount(); ++i) { - pastSkillStatusUpdates.insert({statusUpdate.executionId, statusUpdate}); + auto c = static_cast<SkillExecutionInfoTreeWidgetItem*>( + widget.treeWidgetSkillExecutions->topLevelItem(i)); - auto item = new QTreeWidgetItem(widget.treeWidgetSkillExecutions); - item->setText(0, QString::fromStdString("TODO:")); - item->setText( - 1, QString::fromStdString(statusUpdate.executionId.skillId.toString())); - if (statusUpdate.hasBeenInitialized()) - { - item->setText( - 2, QString::fromStdString("YES (TODO:)")); // when was skill scheduled - } + found = + SkillExecutionInfoTreeWidgetItem::SearchRecursiveForMatch(c, executionId); - if (statusUpdate.hasBeenRunning()) + if (found) { - item->setText( - 3, QString::fromStdString("YES (TODO:)")); // when was skill running + // update values + found->setText(3, + QString::fromStdString( + statusUpdate.hasBeenConstructed() ? " (\xfb) " : "")); + found->setText(4, + QString::fromStdString( + statusUpdate.hasBeenInitialized() ? " (\xfb) " : "")); + found->setText(5, + QString::fromStdString( + statusUpdate.hasBeenPrepared() ? " (\xfb) " : "")); + found->setText(6, + QString::fromStdString( + statusUpdate.hasBeenRunning() ? " (\xfb) " : "")); + found->setText(7, + QString::fromStdString( + statusUpdate.hasBeenTerminated() ? " (\xfb) " : "")); + break; } + } - if (statusUpdate.hasBeenTerminated()) - { - item->setText(4, - QString::fromStdString( - "(" + ExecutionStatus2String.at(statusUpdate.status) + - ")")); // when was skill terminated (and how) - } - item->setText(5, QString::fromStdString(statusUpdate.executionId.executorName)); + if (!found) + { + // TODO: Sort to executor! + auto item = new SkillExecutionInfoTreeWidgetItem( + executionId, widget.treeWidgetSkillExecutions); + + item->setText(0, + QString::fromStdString( + executionId.executionStartedTime.toDateTimeString())); + item->setText(1, QString::fromStdString(executionId.executorName)); + item->setText(2, QString::fromStdString(executionId.skillId.toString())); + item->setText(3, + QString::fromStdString( + statusUpdate.hasBeenConstructed() ? " (\xfb) " : "")); + item->setText(4, + QString::fromStdString( + statusUpdate.hasBeenInitialized() ? " (\xfb) " : "")); + item->setText( + 5, + QString::fromStdString(statusUpdate.hasBeenPrepared() ? " (\xfb) " : "")); + item->setText( + 6, QString::fromStdString(statusUpdate.hasBeenRunning() ? " (\xfb) " : "")); + item->setText( + 7, + QString::fromStdString(statusUpdate.hasBeenTerminated() ? " (\xfb) " : "")); } } - - // widget.listWidgetActiveSkills->clear(); - // for (const auto& [id, prefix] : activeSkillsAndPrefixes) - // { - // auto prefixedStr = id.toString(prefix); - // bool longest = true; - // for ( - // const auto& [id2, prefix2] : - // activeSkillsAndPrefixes) // check if there is a deeper skill currently executing - // { - // auto prefixedStr2 = id.toString(prefix2); - // if (prefixedStr == prefixedStr2) - // { - // continue; - // } - - // if (simox::alg::starts_with(prefixedStr2, prefixedStr)) - // { - // longest = false; - // break; - // } - // } - - // if (longest) - // { - // widget.listWidgetActiveSkills->addItem( - // QString::fromStdString(id.toString() + ": " + id.toString(prefix))); - // } - // } } - catch (...) { // perhaps the manager died during the method? @@ -372,14 +432,16 @@ namespace armarx void SkillManagerMonitorWidgetController::executeSkill() { - if (selectedSkill.providerName.empty() or selectedSkill.skillName.empty()) + if (not selectedSkill.skillId.fullySpecified()) { return; } std::scoped_lock l(updateMutex); - const auto& skillDescriptions = skills.at(selectedSkill.providerName); - if (!skillDescriptions.count(selectedSkill.skillName)) + + auto providerId = skills::ProviderID(selectedSkill.skillId); + const auto& skillDescriptions = skills.at(providerId); + if (skillDescriptions.find(selectedSkill.skillId) == skillDescriptions.end()) { return; } @@ -387,41 +449,37 @@ namespace armarx auto data = getConfigAsAron(); char hostname[HOST_NAME_MAX]; - gethostname(hostname, HOST_NAME_MAX); - skills::manager::dto::SkillExecutionRequest exInfo; - exInfo.executorName = "Skills.Manager GUI (hostname: " + std::string(hostname) + ")"; - exInfo.skillId = {selectedSkill.providerName, selectedSkill.skillName}; - exInfo.params = aron::data::Dict::ToAronDictDTO(data); + skills::SkillExecutionRequest req(selectedSkill.skillId, + "Skills.Manager GUI (hostname: " + std::string(hostname) + + ")", + data); - ARMARX_IMPORTANT << "Executing skill from GUI: " << selectedSkill.providerName << "/" - << selectedSkill.skillName << ". The data was: " << data; + ARMARX_CHECK(selectedSkill.skillId.fullySpecified()); // sanity check + ARMARX_IMPORTANT << "Executing skill from GUI: " << selectedSkill.skillId << "."; // Note that we execute the skill in a seperate thread so that the GUI thread does not freeze. - manager->begin_executeSkill(exInfo); + memory->begin_executeSkill(req.toManagerIce()); } void SkillManagerMonitorWidgetController::stopSkill() { - std::scoped_lock l(updateMutex); - if (selectedSkill.providerName.empty() or selectedSkill.skillName.empty()) - { - return; - } + // std::scoped_lock l(updateMutex); + // if (selectedSkill.skillId.fullySpecified()) + // { + // return; + // } - const auto& skillDescriptions = skills.at(selectedSkill.providerName); - if (!skillDescriptions.count(selectedSkill.skillName)) - { - return; - } + // const auto& skillDescriptions = skills.at(*selectedSkill.skillId.providerId); + // if (!skillDescriptions.count(selectedSkill.skillId.skillName)) + // { + // return; + // } - ARMARX_INFO << "Stopping skill from GUI: " << selectedSkill.providerName << "/" - << selectedSkill.skillName; + // ARMARX_INFO << "Stopping skill from GUI: " << selectedSkill.skillId; - auto id = - skills::manager::dto::SkillID{selectedSkill.providerName, selectedSkill.skillName}; - manager->abortSkill(id); + // manager->abortSkill(selectedSkill.skillId); } void @@ -439,35 +497,35 @@ namespace armarx if (!current->parent()) { - // no parent available. Should not happen + // no parent available. Perhaps provider clicked? return; } - SelectedSkill newSelectedSkill; - - // setup selected skill - newSelectedSkill.providerName = current->parent()->text(0).toStdString(); - newSelectedSkill.skillName = current->text(0).toStdString(); - - // setup groupBox - widget.groupBoxSkillDetails->setTitle(QString::fromStdString( - newSelectedSkill.providerName + "/" + newSelectedSkill.skillName)); - widget.groupBoxSkillDetails->setEnabled(true); + auto c = static_cast<SkillInfoTreeWidgetItem*>(current); + auto skillDescription = c->skillDescription; - if (newSelectedSkill.providerName == selectedSkill.providerName and - newSelectedSkill.skillName == selectedSkill.skillName) + if (selectedSkill.skillId == skillDescription.skillId) { + // no change return; } - selectedSkill = newSelectedSkill; + selectedSkill.skillId = skillDescription.skillId; + + // setup groupBox + widget.groupBoxSkillDetails->setTitle( + QString::fromStdString(selectedSkill.skillId.toString())); + widget.groupBoxSkillDetails->setEnabled(true); // setup table view widget.treeWidgetSkillDetails->clear(); aronTreeWidgetController = nullptr; skillsArgumentsTreeWidgetItem = nullptr; - auto skillDesc = skills.at(selectedSkill.providerName).at(selectedSkill.skillName); + // We assert that the skill exists + ARMARX_CHECK(skills.count(selectedSkill.skillId) > 0); + ARMARX_CHECK(skills.at(*selectedSkill.skillId.providerId).count(selectedSkill.skillId) > 0); + auto skillDesc = skills.at(*selectedSkill.skillId.providerId).at(selectedSkill.skillId); { auto it = new QTreeWidgetItem(widget.treeWidgetSkillDetails, @@ -476,14 +534,6 @@ namespace armarx widget.treeWidgetSkillDetails->addTopLevelItem(it); } - { - auto it = new QTreeWidgetItem(widget.treeWidgetSkillDetails, - {QString::fromStdString("Available profiles"), - QString::fromStdString("" /*simox::alg::join( - simox::alg::get_keys(skillDesc.profiles), ", ")*/)}); - widget.treeWidgetSkillDetails->addTopLevelItem(it); - } - { auto it = new QTreeWidgetItem(widget.treeWidgetSkillDetails, {QString::fromStdString("Description"), @@ -492,24 +542,39 @@ namespace armarx } { - armarx::core::time::Duration d; - armarx::core::time::fromIce(skillDesc.timeout, d); - auto it = new QTreeWidgetItem( widget.treeWidgetSkillDetails, {QString::fromStdString("Timeout"), - QString::fromStdString(std::to_string(d.toMilliSeconds())) + " ms"}); + QString::fromStdString(std::to_string(skillDesc.timeout.toMilliSeconds())) + + " ms"}); widget.treeWidgetSkillDetails->addTopLevelItem(it); } + // select root profile + widget.comboBoxProfiles->setCurrentIndex(0); + + // remove any profile + while (widget.comboBoxProfiles->count() > 1) + { + widget.comboBoxProfiles->removeItem(1); + } + + // add new profiles for this skill + // TODO: Where stored? + skillsArgumentsTreeWidgetItem = new QTreeWidgetItem(widget.treeWidgetSkillDetails, {QString::fromStdString("Arguments")}); - auto aron_args = aron::type::Object::FromAronObjectDTO(skillDesc.acceptedType); - auto default_args = - nullptr; //aron::data::Dict::FromAronDictDTO(skillDesc.defaultParams); TODO! fabian.peller + auto aron_args = skillDesc.acceptedType; + auto default_args_of_profile = skillDesc.rootProfileParameterization; + + aronTreeWidgetController = + std::make_shared<AronTreeWidgetController>(widget.treeWidgetSkillDetails, + skillsArgumentsTreeWidgetItem, + aron_args, + default_args_of_profile); - aronTreeWidgetController = std::make_shared<AronTreeWidgetController>( - widget.treeWidgetSkillDetails, skillsArgumentsTreeWidgetItem, aron_args, default_args); + // automatically expand args + skillsArgumentsTreeWidgetItem->setExpanded(true); } aron::data::DictPtr diff --git a/source/RobotAPI/gui-plugins/SkillManagerPlugin/SkillManagerMonitorWidgetController.h b/source/RobotAPI/gui-plugins/SkillManagerPlugin/SkillManagerMonitorWidgetController.h index d3fb1250f..869e79213 100644 --- a/source/RobotAPI/gui-plugins/SkillManagerPlugin/SkillManagerMonitorWidgetController.h +++ b/source/RobotAPI/gui-plugins/SkillManagerPlugin/SkillManagerMonitorWidgetController.h @@ -38,12 +38,51 @@ #include <RobotAPI/libraries/aron/core/data/variant/All.h> #include <RobotAPI/libraries/aron/core/type/variant/All.h> #include <RobotAPI/libraries/aron/core/type/visitor/variant/VariantVisitor.h> +#include <RobotAPI/libraries/skills/core/ProviderID.h> +#include <RobotAPI/libraries/skills/core/SkillDescription.h> #include <RobotAPI/libraries/skills/core/SkillStatusUpdate.h> #include "aronTreeWidget/AronTreeWidgetController.h" namespace armarx { + class SkillInfoTreeWidgetItem : public QTreeWidgetItem + { + public: + SkillInfoTreeWidgetItem(const skills::SkillDescription& desc, QTreeWidgetItem* parent) : + QTreeWidgetItem(parent), skillDescription(desc) + { + } + + SkillInfoTreeWidgetItem(const skills::SkillDescription& desc, QTreeWidget* parent) : + QTreeWidgetItem(parent), skillDescription(desc) + { + } + + skills::SkillDescription skillDescription; + }; + + class SkillExecutionInfoTreeWidgetItem : public QTreeWidgetItem + { + public: + SkillExecutionInfoTreeWidgetItem(const skills::SkillExecutionID& id, + QTreeWidgetItem* parent) : + QTreeWidgetItem(parent), executionId(id) + { + } + + SkillExecutionInfoTreeWidgetItem(const skills::SkillExecutionID& id, QTreeWidget* parent) : + QTreeWidgetItem(parent), executionId(id) + { + } + + static SkillExecutionInfoTreeWidgetItem* + SearchRecursiveForMatch(SkillExecutionInfoTreeWidgetItem* el, + const skills::SkillExecutionID& needle); + + skills::SkillExecutionID executionId; + }; + class ARMARXCOMPONENT_IMPORT_EXPORT SkillManagerMonitorWidgetController : public armarx::ArmarXComponentWidgetControllerTemplate<SkillManagerMonitorWidgetController> { @@ -101,21 +140,24 @@ namespace armarx QPointer<SimpleConfigDialog> dialog; std::string observerName = "SkillManager"; - skills::manager::dti::SkillManagerInterfacePrx manager = nullptr; - - struct SelectedSkill - { - std::string providerName; - std::string skillName; - }; + skills::dti::SkillMemoryInterfacePrx memory = nullptr; // Data taken from observer (snapshot of it) mutable std::mutex updateMutex; - skills::manager::dto::SkillDescriptionMap skills = {}; - std::map<skills::SkillExecutionId, skills::SkillStatusUpdate> pastSkillStatusUpdates = {}; + std::map<skills::ProviderID, std::map<skills::SkillID, skills::SkillDescription>> skills = + {}; + std::map<skills::SkillExecutionID, skills::SkillStatusUpdate> skillStatusUpdates = {}; // User Input - SelectedSkill selectedSkill; + struct SelectedSkill + { + skills::SkillID skillId; + + // make default constructable + SelectedSkill() : skillId({skills::SkillID::UNKNOWN}, skills::SkillID::UNKNOWN) + { + } + } selectedSkill; // Helper to get the treeWidgetItem easily QTreeWidgetItem* skillsArgumentsTreeWidgetItem = nullptr; @@ -124,9 +166,6 @@ namespace armarx // others QTimer* refreshSkillsResultTimer; - // skillExecutions - std::vector<std::thread> executions; - // connected flag std::atomic_bool connected = false; }; diff --git a/source/RobotAPI/interface/skills/SkillManagerInterface.ice b/source/RobotAPI/interface/skills/SkillManagerInterface.ice index adda483ad..17294f7a6 100644 --- a/source/RobotAPI/interface/skills/SkillManagerInterface.ice +++ b/source/RobotAPI/interface/skills/SkillManagerInterface.ice @@ -32,67 +32,62 @@ module armarx { module dto { + struct ProviderID + { + string providerName; + }; + // A skill ID. Must be unique within one SkillManager struct SkillID { - string providerName; + ProviderID providerId; string skillName; }; - struct ProviderID + struct SkillDescription { - string providerName; + SkillID skillId; + string description; + armarx::core::time::dto::Duration timeout; + aron::type::dto::AronObject acceptedType; + aron::type::dto::AronObject returndType; + aron::data::dto::Dict rootProfileDefaults; }; + dictionary<SkillID, dto::SkillDescription> SkillDescriptionMap; + struct ProviderInfo { ProviderID providerId; - provider::dti::SkillProviderInterface* provider; - provider::dto::SkillDescriptionMap providedSkills; + provider::dti::SkillProviderInterface* providerInterface; + dto::SkillDescriptionMap providedSkills; }; - // The minimum information that is needed to uniquely identifying a past skill execution struct SkillExecutionID { - SkillID skillId; // the id of the skill - string - executorName; // the name of the component/lib/skill that called the execution of the skill - armarx::core::time::dto::DateTime - executionStartedTime; // The time a skill was triggered + SkillID skillId; + string executorName; + armarx::core::time::dto::DateTime executionStartedTime; string uuid; }; - // Status updates of a skill (similar to the status update of the providers except the skillID) - struct SkillStatusUpdateHeader - { - SkillExecutionID executionId; - aron::data::dto::Dict usedParams; // the used parameterization - callback::dti::SkillProviderCallbackInterface* - usedCallbackInterface; // the used callback interface. Probably a prx to the manager - provider::dto::Execution::Status status; // the current status of the skill - }; - - // (similar to the status update of the providers except the skillID) struct SkillStatusUpdate { - SkillStatusUpdateHeader header; - aron::data::dto::Dict - data; // data, attached to the status update. If send via a callback, this data may be used by the callback interface + SkillExecutionID executionId; + aron::data::dto::Dict usedParams; + callback::dti::SkillProviderCallbackInterface* usedCallbackInterface; + core::dto::Execution::Status status; + aron::data::dto::Dict data; }; dictionary<SkillExecutionID, SkillStatusUpdate> SkillStatusUpdateMap; struct SkillExecutionRequest { - SkillID - skillId; // The id of a skill to request. Note that the skill or provider name can be regexes. - string executorName; // Who called the request - aron::data::dto::Dict - params; // the parameters for the skill. Can be nullptr if the skill does not require parameters + SkillID skillId; + string executorName; + aron::data::dto::Dict params; }; - - // Provider data types - dictionary<SkillID, provider::dto::SkillDescription> SkillDescriptionMap; } module dti @@ -106,11 +101,14 @@ module armarx void removeProvider(dto::ProviderID provider); + optional(1) dto::SkillDescription getSkillDescription( + dto::SkillID skillId); // get one skilldescriptions from a provider + dto::SkillDescriptionMap getSkillDescriptions(); // get all skilldescriptions from all providers - dto::SkillStatusUpdate - getSkillExecutionStatus(dto::SkillExecutionID executionId); + optional(2) dto::SkillStatusUpdate + getSkillExecutionStatus(dto::SkillExecutionID executionId); dto::SkillStatusUpdateMap getSkillExecutionStatuses(); // returns the current executions from all providers diff --git a/source/RobotAPI/interface/skills/SkillMemoryInterface.ice b/source/RobotAPI/interface/skills/SkillMemoryInterface.ice index 15a3dc379..934d2faba 100644 --- a/source/RobotAPI/interface/skills/SkillMemoryInterface.ice +++ b/source/RobotAPI/interface/skills/SkillMemoryInterface.ice @@ -38,7 +38,7 @@ module armarx interface SkillMemoryInterface extends armem::server::MemoryInterface, dti::StatechartListenerInterface, manager::dti::SkillManagerInterface { - provider::dto::SkillStatusUpdateMap getLatestSkillExecutionStatuses( + manager::dto::SkillStatusUpdateMap getLatestSkillExecutionStatuses( int n); // returns latest n statusupdates of all providers }; } diff --git a/source/RobotAPI/interface/skills/SkillProviderInterface.ice b/source/RobotAPI/interface/skills/SkillProviderInterface.ice index 31449a86d..b9db3268a 100644 --- a/source/RobotAPI/interface/skills/SkillProviderInterface.ice +++ b/source/RobotAPI/interface/skills/SkillProviderInterface.ice @@ -39,6 +39,51 @@ module armarx interface SkillProviderCallbackInterface; } } + + module provider + { + module dti + { + interface SkillProviderInterface; + } + } + } +} + +module armarx +{ + module skills + { + module core + { + module dto + { + + sequence<string> StringList; + + // The status enum of a skill + module Execution + { + enum Status + { + Constructing, + Initializing, + Preparing, + Running, + + // terminating values + Failed, + Succeeded, + Aborted + }; + } + + // Status updates of a skill + class SkillStatusUpdateBase + { + }; + } + } } } @@ -51,7 +96,6 @@ module armarx { module dto { - sequence<string> StringList; // A profile is something that is client side! // // A parameterization profile @@ -72,24 +116,16 @@ module armarx string skillName; }; - // A provider ID. Only used in callbacks - struct ProviderID - { - string providerName; - }; - // Description of a skill, independant of a provider // A skill is nothing but a executable thing, which can be executed on one or more 'robots' (empty means all) struct SkillDescription { - SkillID skillId; // the id of the skill - string - description; // a human readable description of what the skill does. Used in GUI - armarx::core::time::dto::Duration timeout; // can be set to -1 for infinite - aron::type::dto::AronObject - acceptedType; // the name of the object is irrelevant and only used in GUI. nullptr if not set - aron::data::dto::Dict - rootProfileDefaults; // default parameterization for the skill. Must be robot agnostic + SkillID skillId; + string description; + armarx::core::time::dto::Duration timeout; + aron::type::dto::AronObject acceptedType; + aron::type::dto::AronObject returndType; + aron::data::dto::Dict rootProfileDefaults; }; dictionary<SkillID, SkillDescription> SkillDescriptionMap; @@ -97,57 +133,29 @@ module armarx // Input to a provider to execute a skill struct SkillExecutionRequest { - SkillID skillId; // the id of the skill - string - executorName; // the name of the component/lib/skill that called the execution of the skill - aron::data::dto::Dict params; // the used parameterization - callback::dti::SkillProviderCallbackInterface* - callbackInterface; // use nullptr if you do not want to have callbacks + SkillID skillId; + string executorName; + aron::data::dto::Dict params; + callback::dti::SkillProviderCallbackInterface* callbackInterface; }; - // The status enum of a skill - module Execution - { - enum Status - { - Constructing, - Initializing, - Preparing, - Running, - - // terminating values - Failed, - Succeeded, - Aborted - }; - } - // The minimum information that is needed to uniquely identifying a past skill execution struct SkillExecutionID { - SkillID skillId; // the id of the skill - string - executorName; // the name of the component/lib/skill that called the execution of the skill - armarx::core::time::dto::DateTime - executionStartedTime; // The time a skill was triggered + SkillID skillId; + string executorName; + armarx::core::time::dto::DateTime executionStartedTime; string uuid; }; // Status updates of a skill - struct SkillStatusUpdateHeader - { - SkillExecutionID executionId; - aron::data::dto::Dict usedParams; // the used parameterization - callback::dti::SkillProviderCallbackInterface* - usedCallbackInterface; // the used callback interface. Probably a prx to the manager - Execution::Status status; // the current status of the skill - }; - struct SkillStatusUpdate { - SkillStatusUpdateHeader header; - aron::data::dto::Dict - data; // data, attached to the status update. If send via a callback, this data may be used by the callback interface + SkillExecutionID executionId; + aron::data::dto::Dict usedParams; + callback::dti::SkillProviderCallbackInterface* usedCallbackInterface; + core::dto::Execution::Status status; + aron::data::dto::Dict data; }; dictionary<SkillExecutionID, SkillStatusUpdate> SkillStatusUpdateMap; @@ -157,12 +165,12 @@ module armarx { interface SkillProviderInterface { - dto::SkillDescription getSkillDescription(dto::SkillID skill); + optional(1) dto::SkillDescription getSkillDescription(dto::SkillID skill); dto::SkillDescriptionMap getSkillDescriptions(); - dto::SkillStatusUpdate - getSkillExecutionStatus(dto::SkillExecutionID executionId); + optional(2) dto::SkillStatusUpdate + getSkillExecutionStatus(dto::SkillExecutionID executionId); dto::SkillStatusUpdateMap getSkillExecutionStatuses(); // returns all current skill executions @@ -195,6 +203,10 @@ module armarx { module dto { + struct ProviderID + { + string providerName; + }; } module dti @@ -203,7 +215,7 @@ module armarx { // used for callbacks from providers to update their skill execution status void updateStatusForSkill(provider::dto::SkillStatusUpdate statusUpdate, - provider::dto::ProviderID providerId); + dto::ProviderID providerId); } } } diff --git a/source/RobotAPI/libraries/armem_skills/aron/Skill.xml b/source/RobotAPI/libraries/armem_skills/aron/Skill.xml index 9b218af03..85bf52319 100644 --- a/source/RobotAPI/libraries/armem_skills/aron/Skill.xml +++ b/source/RobotAPI/libraries/armem_skills/aron/Skill.xml @@ -11,6 +11,23 @@ The memory should look like the following: <?xml version="1.0" encoding="UTF-8" ?> <AronTypeDefinition> <GenerateTypes> + <Object name='armarx::skills::arondto::ProviderID'> + <ObjectChild key='providerName'> + <String /> + </ObjectChild> + </Object> + + <Object name='armarx::skills::arondto::SkillID'> + <ObjectChild key='providerId'> + <armarx::skills::arondto::ProviderID /> + </ObjectChild> + <ObjectChild key='skillName'> + <String /> + </ObjectChild> + </Object> + + + <!-- TODO --> <Object name='armarx::skills::arondto::SkillProfile'> <ObjectChild key='profileName'> @@ -29,8 +46,8 @@ The memory should look like the following: <Object name='armarx::skills::arondto::SkillDescription'> - <ObjectChild key='skillName'> - <String /> + <ObjectChild key='skillId'> + <armarx::skills::arondto::SkillID /> </ObjectChild> <ObjectChild key='description'> @@ -53,14 +70,28 @@ The memory should look like the following: <AnyObject shared_ptr="1" /> </ObjectChild> + <ObjectChild key='returnType'> + <AnyObject shared_ptr="1" /> + </ObjectChild> + </Object> - <Object name='armarx::skills::arondto::SkillExecutionInfo'> + <!-- TODO --> + <Object name='armarx::skills::arondto::CompositeSkillExecutionParams'> <ObjectChild key='providerName'> - <String /> + <List> + <String /> <!--<armarx::skills::arondto::SkillExecutionInfo />--> + </List> </ObjectChild> + </Object> - <ObjectChild key='skillName'> + <Object name='armarx::skills::arondto::SkillExecutionRequest'> + + <ObjectChild key='skillId'> + <armarx::skills::arondto::SkillID /> + </ObjectChild> + + <ObjectChild key='executorName'> <String /> </ObjectChild> @@ -69,25 +100,28 @@ The memory should look like the following: </ObjectChild> </Object> - <Object name='armarx::skills::arondto::CompositeSkillExecutionParams'> - <ObjectChild key='providerName'> - <List> - <armarx::skills::arondto::SkillExecutionInfo /> - </List> + <Object name='armarx::skills::arondto::SkillExecutionEvent'> + + <ObjectChild key='skillId'> + <armarx::skills::arondto::SkillID /> </ObjectChild> - </Object> - <Object name='armarx::skills::arondto::SkillExecutionRequest' extends="armarx::skills::arondto::SkillExecutionInfo"> <ObjectChild key='executorName'> <String /> </ObjectChild> - </Object> - <Object name='armarx::skills::arondto::SkillExecutionEvent' extends="armarx::skills::arondto::SkillExecutionInfo"> + <ObjectChild key='executionStartedTimestamp'> + <DateTime /> + </ObjectChild> + <ObjectChild key='status'> <String /> </ObjectChild> + <ObjectChild key='params'> + <AnyObject shared_ptr="1" /> + </ObjectChild> + <ObjectChild key='data'> <AnyObject shared_ptr="1" /> </ObjectChild> diff --git a/source/RobotAPI/libraries/armem_skills/aron_conversions.cpp b/source/RobotAPI/libraries/armem_skills/aron_conversions.cpp index 1d8383b68..4bb6f1f51 100644 --- a/source/RobotAPI/libraries/armem_skills/aron_conversions.cpp +++ b/source/RobotAPI/libraries/armem_skills/aron_conversions.cpp @@ -1,26 +1,50 @@ #include "aron_conversions.h" +#include <RobotAPI/libraries/aron/converter/datatype/DatatypeConverterVisitor.h> +#include <RobotAPI/libraries/aron/converter/json/NLohmannJSONConverter.h> + namespace armarx::armem { - std::map<armarx::eStateType, armarx::skills::arondto::Statechart::StateType> toAronStateTypeMap = - { - {eNormalState, (armarx::skills::arondto::Statechart::StateType) armarx::skills::arondto::Statechart::StateType::NORMAL}, - {eFinalState, (armarx::skills::arondto::Statechart::StateType) armarx::skills::arondto::Statechart::StateType::FINAL}, - {eRemoteState, (armarx::skills::arondto::Statechart::StateType) armarx::skills::arondto::Statechart::StateType::REMOTE}, - {eDynamicRemoteState, (armarx::skills::arondto::Statechart::StateType) armarx::skills::arondto::Statechart::StateType::DYNAMIC_REMOTE}, - {eUndefined, (armarx::skills::arondto::Statechart::StateType) armarx::skills::arondto::Statechart::StateType::UNDEFINED}, + std::map<armarx::eStateType, armarx::skills::arondto::Statechart::StateType> + toAronStateTypeMap = { + {eNormalState, + (armarx::skills::arondto::Statechart::StateType) + armarx::skills::arondto::Statechart::StateType::NORMAL}, + {eFinalState, + (armarx::skills::arondto::Statechart::StateType) + armarx::skills::arondto::Statechart::StateType::FINAL}, + {eRemoteState, + (armarx::skills::arondto::Statechart::StateType) + armarx::skills::arondto::Statechart::StateType::REMOTE}, + {eDynamicRemoteState, + (armarx::skills::arondto::Statechart::StateType) + armarx::skills::arondto::Statechart::StateType::DYNAMIC_REMOTE}, + {eUndefined, + (armarx::skills::arondto::Statechart::StateType) + armarx::skills::arondto::Statechart::StateType::UNDEFINED}, }; - std::map<armarx::skills::arondto::Statechart::StateType, armarx::eStateType> fromAronStateTypeMap = - { - {(armarx::skills::arondto::Statechart::StateType) armarx::skills::arondto::Statechart::StateType::NORMAL, eNormalState}, - {(armarx::skills::arondto::Statechart::StateType) armarx::skills::arondto::Statechart::StateType::FINAL, eFinalState}, - {(armarx::skills::arondto::Statechart::StateType) armarx::skills::arondto::Statechart::StateType::REMOTE, eRemoteState}, - {(armarx::skills::arondto::Statechart::StateType) armarx::skills::arondto::Statechart::StateType::DYNAMIC_REMOTE, eDynamicRemoteState}, - {(armarx::skills::arondto::Statechart::StateType) armarx::skills::arondto::Statechart::StateType::UNDEFINED, eUndefined}, + std::map<armarx::skills::arondto::Statechart::StateType, armarx::eStateType> + fromAronStateTypeMap = { + {(armarx::skills::arondto::Statechart::StateType) + armarx::skills::arondto::Statechart::StateType::NORMAL, + eNormalState}, + {(armarx::skills::arondto::Statechart::StateType) + armarx::skills::arondto::Statechart::StateType::FINAL, + eFinalState}, + {(armarx::skills::arondto::Statechart::StateType) + armarx::skills::arondto::Statechart::StateType::REMOTE, + eRemoteState}, + {(armarx::skills::arondto::Statechart::StateType) + armarx::skills::arondto::Statechart::StateType::DYNAMIC_REMOTE, + eDynamicRemoteState}, + {(armarx::skills::arondto::Statechart::StateType) + armarx::skills::arondto::Statechart::StateType::UNDEFINED, + eUndefined}, }; - void fromAron(const skills::arondto::Statechart::StateType& dto, eStateType& bo) + void + fromAron(const skills::arondto::Statechart::StateType& dto, eStateType& bo) { if (fromAronStateTypeMap.find(dto) != fromAronStateTypeMap.end()) { @@ -32,7 +56,8 @@ namespace armarx::armem } } - void toAron(skills::arondto::Statechart::StateType& dto, const eStateType& bo) + void + toAron(skills::arondto::Statechart::StateType& dto, const eStateType& bo) { if (toAronStateTypeMap.find(bo) != toAronStateTypeMap.end()) { @@ -44,7 +69,8 @@ namespace armarx::armem } } - void fromAron(const skills::arondto::Statechart::ParameterMap& dto, StateParameterMap& bo) + void + fromAron(const skills::arondto::Statechart::ParameterMap& dto, StateParameterMap& bo) { // todo: implement // for (auto const& [key, val] : dto.parameters) @@ -54,7 +80,8 @@ namespace armarx::armem // } } - void toAron(skills::arondto::Statechart::ParameterMap& dto, const StateParameterMap& bo) + void + toAron(skills::arondto::Statechart::ParameterMap& dto, const StateParameterMap& bo) { for (auto const& [key, val] : bo) { @@ -62,7 +89,9 @@ namespace armarx::armem } } - void fromAron(const skills::arondto::Statechart::Transition& dto, ProfilerStatechartTransitionWithParameters& bo) + void + fromAron(const skills::arondto::Statechart::Transition& dto, + ProfilerStatechartTransitionWithParameters& bo) { bo.processId = dto.processId; bo.sourceStateIdentifier = dto.sourceStateIdentifier; @@ -74,7 +103,9 @@ namespace armarx::armem fromAron(dto.outputParameters, bo.outputParameters); } - void toAron(skills::arondto::Statechart::Transition& dto, const ProfilerStatechartTransitionWithParameters& bo) + void + toAron(skills::arondto::Statechart::Transition& dto, + const ProfilerStatechartTransitionWithParameters& bo) { dto.processId = bo.processId; dto.sourceStateIdentifier = bo.sourceStateIdentifier; @@ -85,4 +116,122 @@ namespace armarx::armem toAron(dto.localParameters, bo.localParameters); toAron(dto.outputParameters, bo.outputParameters); } -} + + void + fromAron(const armarx::skills::arondto::ProviderID& dto, skills::ProviderID& bo) + { + bo.providerName = dto.providerName; + } + + void + toAron(armarx::skills::arondto::ProviderID& dto, const skills::ProviderID& bo) + { + dto.providerName = bo.providerName; + } + + void + fromAron(const armarx::skills::arondto::SkillID& dto, skills::SkillID& bo) + { + bo.skillName = dto.skillName; + bo.providerId = skills::ProviderID(skills::SkillID::UNKNOWN); + fromAron(dto.providerId, *bo.providerId); + } + + void + toAron(armarx::skills::arondto::SkillID& dto, const skills::SkillID& bo) + { + dto.skillName = bo.skillName; + dto.providerId.resetHard(); + if (bo.providerId.has_value()) + { + toAron(dto.providerId, *bo.providerId); + } + } + + void + fromAron(const armarx::skills::arondto::SkillDescription& dto, skills::SkillDescription& bo) + { + fromAron(dto.skillId, bo.skillId); + bo.description = dto.description; + bo.timeout = dto.timeout; + bo.rootProfileParameterization = dto.rootProfileParameterization; + if (dto.acceptedType) + { + throw armarx::LocalException("Not implemented yet"); + } + } + + void + toAron(armarx::skills::arondto::SkillDescription& dto, const skills::SkillDescription& bo) + { + toAron(dto.skillId, bo.skillId); + dto.description = bo.description; + dto.timeout = bo.timeout; + dto.rootProfileParameterization = bo.rootProfileParameterization; + if (bo.acceptedType) + { + aron::type::converter::AronDatatypeConverterVisitor c; + aron::type::visit(c, bo.acceptedType); + + dto.acceptedType = aron::data::Dict::DynamicCastAndCheck(c.latest); + } + } + + void + fromAron(const armarx::skills::arondto::SkillExecutionRequest& dto, + skills::SkillExecutionRequest& bo) + { + fromAron(dto.skillId, bo.skillId); + bo.executorName = dto.executorName; + bo.params = dto.params; + } + + void + toAron(armarx::skills::arondto::SkillExecutionRequest& dto, + const skills::SkillExecutionRequest& bo) + { + toAron(dto.skillId, bo.skillId); + dto.executorName = bo.executorName; + dto.params = bo.params; + } + + void + fromAron(const armarx::skills::arondto::SkillExecutionEvent& dto, skills::SkillStatusUpdate& bo) + { + static std::map<std::string, skills::SkillStatus> map{ + {"Constructing", skills::SkillStatus::Constructing}, + {"Initializing", skills::SkillStatus::Initializing}, + {"Preparing", skills::SkillStatus::Preparing}, + {"Running", skills::SkillStatus::Running}, + {"Failed", skills::SkillStatus::Failed}, + {"Aborted", skills::SkillStatus::Aborted}, + {"Succeeded", skills::SkillStatus::Succeeded}}; + + fromAron(dto.skillId, bo.executionId.skillId); + bo.executionId.executionStartedTime = dto.executionStartedTimestamp; + bo.executionId.executorName = dto.executorName; + bo.usedParameterization.parameterization = dto.params; + bo.data = dto.data; + bo.status = map.at(dto.status); + } + + void + toAron(armarx::skills::arondto::SkillExecutionEvent& dto, const skills::SkillStatusUpdate& bo) + { + static std::map<skills::SkillStatus, std::string> map{ + {skills::SkillStatus::Constructing, "Constructing"}, + {skills::SkillStatus::Initializing, "Initializing"}, + {skills::SkillStatus::Preparing, "Preparing"}, + {skills::SkillStatus::Running, "Running"}, + {skills::SkillStatus::Failed, "Failed"}, + {skills::SkillStatus::Aborted, "Aborted"}, + {skills::SkillStatus::Succeeded, "Succeeded"}}; + + toAron(dto.skillId, bo.executionId.skillId); + dto.executorName = bo.executionId.executorName; + dto.executionStartedTimestamp = bo.executionId.executionStartedTime; + dto.params = bo.usedParameterization.parameterization; + dto.data = bo.data; + dto.status = map.at(bo.status); + } +} // namespace armarx::armem diff --git a/source/RobotAPI/libraries/armem_skills/aron_conversions.h b/source/RobotAPI/libraries/armem_skills/aron_conversions.h index 37092255c..57b7dd312 100644 --- a/source/RobotAPI/libraries/armem_skills/aron_conversions.h +++ b/source/RobotAPI/libraries/armem_skills/aron_conversions.h @@ -3,16 +3,45 @@ #include <ArmarXCore/interface/core/Profiler.h> #include <ArmarXCore/observers/ObserverObjectFactories.h> +#include <RobotAPI/libraries/armem_skills/aron/Skill.aron.generated.h> #include <RobotAPI/libraries/armem_skills/aron/Statechart.aron.generated.h> +#include <RobotAPI/libraries/skills/core/SkillDescription.h> +#include <RobotAPI/libraries/skills/core/SkillExecutionRequest.h> +#include <RobotAPI/libraries/skills/core/SkillStatusUpdate.h> namespace armarx::armem { - void fromAron(const armarx::skills::arondto::Statechart::StateType& dto, armarx::eStateType& bo); + void fromAron(const armarx::skills::arondto::Statechart::StateType& dto, + armarx::eStateType& bo); void toAron(armarx::skills::arondto::Statechart::StateType& dto, const armarx::eStateType& bo); - void fromAron(const armarx::skills::arondto::Statechart::ParameterMap& dto, armarx::StateParameterMap& bo); - void toAron(armarx::skills::arondto::Statechart::ParameterMap& dto, const armarx::StateParameterMap& bo); + void fromAron(const armarx::skills::arondto::Statechart::ParameterMap& dto, + armarx::StateParameterMap& bo); + void toAron(armarx::skills::arondto::Statechart::ParameterMap& dto, + const armarx::StateParameterMap& bo); - void fromAron(const armarx::skills::arondto::Statechart::Transition& dto, armarx::ProfilerStatechartTransitionWithParameters& bo); - void toAron(armarx::skills::arondto::Statechart::Transition& dto, const armarx::ProfilerStatechartTransitionWithParameters& bo); -} + void fromAron(const armarx::skills::arondto::Statechart::Transition& dto, + armarx::ProfilerStatechartTransitionWithParameters& bo); + void toAron(armarx::skills::arondto::Statechart::Transition& dto, + const armarx::ProfilerStatechartTransitionWithParameters& bo); + + void fromAron(const armarx::skills::arondto::ProviderID& dto, skills::ProviderID& bo); + void toAron(armarx::skills::arondto::ProviderID& dto, const skills::ProviderID& bo); + + void fromAron(const armarx::skills::arondto::SkillID& dto, skills::SkillID& bo); + void toAron(armarx::skills::arondto::SkillID& dto, const skills::SkillID& bo); + + void fromAron(const armarx::skills::arondto::SkillDescription& dto, + skills::SkillDescription& bo); + void toAron(armarx::skills::arondto::SkillDescription& dto, const skills::SkillDescription& bo); + + void fromAron(const armarx::skills::arondto::SkillExecutionRequest& dto, + skills::SkillExecutionRequest& bo); + void toAron(armarx::skills::arondto::SkillExecutionRequest& dto, + const skills::SkillExecutionRequest& bo); + + void fromAron(const armarx::skills::arondto::SkillExecutionEvent& dto, + skills::SkillStatusUpdate& bo); + void toAron(armarx::skills::arondto::SkillExecutionEvent& dto, + const skills::SkillStatusUpdate& bo); +} // namespace armarx::armem diff --git a/source/RobotAPI/libraries/armem_skills/server/segment/ExecutableSkillLibrarySegment.cpp b/source/RobotAPI/libraries/armem_skills/server/segment/ExecutableSkillLibrarySegment.cpp index 51d783b81..d2f99544e 100644 --- a/source/RobotAPI/libraries/armem_skills/server/segment/ExecutableSkillLibrarySegment.cpp +++ b/source/RobotAPI/libraries/armem_skills/server/segment/ExecutableSkillLibrarySegment.cpp @@ -6,6 +6,7 @@ #include <RobotAPI/libraries/armem/server/MemoryToIceAdapter.h> #include <RobotAPI/libraries/armem_skills/aron/Skill.aron.generated.h> +#include <RobotAPI/libraries/armem_skills/aron_conversions.h> #include <RobotAPI/libraries/aron/converter/datatype/DatatypeConverterVisitor.h> #include <RobotAPI/libraries/aron/converter/json/NLohmannJSONConverter.h> @@ -31,35 +32,16 @@ namespace armarx::skills::segment } void - ExecutableSkillLibraryCoreSegment::addSkillProvider( - const skills::manager::dto::ProviderInfo& info) + ExecutableSkillLibraryCoreSegment::addSkillProvider(const skills::ProviderInfo& info) { // add skills auto skills = info.providedSkills; - auto provId = id().withProviderSegmentName(info.providerId.providerName); - for (const auto& [key, desc] : skills) + for (const auto& [s, d] : skills) { armarx::skills::arondto::SkillDescription skillDescription; - skillDescription.skillName = desc.skillId.skillName; - skillDescription.description = desc.description; - skillDescription.iceInfo = info.provider->ice_toString(); - - skillDescription.rootProfileParameterization = - armarx::aron::data::Dict::FromAronDictDTO(desc.rootProfileDefaults); - - armarx::core::time::fromIce(desc.timeout, skillDescription.timeout); - - if (desc.acceptedType) - { - auto t = aron::type::Object::FromAronObjectDTO(desc.acceptedType); - - aron::type::converter::AronDatatypeConverterVisitor c; - aron::type::visit(c, t); - - skillDescription.acceptedType = aron::data::Dict::DynamicCastAndCheck(c.latest); - } + armem::toAron(skillDescription, d); armem::Commit commit; auto& entityUpdate = commit.add(); @@ -68,7 +50,7 @@ namespace armarx::skills::segment entityUpdate.sentTime = armem::Time::Now(); entityUpdate.arrivedTime = armem::Time::Now(); entityUpdate.instancesData = {skillDescription.toAron()}; - entityUpdate.entityID = provId.withEntityName(skillDescription.skillName); + entityUpdate.entityID = provId.withEntityName(d.skillId.skillName); // Commit data to memory and notify iceMemory.commit(commit); diff --git a/source/RobotAPI/libraries/armem_skills/server/segment/ExecutableSkillLibrarySegment.h b/source/RobotAPI/libraries/armem_skills/server/segment/ExecutableSkillLibrarySegment.h index a2d4227bb..e71a8a74a 100644 --- a/source/RobotAPI/libraries/armem_skills/server/segment/ExecutableSkillLibrarySegment.h +++ b/source/RobotAPI/libraries/armem_skills/server/segment/ExecutableSkillLibrarySegment.h @@ -4,19 +4,18 @@ #include <RobotAPI/libraries/armem/server/segment/SpecializedSegment.h> // ArmarX +#include <ArmarXCore/core/application/properties/PropertyDefinitionContainer.h> #include <ArmarXCore/interface/core/Profiler.h> #include <ArmarXCore/observers/ObserverObjectFactories.h> -#include <ArmarXCore/core/application/properties/PropertyDefinitionContainer.h> #include <RobotAPI/interface/skills/SkillManagerInterface.h> #include <RobotAPI/interface/skills/SkillProviderInterface.h> - #include <RobotAPI/libraries/armem_skills/aron/Skill.aron.generated.h> +#include <RobotAPI/libraries/skills/core/ProviderInfo.h> namespace armarx::skills::segment { - class ExecutableSkillLibraryCoreSegment : - public armem::server::segment::SpecializedCoreSegment + class ExecutableSkillLibraryCoreSegment : public armem::server::segment::SpecializedCoreSegment { using Base = armem::server::segment::SpecializedCoreSegment; @@ -25,10 +24,10 @@ namespace armarx::skills::segment ExecutableSkillLibraryCoreSegment(armem::server::MemoryToIceAdapter& iceMemory); - void defineProperties(PropertyDefinitionsPtr defs, const std::string &prefix); + void defineProperties(PropertyDefinitionsPtr defs, const std::string& prefix); void init(); - void addSkillProvider(const skills::manager::dto::ProviderInfo& info); + void addSkillProvider(const skills::ProviderInfo& info); void removeSkillProvider(const std::string& providerName); size_t size() const; @@ -36,4 +35,4 @@ namespace armarx::skills::segment private: std::map<std::string, std::map<std::string, skills::manager::dto::ProviderInfo>> skills; }; -} +} // namespace armarx::skills::segment diff --git a/source/RobotAPI/libraries/armem_skills/server/segment/SkillEventSegment.cpp b/source/RobotAPI/libraries/armem_skills/server/segment/SkillEventSegment.cpp index 8960afd4b..6328e6d73 100644 --- a/source/RobotAPI/libraries/armem_skills/server/segment/SkillEventSegment.cpp +++ b/source/RobotAPI/libraries/armem_skills/server/segment/SkillEventSegment.cpp @@ -4,8 +4,8 @@ #include <RobotAPI/libraries/armem/server/MemoryToIceAdapter.h> #include <RobotAPI/libraries/armem_skills/aron/Skill.aron.generated.h> +#include <RobotAPI/libraries/armem_skills/aron_conversions.h> #include <RobotAPI/libraries/aron/converter/json/NLohmannJSONConverter.h> -#include <RobotAPI/libraries/skills/core/SkillStatusUpdate.h> namespace armarx::skills::segment { @@ -30,34 +30,15 @@ namespace armarx::skills::segment } void - SkillEventCoreSegment::addSkillUpdateEvent( - const skills::provider::dto::SkillStatusUpdate& update, - const std::string& providerName) + SkillEventCoreSegment::addSkillUpdateEvent(const skills::SkillStatusUpdate& update) { - // add update for skill to memory - static std::map<armarx::skills::provider::dto::Execution::Status, std::string> - ExecutionStatus2String = { - {armarx::skills::provider::dto::Execution::Status::Constructing, "Constructing"}, - {armarx::skills::provider::dto::Execution::Status::Initializing, "Initializing"}, - {armarx::skills::provider::dto::Execution::Status::Preparing, "Preparing"}, - {armarx::skills::provider::dto::Execution::Status::Running, "Running"}, - {armarx::skills::provider::dto::Execution::Status::Aborted, "Aborted"}, - {armarx::skills::provider::dto::Execution::Status::Failed, "Failed"}, - {armarx::skills::provider::dto::Execution::Status::Succeeded, "Succeeded"}}; - - auto up = skills::SkillStatusUpdate::FromIce(update, providerName); - // create commit about new update armarx::skills::arondto::SkillExecutionEvent event; - event.providerName = up.executionId.skillId.providerName; - event.skillName = up.executionId.skillId.skillName; - event.status = ExecutionStatus2String.at(update.header.status); - event.params = up.usedParameterization.parameterization; - event.data = up.data; + armem::toAron(event, update); armem::MemoryID commitId = id(); - commitId.providerSegmentName = event.providerName; - commitId.entityName = event.skillName; + commitId.providerSegmentName = event.skillId.providerId.providerName; + commitId.entityName = event.skillId.skillName; auto aron = event.toAron(); @@ -68,6 +49,44 @@ namespace armarx::skills::segment entityUpdate.instancesData = {aron}; entityUpdate.entityID = commitId; - iceMemory.commit(comm); + iceMemory.commitLocking(comm); + } + + std::map<skills::SkillExecutionID, skills::SkillStatusUpdate> + SkillEventCoreSegment::getLatestSkillEvents(int n) + { + std::map<skills::SkillExecutionID, skills::SkillStatusUpdate> ret; + auto coreSegment = this->segmentPtr; + ARMARX_CHECK(coreSegment); + + // 1. get all events and sort them by timestamp. + std::vector<skills::SkillStatusUpdate> sorted; + coreSegment->forEachInstance( + [&sorted](const armem::wm::EntityInstance& i) + { + auto event = i.dataAs<armarx::skills::arondto::SkillExecutionEvent>(); + skills::SkillStatusUpdate up({{{""}, ""}, "", armarx::core::time::DateTime::Now()}, + {nullptr, nullptr}); + armem::fromAron(event, up); + sorted.emplace_back(std::move(up)); + }); + + std::sort(sorted.begin(), + sorted.end(), + [](const skills::SkillStatusUpdate& a, const skills::SkillStatusUpdate& b) + { return b < a; }); + + for (const auto& el : sorted) + { + if (ret.size() >= (size_t)n) + { + break; + } + + ret.emplace( + std::piecewise_construct, std::make_tuple(el.executionId), std::make_tuple(el)); + } + + return ret; } } // namespace armarx::skills::segment diff --git a/source/RobotAPI/libraries/armem_skills/server/segment/SkillEventSegment.h b/source/RobotAPI/libraries/armem_skills/server/segment/SkillEventSegment.h index 7d67fc2d6..492c26090 100644 --- a/source/RobotAPI/libraries/armem_skills/server/segment/SkillEventSegment.h +++ b/source/RobotAPI/libraries/armem_skills/server/segment/SkillEventSegment.h @@ -9,6 +9,7 @@ #include <RobotAPI/interface/skills/SkillManagerInterface.h> #include <RobotAPI/interface/skills/SkillProviderInterface.h> #include <RobotAPI/libraries/armem_skills/aron/Skill.aron.generated.h> +#include <RobotAPI/libraries/skills/core/SkillStatusUpdate.h> namespace armarx::skills::segment { @@ -24,8 +25,9 @@ namespace armarx::skills::segment void defineProperties(PropertyDefinitionsPtr defs, const std::string& prefix); void init(); - void addSkillUpdateEvent(const skills::provider::dto::SkillStatusUpdate& update, - const std::string& providerName); + void addSkillUpdateEvent(const skills::SkillStatusUpdate& update); + + std::map<skills::SkillExecutionID, skills::SkillStatusUpdate> getLatestSkillEvents(int n); private: }; diff --git a/source/RobotAPI/libraries/armem_skills/server/segment/SkillExecutionRequestSegment.cpp b/source/RobotAPI/libraries/armem_skills/server/segment/SkillExecutionRequestSegment.cpp index 818f3d13b..4b57e0b44 100644 --- a/source/RobotAPI/libraries/armem_skills/server/segment/SkillExecutionRequestSegment.cpp +++ b/source/RobotAPI/libraries/armem_skills/server/segment/SkillExecutionRequestSegment.cpp @@ -1,33 +1,36 @@ #include "SkillExecutionRequestSegment.h" -#include <RobotAPI/libraries/armem/server/MemoryToIceAdapter.h> #include <SimoxUtility/algorithm/string.h> -#include <RobotAPI/libraries/aron/converter/json/NLohmannJSONConverter.h> - +#include <RobotAPI/libraries/armem/server/MemoryToIceAdapter.h> #include <RobotAPI/libraries/armem_skills/aron/Skill.aron.generated.h> - +#include <RobotAPI/libraries/armem_skills/aron_conversions.h> +#include <RobotAPI/libraries/aron/converter/json/NLohmannJSONConverter.h> namespace armarx::skills::segment { - SkillExecutionRequestCoreSegment::SkillExecutionRequestCoreSegment(armem::server::MemoryToIceAdapter& iceMemory): + SkillExecutionRequestCoreSegment::SkillExecutionRequestCoreSegment( + armem::server::MemoryToIceAdapter& iceMemory) : Base(iceMemory, CoreSegmentName, skills::arondto::SkillExecutionRequest::ToAronType()) { } - void SkillExecutionRequestCoreSegment::defineProperties(PropertyDefinitionsPtr defs, const std::string &prefix) + void + SkillExecutionRequestCoreSegment::defineProperties(PropertyDefinitionsPtr defs, + const std::string& prefix) { // No properties! (meaning no name and no max size) } - void SkillExecutionRequestCoreSegment::init() + void + SkillExecutionRequestCoreSegment::init() { Base::init(); } - - skills::manager::dto::SkillExecutionRequest SkillExecutionRequestCoreSegment::convertCommit(const aron::data::dto::DictPtr& commitData) + skills::SkillExecutionRequest + SkillExecutionRequestCoreSegment::convertCommit(const aron::data::dto::DictPtr& commitData) { // convert ice commitData to aron auto commitDataAron = std::make_shared<aron::data::Dict>(commitData); @@ -36,23 +39,20 @@ namespace armarx::skills::segment skills::arondto::SkillExecutionRequest request; request.fromAron(commitDataAron); - skills::manager::dto::SkillExecutionRequest info; - info.skillId = {request.providerName, request.skillName}; - info.params = request.params->toAronDictDTO(); + skills::SkillExecutionRequest info({{""}, ""}, "", nullptr); + armem::fromAron(request, info); return info; } - - void SkillExecutionRequestCoreSegment::addSkillExecutionRequest(const skills::manager::dto::SkillExecutionRequest& info) + void + SkillExecutionRequestCoreSegment::addSkillExecutionRequest( + const skills::SkillExecutionRequest& info) { // override directly execution to add a request to the memory armem::Commit comm; skills::arondto::SkillExecutionRequest request; - request.executorName = info.executorName; - request.providerName = info.skillId.providerName; - request.skillName = info.skillId.skillName; - request.params = aron::data::Dict::FromAronDictDTO(info.params); + armem::toAron(request, info); auto aron = request.toAron(); @@ -60,11 +60,11 @@ namespace armarx::skills::segment auto& entityUpdate = comm.add(); armem::MemoryID skillExecutionMemID = id(); - skillExecutionMemID.providerSegmentName = request.providerName; - skillExecutionMemID.entityName = request.skillName; + skillExecutionMemID.providerSegmentName = request.skillId.providerId.providerName; + skillExecutionMemID.entityName = request.skillId.skillName; entityUpdate.entityID = skillExecutionMemID; - entityUpdate.instancesData = { aron }; + entityUpdate.instancesData = {aron}; entityUpdate.confidence = 1.0; entityUpdate.referencedTime = armem::Time::Now(); } @@ -77,7 +77,7 @@ namespace armarx::skills::segment skillExecutionMemID.entityName = "All Skill Execution Requests"; entityUpdate.entityID = skillExecutionMemID; - entityUpdate.instancesData = { aron }; + entityUpdate.instancesData = {aron}; entityUpdate.confidence = 1.0; entityUpdate.referencedTime = armem::Time::Now(); } @@ -85,4 +85,4 @@ namespace armarx::skills::segment iceMemory.commit(comm); } -} +} // namespace armarx::skills::segment diff --git a/source/RobotAPI/libraries/armem_skills/server/segment/SkillExecutionRequestSegment.h b/source/RobotAPI/libraries/armem_skills/server/segment/SkillExecutionRequestSegment.h index 262bc829b..c5af9dd8a 100644 --- a/source/RobotAPI/libraries/armem_skills/server/segment/SkillExecutionRequestSegment.h +++ b/source/RobotAPI/libraries/armem_skills/server/segment/SkillExecutionRequestSegment.h @@ -4,17 +4,17 @@ #include <RobotAPI/libraries/armem/server/segment/SpecializedSegment.h> // ArmarX +#include <ArmarXCore/core/application/properties/PropertyDefinitionContainer.h> #include <ArmarXCore/interface/core/Profiler.h> #include <ArmarXCore/observers/ObserverObjectFactories.h> -#include <ArmarXCore/core/application/properties/PropertyDefinitionContainer.h> #include <RobotAPI/interface/skills/SkillManagerInterface.h> #include <RobotAPI/interface/skills/SkillProviderInterface.h> +#include <RobotAPI/libraries/skills/core/SkillExecutionRequest.h> namespace armarx::skills::segment { - class SkillExecutionRequestCoreSegment : - public armem::server::segment::SpecializedCoreSegment + class SkillExecutionRequestCoreSegment : public armem::server::segment::SpecializedCoreSegment { using Base = armem::server::segment::SpecializedCoreSegment; @@ -23,11 +23,11 @@ namespace armarx::skills::segment SkillExecutionRequestCoreSegment(armem::server::MemoryToIceAdapter& iceMemory); - void defineProperties(PropertyDefinitionsPtr defs, const std::string &prefix); + void defineProperties(PropertyDefinitionsPtr defs, const std::string& prefix); void init(); - skills::manager::dto::SkillExecutionRequest convertCommit(const aron::data::dto::DictPtr& commitData); + skills::SkillExecutionRequest convertCommit(const aron::data::dto::DictPtr& commitData); - void addSkillExecutionRequest(const skills::manager::dto::SkillExecutionRequest& info); + void addSkillExecutionRequest(const skills::SkillExecutionRequest& info); }; -} +} // namespace armarx::skills::segment diff --git a/source/RobotAPI/libraries/aron/core/data/variant/container/Dict.cpp b/source/RobotAPI/libraries/aron/core/data/variant/container/Dict.cpp index bed880399..1d85a7f80 100644 --- a/source/RobotAPI/libraries/aron/core/data/variant/container/Dict.cpp +++ b/source/RobotAPI/libraries/aron/core/data/variant/container/Dict.cpp @@ -347,65 +347,68 @@ namespace armarx::aron::data { ARMARX_TRACE; auto objectTypeNav = type::Object::DynamicCastAndCheck(type); - for (const auto& [key, nav] : childrenNavigators) + + // here we need to iterate over the elements of the type. That must be fulfilled. + // If this dict has more members that its fine. + for (const auto& [key, childTypeNav] : objectTypeNav->getMemberTypes()) { - if (!objectTypeNav->hasMemberType(key)) + if (!this->hasElement(key)) { - ARMARX_TRACE; - return false; + return false; // key must exist } - auto childTypeNav = objectTypeNav->getMemberType(key); - if (!nav) + if (!childTypeNav) { - ARMARX_TRACE; - if (childTypeNav && childTypeNav->getMaybe() == type::Maybe::NONE) + continue; // no information whih is fine --> continue + } + + auto childNav = this->getElement(key); + if (childNav) + { + if (not childNav->fullfillsType(childTypeNav)) { - ARMARX_TRACE; return false; } - ARMARX_TRACE; - return true; + // else childnav fulfills type which is fine --> continue + continue; } - if (!nav->fullfillsType(childTypeNav)) + else { - ARMARX_TRACE; - return false; + if (childTypeNav->getMaybe() == type::Maybe::NONE) + { + return false; + } + // else: childTypeNav == maybe && nav == null which is fine --> continue + continue; } } - ARMARX_TRACE; return true; } case type::Descriptor::DICT: { ARMARX_TRACE; auto dictTypeNav = type::Dict::DynamicCastAndCheck(type); - for (const auto& [key, nav] : childrenNavigators) + for (const auto& [key, childNav] : childrenNavigators) { (void)key; auto childTypeNav = dictTypeNav->getAcceptedType(); - if (!nav) + if (!childNav) { - ARMARX_TRACE; if (childTypeNav && childTypeNav->getMaybe() == type::Maybe::NONE) { - ARMARX_TRACE; return false; } - ARMARX_TRACE; - return true; + // else childTypeNav is null or maybe and childNav is null which is fine. + continue; } - if (!nav->fullfillsType(childTypeNav)) + if (!childNav->fullfillsType(childTypeNav)) { - ARMARX_TRACE; return false; } } - ARMARX_TRACE; return true; } default: - ARMARX_TRACE; return false; } } diff --git a/source/RobotAPI/libraries/aron/core/data/variant/container/List.cpp b/source/RobotAPI/libraries/aron/core/data/variant/container/List.cpp index 83e23f76f..82955eabf 100644 --- a/source/RobotAPI/libraries/aron/core/data/variant/container/List.cpp +++ b/source/RobotAPI/libraries/aron/core/data/variant/container/List.cpp @@ -271,59 +271,51 @@ namespace armarx::aron::data { if (childTypeNav && childTypeNav->getMaybe() == type::Maybe::NONE) { - ARMARX_TRACE; return false; } - ARMARX_TRACE; - return true; + continue; } if (!nav->fullfillsType(childTypeNav)) { - ARMARX_TRACE; return false; } } - ARMARX_TRACE; return true; } case type::Descriptor::TUPLE: { + ARMARX_TRACE; auto tupleTypeNav = type::Tuple::DynamicCastAndCheck(type); unsigned int i = 0; - for (const auto& nav : childrenNavigators) + for (const auto& childTypeNav : tupleTypeNav->getAcceptedTypes()) { - if (!tupleTypeNav->hasAcceptedType(i)) + if (!this->hasElement(i)) { - ARMARX_TRACE; return false; } - auto childTypeNav = tupleTypeNav->getAcceptedType(i); - if (!nav) + auto childNav = this->getElement(i); + if (!childNav) { if (childTypeNav && childTypeNav->getMaybe() == type::Maybe::NONE) { - ARMARX_TRACE; return false; } - ARMARX_TRACE; - return false; + continue; } - if (!nav->fullfillsType(tupleTypeNav->getAcceptedType(i))) + if (!childNav->fullfillsType(tupleTypeNav->getAcceptedType(i))) { - ARMARX_TRACE; return false; } } - ARMARX_TRACE; return true; } case type::Descriptor::PAIR: { + ARMARX_TRACE; auto pairTypeNav = type::Pair::DynamicCastAndCheck(type); if (childrenSize() != 2) { - ARMARX_TRACE; return false; } auto firstChildTypeNav = pairTypeNav->getFirstAcceptedType(); @@ -331,24 +323,17 @@ namespace armarx::aron::data { if (firstChildTypeNav && firstChildTypeNav->getMaybe() == type::Maybe::NONE) { - ARMARX_TRACE; return false; } - ARMARX_TRACE; - return false; } auto secondChildTypeNav = pairTypeNav->getSecondAcceptedType(); if (!childrenNavigators[1]) { if (secondChildTypeNav && secondChildTypeNav->getMaybe() == type::Maybe::NONE) { - ARMARX_TRACE; return false; } - ARMARX_TRACE; - return false; } - ARMARX_TRACE; return childrenNavigators[0]->fullfillsType(firstChildTypeNav) && childrenNavigators[1]->fullfillsType(secondChildTypeNav); } diff --git a/source/RobotAPI/libraries/skills/core/ProviderID.cpp b/source/RobotAPI/libraries/skills/core/ProviderID.cpp index c347dcf2f..83330c897 100644 --- a/source/RobotAPI/libraries/skills/core/ProviderID.cpp +++ b/source/RobotAPI/libraries/skills/core/ProviderID.cpp @@ -1,5 +1,7 @@ #include "ProviderID.h" +#include "SkillID.h" + namespace armarx { namespace skills @@ -8,8 +10,10 @@ namespace armarx { } - ProviderID::ProviderID(const skills::SkillID& skillid) : providerName(skillid.providerName) + ProviderID::ProviderID(const skills::SkillID& skillid) { + ARMARX_CHECK(skillid.providerId.has_value()); + providerName = skillid.providerId->providerName; } bool @@ -37,7 +41,7 @@ namespace armarx } ProviderID - ProviderID::FromIce(const provider::dto::ProviderID& s) + ProviderID::FromIce(const callback::dto::ProviderID& s) { return ProviderID(s.providerName); } @@ -48,8 +52,8 @@ namespace armarx return {providerName}; } - provider::dto::ProviderID - ProviderID::toProviderIce() const + callback::dto::ProviderID + ProviderID::toCallbackIce() const { return {providerName}; } diff --git a/source/RobotAPI/libraries/skills/core/ProviderID.h b/source/RobotAPI/libraries/skills/core/ProviderID.h index 7aee01fd7..0e0159d9d 100644 --- a/source/RobotAPI/libraries/skills/core/ProviderID.h +++ b/source/RobotAPI/libraries/skills/core/ProviderID.h @@ -6,12 +6,12 @@ #include <RobotAPI/interface/skills/SkillManagerInterface.h> #include <RobotAPI/libraries/aron/core/data/variant/container/Dict.h> -#include "SkillID.h" - namespace armarx { namespace skills { + class SkillID; + class ProviderID { public: @@ -28,10 +28,10 @@ namespace armarx bool operator<(const ProviderID& other) const; manager::dto::ProviderID toManagerIce() const; - provider::dto::ProviderID toProviderIce() const; + callback::dto::ProviderID toCallbackIce() const; static ProviderID FromIce(const manager::dto::ProviderID&); - static ProviderID FromIce(const provider::dto::ProviderID&); + static ProviderID FromIce(const callback::dto::ProviderID&); std::string toString(const std::string& prefix = "") const; }; diff --git a/source/RobotAPI/libraries/skills/core/ProviderInfo.cpp b/source/RobotAPI/libraries/skills/core/ProviderInfo.cpp index ec12cb9ae..7ae36dbfa 100644 --- a/source/RobotAPI/libraries/skills/core/ProviderInfo.cpp +++ b/source/RobotAPI/libraries/skills/core/ProviderInfo.cpp @@ -7,20 +7,33 @@ namespace armarx ProviderInfo::ProviderInfo(const ProviderID& pid, const provider::dti::SkillProviderInterfacePrx& i, const std::map<SkillID, SkillDescription>& skills) : - providerId(pid), provider(i), providedSkills(skills) + providerId(pid), providerInterface(i), providedSkills(skills) { } + skills::manager::dto::ProviderInfo + ProviderInfo::toIce() const + { + skills::manager::dto::ProviderInfo ret; + ret.providerId = providerId.toManagerIce(); + ret.providerInterface = providerInterface; + + for (const auto& [k, v] : providedSkills) + { + ret.providedSkills[k.toManagerIce()] = v.toManagerIce(); + } + return ret; + } + ProviderInfo ProviderInfo::FromIce(const manager::dto::ProviderInfo& i) { std::map<SkillID, SkillDescription> m; for (const auto& [k, v] : i.providedSkills) { - m.insert({skills::SkillID::FromIce(k, i.providerId.providerName), - skills::SkillDescription::FromIce(v)}); + m.insert({skills::SkillID::FromIce(k), skills::SkillDescription::FromIce(v)}); } - return ProviderInfo(skills::ProviderID::FromIce(i.providerId), i.provider, m); + return ProviderInfo(skills::ProviderID::FromIce(i.providerId), i.providerInterface, m); } } // namespace skills } // namespace armarx diff --git a/source/RobotAPI/libraries/skills/core/ProviderInfo.h b/source/RobotAPI/libraries/skills/core/ProviderInfo.h index 2213d1615..92c5484c3 100644 --- a/source/RobotAPI/libraries/skills/core/ProviderInfo.h +++ b/source/RobotAPI/libraries/skills/core/ProviderInfo.h @@ -20,7 +20,7 @@ namespace armarx { public: ProviderID providerId; - provider::dti::SkillProviderInterfacePrx provider; + provider::dti::SkillProviderInterfacePrx providerInterface; std::map<SkillID, SkillDescription> providedSkills; ProviderInfo() = delete; @@ -28,6 +28,8 @@ namespace armarx const provider::dti::SkillProviderInterfacePrx& i, const std::map<SkillID, SkillDescription>& skills); + skills::manager::dto::ProviderInfo toIce() const; + static ProviderInfo FromIce(const manager::dto::ProviderInfo&); }; } // namespace skills diff --git a/source/RobotAPI/libraries/skills/core/Skill.cpp b/source/RobotAPI/libraries/skills/core/Skill.cpp index e104ef656..19169d627 100644 --- a/source/RobotAPI/libraries/skills/core/Skill.cpp +++ b/source/RobotAPI/libraries/skills/core/Skill.cpp @@ -18,7 +18,7 @@ namespace armarx conditionCallbacks.push_back({f, cb}); } - void + Skill::InitResult Skill::_init() { //ARMARX_IMPORTANT << "Initializing skill '" << description.skillName << "'"; @@ -61,21 +61,41 @@ namespace armarx } } }); + return {.status = TerminatedSkillStatus::Succeeded}; } - void + Skill::PrepareResult Skill::_prepare() { - // Nothing here yet... + if (checkWhetherSkillShouldStopASAP()) + { + return {.status = ActiveOrTerminatedSkillStatus::Aborted}; + } + + // Default nothing to prepare + std::scoped_lock l(parametersMutex); + if (not description.acceptedType) + { + return {.status = ActiveOrTerminatedSkillStatus::Succeeded}; + } + if (this->parameters && this->parameters->fullfillsType(description.acceptedType)) + { + // wait until parameters fulfill type + return {.status = ActiveOrTerminatedSkillStatus::Succeeded}; + } + + // false if we have to wait for parameters + return {.status = ActiveOrTerminatedSkillStatus::Running}; } - void + Skill::MainResult Skill::_main() { // Nothing here yet... + return {.status = TerminatedSkillStatus::Succeeded}; } - void + Skill::ExitResult Skill::_exit() { // ARMARX_IMPORTANT << "Exiting Skill '" << description.skillName << "'"; @@ -86,41 +106,39 @@ namespace armarx conditionCheckingThread.join(); } exited = armarx::core::time::DateTime::Now(); + return {.status = TerminatedSkillStatus::Succeeded}; } Skill::InitResult Skill::initSkill() { - this->_init(); - return this->init(); - } - - bool - Skill::skillPreparationFinished() const - { - return this->preparationFinished(); + auto _res = this->_init(); + auto res = this->init(); + return {.status = skills::MergeSkillStatus(_res.status, res.status)}; } Skill::PrepareResult Skill::prepareSkill() { - this->_prepare(); - return this->prepare(); + auto _res = this->_prepare(); + auto res = this->prepare(); + return {.status = skills::MergeSkillStatus(_res.status, res.status)}; } Skill::MainResult Skill::mainOfSkill() { - this->_main(); - return this->main(); + auto _res = this->_main(); + auto res = this->main(); + return {.status = skills::MergeSkillStatus(_res.status, res.status), .data = res.data}; } Skill::ExitResult Skill::exitSkill() { - auto ret = this->exit(); - this->_exit(); - return ret; + auto res = this->exit(); + auto _res = this->_exit(); + return {.status = skills::MergeSkillStatus(_res.status, res.status)}; } void @@ -171,26 +189,6 @@ namespace armarx return {.status = TerminatedSkillStatus::Succeeded}; } - bool - Skill::preparationFinished() const - { - std::scoped_lock l(parametersMutex); - if (description.acceptedType != nullptr) - { - if (this->parameters != nullptr) - { - // wait until parameters fulfill type - return this->parameters->fullfillsType(description.acceptedType); - } - - // false if we have to wait for parameters - return false; - } - - // always true if no type set. - return true; - } - // always called before main (should not take longer than 100ms) Skill::PrepareResult Skill::prepare() diff --git a/source/RobotAPI/libraries/skills/core/Skill.h b/source/RobotAPI/libraries/skills/core/Skill.h index 30f1f666e..bc7402a97 100644 --- a/source/RobotAPI/libraries/skills/core/Skill.h +++ b/source/RobotAPI/libraries/skills/core/Skill.h @@ -60,12 +60,22 @@ namespace armarx SkillID getSkillId() const { - return {providerName, description.skillId.providerName}; + return description.skillId; } - PrepareResult prepareSkill(); + SkillDescription + getSkillDescription() const + { + return description; + } + + void + setProviderId(const skills::ProviderID& pid) + { + description.skillId.providerId = pid; + } - bool skillPreparationFinished() const; + PrepareResult prepareSkill(); InitResult initSkill(); @@ -95,6 +105,14 @@ namespace armarx } } + // hard set the parameters, ignoring everything that has been set or merged before + void + setParameters(const aron::data::DictPtr& d) + { + std::scoped_lock l(this->parametersMutex); + this->parameters = d; + } + // get the parameters aron::data::DictPtr getParameters() const @@ -110,27 +128,24 @@ namespace armarx void notifyTimeoutReached(); // helper methods to do all the static initialization stuff - void _init(); - void _prepare(); - void _main(); - void _exit(); + InitResult _init(); + PrepareResult _prepare(); + MainResult _main(); + ExitResult _exit(); - private: /// Override this method with the actual implementation. virtual InitResult init(); /// Override this method with the actual implementation. virtual PrepareResult prepare(); - /// Override this method with the actual implementation - virtual bool preparationFinished() const; - /// Override this method with the actual implementation. The callback is for status updates to the calling instance virtual MainResult main(); /// Override this method with the actual implementation. virtual ExitResult exit(); + private: /// Override these methods if you want to do something special when notification comes virtual void onTimeoutReached(); virtual void onStopRequested(); @@ -141,25 +156,24 @@ namespace armarx std::function<void()>&& cb); public: - // The descripion of the skill, which will be available via the provider/manager - const SkillDescription description; - // running params armarx::core::time::DateTime started = armarx::core::time::DateTime::Invalid(); armarx::core::time::DateTime exited = armarx::core::time::DateTime::Invalid(); // parameterization.Will be set from implementation wrapper. - // const params after initialization + // const params after initialization!! std::function<void(const SkillStatus s, const armarx::aron::data::DictPtr&)> callback; manager::dti::SkillManagerInterfacePrx manager = nullptr; - std::string providerName = "INVALID PROVIDER NAME"; std::string executorName = "INVALID EXECUTOR NAME"; + protected: // non-const params mutable std::mutex parametersMutex; armarx::aron::data::DictPtr parameters; - protected: + // The descripion of the skill + SkillDescription description; + // active conditions. First is condition (bool return func) mutable std::mutex conditionCallbacksMutex; std::vector<std::pair<std::function<bool()>, std::function<void()>>> conditionCallbacks; diff --git a/source/RobotAPI/libraries/skills/core/SkillDescription.cpp b/source/RobotAPI/libraries/skills/core/SkillDescription.cpp index fb5f6f062..d8e7885a0 100644 --- a/source/RobotAPI/libraries/skills/core/SkillDescription.cpp +++ b/source/RobotAPI/libraries/skills/core/SkillDescription.cpp @@ -32,20 +32,47 @@ namespace armarx } provider::dto::SkillDescription - SkillDescription::toIce() const + SkillDescription::toProviderIce() const { provider::dto::SkillDescription ret; ret.acceptedType = aron::type::Object::ToAronObjectDTO(acceptedType); ret.description = description; ret.skillId = skillId.toProviderIce(); - ret.rootProfileDefaults = rootProfileParameterization->toAronDictDTO(); + ret.rootProfileDefaults = aron::data::Dict::ToAronDictDTO(rootProfileParameterization); armarx::core::time::toIce(ret.timeout, timeout); return ret; } + manager::dto::SkillDescription + SkillDescription::toManagerIce() const + { + manager::dto::SkillDescription ret; + ret.acceptedType = aron::type::Object::ToAronObjectDTO(acceptedType); + ret.description = description; + ret.skillId = skillId.toManagerIce(); + ret.rootProfileDefaults = aron::data::Dict::ToAronDictDTO(rootProfileParameterization); + + armarx::core::time::toIce(ret.timeout, timeout); + return ret; + } + + SkillDescription + SkillDescription::FromIce(const provider::dto::SkillDescription& i, + const std::optional<ProviderID>& pid) + { + armarx::core::time::Duration _d; + armarx::core::time::fromIce(i.timeout, _d); + return SkillDescription( + SkillID::FromIce(i.skillId, pid), + i.description, + armarx::aron::data::Dict::FromAronDictDTO(i.rootProfileDefaults), + _d, + armarx::aron::type::Object::FromAronObjectDTO(i.acceptedType)); + } + SkillDescription - SkillDescription::FromIce(const provider::dto::SkillDescription& i) + SkillDescription::FromIce(const manager::dto::SkillDescription& i) { armarx::core::time::Duration _d; armarx::core::time::fromIce(i.timeout, _d); diff --git a/source/RobotAPI/libraries/skills/core/SkillDescription.h b/source/RobotAPI/libraries/skills/core/SkillDescription.h index e1e5b4fcf..1fc370e2c 100644 --- a/source/RobotAPI/libraries/skills/core/SkillDescription.h +++ b/source/RobotAPI/libraries/skills/core/SkillDescription.h @@ -30,6 +30,7 @@ namespace armarx struct SkillDescription { SkillDescription() = delete; + SkillDescription(const SkillDescription&) = default; SkillDescription(const SkillID& id, const std::string& desc, const aron::data::DictPtr& data = nullptr, @@ -37,6 +38,7 @@ namespace armarx armarx::core::time::Duration::MilliSeconds(-1), const aron::type::ObjectPtr& acceptedType = nullptr); + SkillDescription& operator=(const SkillDescription&) = default; SkillID skillId; std::string description; @@ -44,9 +46,15 @@ namespace armarx armarx::core::time::Duration timeout; aron::type::ObjectPtr acceptedType; - provider::dto::SkillDescription toIce() const; + provider::dto::SkillDescription toProviderIce() const; + manager::dto::SkillDescription toManagerIce() const; - static SkillDescription FromIce(const provider::dto::SkillDescription& i); + static SkillDescription FromIce(const provider::dto::SkillDescription& i, + const std::optional<ProviderID>& = std::nullopt); + static SkillDescription FromIce(const manager::dto::SkillDescription& i); }; + + template <class T> + concept isSkillDescription = std::is_base_of<SkillDescription, T>::value; } // namespace skills } // namespace armarx diff --git a/source/RobotAPI/libraries/skills/core/SkillExecutionID.cpp b/source/RobotAPI/libraries/skills/core/SkillExecutionID.cpp index 3efb06d9e..f048167a1 100644 --- a/source/RobotAPI/libraries/skills/core/SkillExecutionID.cpp +++ b/source/RobotAPI/libraries/skills/core/SkillExecutionID.cpp @@ -4,7 +4,7 @@ namespace armarx { namespace skills { - SkillExecutionId::SkillExecutionId(const SkillID& id, + SkillExecutionID::SkillExecutionID(const SkillID& id, const std::string& executorName, const armarx::core::time::DateTime& time) : skillId(id), executorName(executorName), executionStartedTime(time) @@ -12,18 +12,17 @@ namespace armarx } skills::manager::dto::SkillExecutionID - SkillExecutionId::toManagerIce() const + SkillExecutionID::toManagerIce() const { skills::manager::dto::SkillExecutionID ret; - ret.skillId.skillName = skillId.skillName; - ret.skillId.providerName = skillId.providerName; + ret.skillId = skillId.toManagerIce(); ret.executorName = executorName; armarx::core::time::toIce(ret.executionStartedTime, executionStartedTime); return ret; } skills::provider::dto::SkillExecutionID - SkillExecutionId::toProviderIce() const + SkillExecutionID::toProviderIce() const { skills::provider::dto::SkillExecutionID ret; ret.skillId = skillId.toProviderIce(); @@ -32,17 +31,17 @@ namespace armarx return ret; } - SkillExecutionId - SkillExecutionId::FromIce(const skills::manager::dto::SkillExecutionID& i) + SkillExecutionID + SkillExecutionID::FromIce(const skills::manager::dto::SkillExecutionID& i) { armarx::core::time::DateTime t; armarx::core::time::fromIce(i.executionStartedTime, t); return {skills::SkillID::FromIce(i.skillId), i.executorName, t}; } - SkillExecutionId - SkillExecutionId::FromIce(const skills::provider::dto::SkillExecutionID& i, - const std::string& providerName) + SkillExecutionID + SkillExecutionID::FromIce(const skills::provider::dto::SkillExecutionID& i, + const std::optional<skills::ProviderID>& providerName) { armarx::core::time::DateTime t; armarx::core::time::fromIce(i.executionStartedTime, t); diff --git a/source/RobotAPI/libraries/skills/core/SkillExecutionID.h b/source/RobotAPI/libraries/skills/core/SkillExecutionID.h index 356aec611..7ba3ea987 100644 --- a/source/RobotAPI/libraries/skills/core/SkillExecutionID.h +++ b/source/RobotAPI/libraries/skills/core/SkillExecutionID.h @@ -16,19 +16,19 @@ namespace armarx { namespace skills { - struct SkillExecutionId + struct SkillExecutionID { SkillID skillId; std::string executorName; armarx::core::time::DateTime executionStartedTime; - SkillExecutionId() = delete; - SkillExecutionId(const SkillID&, + SkillExecutionID() = delete; + SkillExecutionID(const SkillID&, const std::string& executorName, const armarx::core::time::DateTime&); bool - operator==(const SkillExecutionId& other) const + operator==(const SkillExecutionID& other) const { if (skillId != other.skillId) { @@ -46,7 +46,7 @@ namespace armarx } bool - operator<(const SkillExecutionId& other) const + operator<(const SkillExecutionID& other) const { // We explicitly do not compare skillIds as we ONLY want to bring the executionids in some (temporal) order return executionStartedTime < other.executionStartedTime; @@ -56,10 +56,10 @@ namespace armarx skills::provider::dto::SkillExecutionID toProviderIce() const; - static SkillExecutionId FromIce(const skills::manager::dto::SkillExecutionID&); + static SkillExecutionID FromIce(const skills::manager::dto::SkillExecutionID&); - static SkillExecutionId FromIce(const skills::provider::dto::SkillExecutionID&, - const std::string& providerName); + static SkillExecutionID FromIce(const skills::provider::dto::SkillExecutionID&, + const std::optional<skills::ProviderID>& providerName); }; } // namespace skills diff --git a/source/RobotAPI/libraries/skills/core/SkillExecutionRequest.cpp b/source/RobotAPI/libraries/skills/core/SkillExecutionRequest.cpp index d045cc239..91fca69ca 100644 --- a/source/RobotAPI/libraries/skills/core/SkillExecutionRequest.cpp +++ b/source/RobotAPI/libraries/skills/core/SkillExecutionRequest.cpp @@ -19,7 +19,7 @@ namespace armarx manager::dto::SkillExecutionRequest ret; ret.skillId = skillId.toManagerIce(); ret.executorName = executorName; - ret.params = params->toAronDictDTO(); + ret.params = armarx::aron::data::Dict::ToAronDictDTO(params); return ret; } @@ -29,7 +29,7 @@ namespace armarx provider::dto::SkillExecutionRequest ret; ret.skillId = skillId.toProviderIce(); ret.executorName = executorName; - ret.params = params->toAronDictDTO(); + ret.params = armarx::aron::data::Dict::ToAronDictDTO(params); ret.callbackInterface = callbackInterface; return ret; } @@ -44,9 +44,10 @@ namespace armarx } SkillExecutionRequest - SkillExecutionRequest::FromIce(const provider::dto::SkillExecutionRequest& req) + SkillExecutionRequest::FromIce(const provider::dto::SkillExecutionRequest& req, + const std::optional<skills::ProviderID>& providerId) { - return {skills::SkillID::FromIce(req.skillId), + return {skills::SkillID::FromIce(req.skillId, providerId), req.executorName, armarx::aron::data::Dict::FromAronDictDTO(req.params), req.callbackInterface}; diff --git a/source/RobotAPI/libraries/skills/core/SkillExecutionRequest.h b/source/RobotAPI/libraries/skills/core/SkillExecutionRequest.h index ec39e2f44..9eaa00791 100644 --- a/source/RobotAPI/libraries/skills/core/SkillExecutionRequest.h +++ b/source/RobotAPI/libraries/skills/core/SkillExecutionRequest.h @@ -27,17 +27,19 @@ namespace armarx callback::dti::SkillProviderCallbackInterfacePrx callbackInterface; SkillExecutionRequest() = delete; - SkillExecutionRequest(const skills::SkillID& skill, - const std::string executorName, - const armarx::aron::data::DictPtr& params, - const callback::dti::SkillProviderCallbackInterfacePrx& callback); + SkillExecutionRequest( + const skills::SkillID& skill, + const std::string executorName, + const armarx::aron::data::DictPtr& params, + const callback::dti::SkillProviderCallbackInterfacePrx& callback = nullptr); manager::dto::SkillExecutionRequest toManagerIce() const; provider::dto::SkillExecutionRequest toProviderIce() const; static SkillExecutionRequest FromIce(const manager::dto::SkillExecutionRequest&); static SkillExecutionRequest - FromIce(const provider::dto::SkillExecutionRequest&); + FromIce(const provider::dto::SkillExecutionRequest&, + const std::optional<skills::ProviderID>& providerId = std::nullopt); }; } // namespace skills } // namespace armarx diff --git a/source/RobotAPI/libraries/skills/core/SkillID.cpp b/source/RobotAPI/libraries/skills/core/SkillID.cpp index 80373376a..9bb0b36a8 100644 --- a/source/RobotAPI/libraries/skills/core/SkillID.cpp +++ b/source/RobotAPI/libraries/skills/core/SkillID.cpp @@ -4,14 +4,15 @@ namespace armarx { namespace skills { - SkillID::SkillID(const std::string& skillName) : SkillID(NOT_YET_KNOWN, skillName) + SkillID::SkillID(const std::string& skillName) : + providerId(std::nullopt), skillName(skillName) { } - SkillID::SkillID(const std::string& providerName, const std::string& skillName) : - providerName(providerName), skillName(skillName) + SkillID::SkillID(const ProviderID& providerId, const std::string& skillName) : + providerId(providerId), skillName(skillName) { - if (simox::alg::contains(providerName, NAME_SEPARATOR) || + if (simox::alg::contains(providerId.providerName, NAME_SEPARATOR) || simox::alg::contains(skillName, NAME_SEPARATOR)) { throw error::SkillException( @@ -20,7 +21,7 @@ namespace armarx NAME_SEPARATOR + "'."); } - if (simox::alg::contains(providerName, PREFIX_SEPARATOR) || + if (simox::alg::contains(providerId.providerName, PREFIX_SEPARATOR) || simox::alg::contains(skillName, PREFIX_SEPARATOR)) { throw error::SkillException( @@ -33,7 +34,7 @@ namespace armarx bool SkillID::operator==(const SkillID& other) const { - return providerName == other.providerName && skillName == other.skillName; + return providerId == other.providerId && skillName == other.skillName; } bool @@ -51,19 +52,25 @@ namespace armarx SkillID SkillID::FromIce(const manager::dto::SkillID& s) { - return SkillID(s.providerName, s.skillName); + return SkillID(s.providerId.providerName, s.skillName); } SkillID - SkillID::FromIce(const provider::dto::SkillID& s, const std::string& providerName) + SkillID::FromIce(const provider::dto::SkillID& s, + const std::optional<ProviderID>& providerId) { - return SkillID(providerName, s.skillName); + if (providerId.has_value()) + { + return SkillID(*providerId, s.skillName); + } + return SkillID(s.skillName); } manager::dto::SkillID SkillID::toManagerIce() const { - return {providerName, skillName}; + ARMARX_CHECK(fullySpecified()); + return {providerId->toManagerIce(), skillName}; } provider::dto::SkillID @@ -75,7 +82,12 @@ namespace armarx std::string SkillID::toString(const std::string& prefix) const { - return (prefix.empty() ? std::string("") : (prefix + PREFIX_SEPARATOR)) + providerName + + if (providerId.has_value()) + { + return (prefix.empty() ? std::string("") : (prefix + PREFIX_SEPARATOR)) + + providerId->providerName + NAME_SEPARATOR + skillName; + } + return (prefix.empty() ? std::string("") : (prefix + PREFIX_SEPARATOR)) + UNKNOWN + NAME_SEPARATOR + skillName; } } // namespace skills diff --git a/source/RobotAPI/libraries/skills/core/SkillID.h b/source/RobotAPI/libraries/skills/core/SkillID.h index a65765f0c..39561595d 100644 --- a/source/RobotAPI/libraries/skills/core/SkillID.h +++ b/source/RobotAPI/libraries/skills/core/SkillID.h @@ -7,6 +7,7 @@ #include <RobotAPI/interface/skills/SkillManagerInterface.h> +#include "ProviderID.h" #include "error/Exception.h" namespace armarx @@ -18,25 +19,47 @@ namespace armarx public: static const constexpr char* PREFIX_SEPARATOR = "->"; static const constexpr char* NAME_SEPARATOR = "/"; - static const constexpr char* NOT_YET_KNOWN = "NOT YET KNOWN"; + static const constexpr char* UNKNOWN = "UNKNOWN"; - std::string providerName; + std::optional<ProviderID> providerId; std::string skillName; SkillID() = delete; SkillID(const std::string& skillName); - SkillID(const std::string& providerName, const std::string& skillName); + SkillID(const ProviderID& providerId, const std::string& skillName); bool operator==(const SkillID& other) const; bool operator!=(const SkillID& other) const; bool operator<(const SkillID& other) const; + bool + fullySpecified() const + { + return skillSpecified() && providerSpecified(); + } + + bool + skillSpecified() const + { + return skillName != UNKNOWN; + } + + bool + providerSpecified() const + { + if (not providerId.has_value()) + { + return false; + } + return providerId->providerName != UNKNOWN; + } + manager::dto::SkillID toManagerIce() const; provider::dto::SkillID toProviderIce() const; static SkillID FromIce(const manager::dto::SkillID&); static SkillID FromIce(const provider::dto::SkillID&, - const std::string& providerName = NOT_YET_KNOWN); + const std::optional<ProviderID>& providerId = std::nullopt); std::string toString(const std::string& prefix = "") const; }; diff --git a/source/RobotAPI/libraries/skills/core/SkillStatusUpdate.cpp b/source/RobotAPI/libraries/skills/core/SkillStatusUpdate.cpp index df5950ac3..36ac32ed7 100644 --- a/source/RobotAPI/libraries/skills/core/SkillStatusUpdate.cpp +++ b/source/RobotAPI/libraries/skills/core/SkillStatusUpdate.cpp @@ -36,95 +36,142 @@ namespace armarx throw error::SkillException(__PRETTY_FUNCTION__, "Should not happen!"); } + TerminatedSkillStatus + MergeSkillStatus(const TerminatedSkillStatus t1, const TerminatedSkillStatus t2) + { + // if both are equal + if (t1 == t2) + { + return t1; + } + + // if one is failed (most unspecific result) + if (t1 == TerminatedSkillStatus::Failed or t2 == TerminatedSkillStatus::Failed) + { + return TerminatedSkillStatus::Failed; + } + + // else one must be aborted and the other one must be succeeded + return TerminatedSkillStatus::Aborted; + } + + ActiveOrTerminatedSkillStatus + MergeSkillStatus(const ActiveOrTerminatedSkillStatus t1, + const ActiveOrTerminatedSkillStatus t2) + { + // if both are equal + if (t1 == t2) + { + return t1; + } + + // if one is failed (most unspecific result) + if (t1 == ActiveOrTerminatedSkillStatus::Failed or + t2 == ActiveOrTerminatedSkillStatus::Failed) + { + return ActiveOrTerminatedSkillStatus::Failed; + } + + // if none is failed and one is aborted (second most unspecific result) + if (t1 == ActiveOrTerminatedSkillStatus::Aborted or + t2 == ActiveOrTerminatedSkillStatus::Aborted) + { + return ActiveOrTerminatedSkillStatus::Aborted; + } + + // else one must be running and the other one must be succeeded + return ActiveOrTerminatedSkillStatus::Running; + } + void - toIce(provider::dto::Execution::Status& ret, const SkillStatus& status) + toIce(core::dto::Execution::Status& ret, const SkillStatus& status) { switch (status) { case SkillStatus::Constructing: - ret = provider::dto::Execution::Status::Constructing; + ret = core::dto::Execution::Status::Constructing; return; case SkillStatus::Initializing: - ret = provider::dto::Execution::Status::Initializing; + ret = core::dto::Execution::Status::Initializing; return; case SkillStatus::Preparing: - ret = provider::dto::Execution::Status::Preparing; + ret = core::dto::Execution::Status::Preparing; return; case SkillStatus::Running: - ret = provider::dto::Execution::Status::Running; + ret = core::dto::Execution::Status::Running; return; case SkillStatus::Failed: - ret = provider::dto::Execution::Status::Failed; + ret = core::dto::Execution::Status::Failed; return; case SkillStatus::Succeeded: - ret = provider::dto::Execution::Status::Succeeded; + ret = core::dto::Execution::Status::Succeeded; return; case SkillStatus::Aborted: - ret = provider::dto::Execution::Status::Aborted; + ret = core::dto::Execution::Status::Aborted; return; } throw error::SkillException(__PRETTY_FUNCTION__, "Should not happen!"); } void - toIce(provider::dto::Execution::Status& ret, const ActiveOrTerminatedSkillStatus& status) + toIce(core::dto::Execution::Status& ret, const ActiveOrTerminatedSkillStatus& status) { switch (status) { case ActiveOrTerminatedSkillStatus::Running: - ret = provider::dto::Execution::Status::Running; + ret = core::dto::Execution::Status::Running; return; case ActiveOrTerminatedSkillStatus::Failed: - ret = provider::dto::Execution::Status::Failed; + ret = core::dto::Execution::Status::Failed; return; case ActiveOrTerminatedSkillStatus::Succeeded: - ret = provider::dto::Execution::Status::Succeeded; + ret = core::dto::Execution::Status::Succeeded; return; case ActiveOrTerminatedSkillStatus::Aborted: - ret = provider::dto::Execution::Status::Aborted; + ret = core::dto::Execution::Status::Aborted; return; } throw error::SkillException(__PRETTY_FUNCTION__, "Should not happen!"); } void - toIce(provider::dto::Execution::Status& ret, const TerminatedSkillStatus& status) + toIce(core::dto::Execution::Status& ret, const TerminatedSkillStatus& status) { switch (status) { case TerminatedSkillStatus::Failed: - ret = provider::dto::Execution::Status::Failed; + ret = core::dto::Execution::Status::Failed; return; case TerminatedSkillStatus::Succeeded: - ret = provider::dto::Execution::Status::Succeeded; + ret = core::dto::Execution::Status::Succeeded; return; case TerminatedSkillStatus::Aborted: - ret = provider::dto::Execution::Status::Aborted; + ret = core::dto::Execution::Status::Aborted; return; } throw error::SkillException(__PRETTY_FUNCTION__, "Should not happen!"); } void - fromIce(const provider::dto::Execution::Status& status, TerminatedSkillStatus& ret) + fromIce(const core::dto::Execution::Status& status, TerminatedSkillStatus& ret) { switch (status) { - case provider::dto::Execution::Status::Constructing: + case core::dto::Execution::Status::Constructing: [[fallthrough]]; - case provider::dto::Execution::Status::Initializing: + case core::dto::Execution::Status::Initializing: [[fallthrough]]; - case provider::dto::Execution::Status::Preparing: + case core::dto::Execution::Status::Preparing: [[fallthrough]]; - case provider::dto::Execution::Status::Running: + case core::dto::Execution::Status::Running: break; - case provider::dto::Execution::Status::Failed: + case core::dto::Execution::Status::Failed: ret = TerminatedSkillStatus::Failed; return; - case provider::dto::Execution::Status::Succeeded: + case core::dto::Execution::Status::Succeeded: ret = TerminatedSkillStatus::Succeeded; return; - case provider::dto::Execution::Status::Aborted: + case core::dto::Execution::Status::Aborted: ret = TerminatedSkillStatus::Aborted; return; } @@ -134,26 +181,26 @@ namespace armarx } void - fromIce(const provider::dto::Execution::Status& status, ActiveOrTerminatedSkillStatus& ret) + fromIce(const core::dto::Execution::Status& status, ActiveOrTerminatedSkillStatus& ret) { switch (status) { - case provider::dto::Execution::Status::Constructing: + case core::dto::Execution::Status::Constructing: [[fallthrough]]; - case provider::dto::Execution::Status::Initializing: + case core::dto::Execution::Status::Initializing: [[fallthrough]]; - case provider::dto::Execution::Status::Preparing: + case core::dto::Execution::Status::Preparing: break; - case provider::dto::Execution::Status::Running: + case core::dto::Execution::Status::Running: ret = ActiveOrTerminatedSkillStatus::Running; return; - case provider::dto::Execution::Status::Failed: + case core::dto::Execution::Status::Failed: ret = ActiveOrTerminatedSkillStatus::Failed; return; - case provider::dto::Execution::Status::Succeeded: + case core::dto::Execution::Status::Succeeded: ret = ActiveOrTerminatedSkillStatus::Succeeded; return; - case provider::dto::Execution::Status::Aborted: + case core::dto::Execution::Status::Aborted: ret = ActiveOrTerminatedSkillStatus::Aborted; return; } @@ -163,36 +210,36 @@ namespace armarx } void - fromIce(const provider::dto::Execution::Status& status, SkillStatus& ret) + fromIce(const core::dto::Execution::Status& status, SkillStatus& ret) { switch (status) { - case provider::dto::Execution::Status::Constructing: + case core::dto::Execution::Status::Constructing: ret = SkillStatus::Constructing; return; - case provider::dto::Execution::Status::Initializing: + case core::dto::Execution::Status::Initializing: ret = SkillStatus::Initializing; return; - case provider::dto::Execution::Status::Preparing: + case core::dto::Execution::Status::Preparing: ret = SkillStatus::Preparing; return; - case provider::dto::Execution::Status::Running: + case core::dto::Execution::Status::Running: ret = SkillStatus::Running; return; - case provider::dto::Execution::Status::Failed: + case core::dto::Execution::Status::Failed: ret = SkillStatus::Failed; return; - case provider::dto::Execution::Status::Succeeded: + case core::dto::Execution::Status::Succeeded: ret = SkillStatus::Succeeded; return; - case provider::dto::Execution::Status::Aborted: + case core::dto::Execution::Status::Aborted: ret = SkillStatus::Aborted; return; } throw error::SkillException(__PRETTY_FUNCTION__, "Should not happen!"); } - SkillStatusUpdateBase::SkillStatusUpdateBase(const SkillExecutionId& exec, + SkillStatusUpdateBase::SkillStatusUpdateBase(const SkillExecutionID& exec, const SkillParameterization& param) : executionId(exec), usedParameterization(param) { @@ -202,13 +249,12 @@ namespace armarx SkillStatusUpdateBase::toManagerIce() const { manager::dto::SkillStatusUpdate ret; - ret.header.executionId.skillId = executionId.skillId.toManagerIce(); - ret.header.executionId.executorName = executionId.executorName; - armarx::core::time::toIce(ret.header.executionId.executionStartedTime, + ret.executionId.skillId = executionId.skillId.toManagerIce(); + ret.executionId.executorName = executionId.executorName; + armarx::core::time::toIce(ret.executionId.executionStartedTime, executionId.executionStartedTime); - ret.header.usedParams = - aron::data::Dict::ToAronDictDTO(usedParameterization.parameterization); - ret.header.usedCallbackInterface = usedParameterization.callbackInterface; + ret.usedParams = aron::data::Dict::ToAronDictDTO(usedParameterization.parameterization); + ret.usedCallbackInterface = usedParameterization.callbackInterface; ret.data = aron::data::Dict::ToAronDictDTO(data); return ret; } @@ -217,13 +263,12 @@ namespace armarx SkillStatusUpdateBase::toProviderIce() const { provider::dto::SkillStatusUpdate ret; - ret.header.executionId.skillId = executionId.skillId.toProviderIce(); - ret.header.executionId.executorName = executionId.executorName; - armarx::core::time::toIce(ret.header.executionId.executionStartedTime, + ret.executionId.skillId = executionId.skillId.toProviderIce(); + ret.executionId.executorName = executionId.executorName; + armarx::core::time::toIce(ret.executionId.executionStartedTime, executionId.executionStartedTime); - ret.header.usedParams = - aron::data::Dict::ToAronDictDTO(usedParameterization.parameterization); - ret.header.usedCallbackInterface = usedParameterization.callbackInterface; + ret.usedParams = aron::data::Dict::ToAronDictDTO(usedParameterization.parameterization); + ret.usedCallbackInterface = usedParameterization.callbackInterface; ret.data = aron::data::Dict::ToAronDictDTO(data); return ret; } @@ -232,7 +277,7 @@ namespace armarx TerminatedSkillStatusUpdate::toManagerIce() const { manager::dto::SkillStatusUpdate ret = SkillStatusUpdateBase::toManagerIce(); - skills::toIce(ret.header.status, status); + skills::toIce(ret.status, status); return ret; } @@ -240,7 +285,7 @@ namespace armarx TerminatedSkillStatusUpdate::toProviderIce() const { provider::dto::SkillStatusUpdate ret = SkillStatusUpdateBase::toProviderIce(); - skills::toIce(ret.header.status, status); + skills::toIce(ret.status, status); return ret; } @@ -248,7 +293,7 @@ namespace armarx SkillStatusUpdate::toManagerIce() const { manager::dto::SkillStatusUpdate ret = SkillStatusUpdateBase::toManagerIce(); - skills::toIce(ret.header.status, status); + skills::toIce(ret.status, status); return ret; } @@ -256,7 +301,7 @@ namespace armarx SkillStatusUpdate::toProviderIce() const { provider::dto::SkillStatusUpdate ret = SkillStatusUpdateBase::toProviderIce(); - skills::toIce(ret.header.status, status); + skills::toIce(ret.status, status); return ret; } @@ -264,7 +309,7 @@ namespace armarx ActiveOrTerminatedSkillStatusUpdate::toManagerIce() const { manager::dto::SkillStatusUpdate ret = SkillStatusUpdateBase::toManagerIce(); - skills::toIce(ret.header.status, status); + skills::toIce(ret.status, status); return ret; } @@ -272,53 +317,50 @@ namespace armarx ActiveOrTerminatedSkillStatusUpdate::toProviderIce() const { provider::dto::SkillStatusUpdate ret = SkillStatusUpdateBase::toProviderIce(); - skills::toIce(ret.header.status, status); + skills::toIce(ret.status, status); return ret; } TerminatedSkillStatusUpdate TerminatedSkillStatusUpdate::FromIce(const manager::dto::SkillStatusUpdate& update) { - TerminatedSkillStatusUpdate ret( - skills::SkillExecutionId::FromIce(update.header.executionId), - skills::SkillParameterization::FromIce(update.header.usedParams, - update.header.usedCallbackInterface)); - skills::fromIce(update.header.status, ret.status); + TerminatedSkillStatusUpdate ret(skills::SkillExecutionID::FromIce(update.executionId), + skills::SkillParameterization::FromIce( + update.usedParams, update.usedCallbackInterface)); + skills::fromIce(update.status, ret.status); return ret; } TerminatedSkillStatusUpdate TerminatedSkillStatusUpdate::FromIce(const provider::dto::SkillStatusUpdate& update, - const std::string& providerName) + const std::optional<skills::ProviderID>& providerId) { TerminatedSkillStatusUpdate ret( - skills::SkillExecutionId::FromIce(update.header.executionId, providerName), - skills::SkillParameterization::FromIce(update.header.usedParams, - update.header.usedCallbackInterface)); - skills::fromIce(update.header.status, ret.status); + skills::SkillExecutionID::FromIce(update.executionId, providerId), + skills::SkillParameterization::FromIce(update.usedParams, + update.usedCallbackInterface)); + skills::fromIce(update.status, ret.status); return ret; } SkillStatusUpdate SkillStatusUpdate::FromIce(const manager::dto::SkillStatusUpdate& update) { - SkillStatusUpdate ret( - skills::SkillExecutionId::FromIce(update.header.executionId), - skills::SkillParameterization::FromIce(update.header.usedParams, - update.header.usedCallbackInterface)); - skills::fromIce(update.header.status, ret.status); + SkillStatusUpdate ret(skills::SkillExecutionID::FromIce(update.executionId), + skills::SkillParameterization::FromIce( + update.usedParams, update.usedCallbackInterface)); + skills::fromIce(update.status, ret.status); return ret; } SkillStatusUpdate SkillStatusUpdate::FromIce(const provider::dto::SkillStatusUpdate& update, - const std::string& providerName) + const std::optional<skills::ProviderID>& providerId) { - SkillStatusUpdate ret( - skills::SkillExecutionId::FromIce(update.header.executionId, providerName), - skills::SkillParameterization::FromIce(update.header.usedParams, - update.header.usedCallbackInterface)); - skills::fromIce(update.header.status, ret.status); + SkillStatusUpdate ret(skills::SkillExecutionID::FromIce(update.executionId, providerId), + skills::SkillParameterization::FromIce( + update.usedParams, update.usedCallbackInterface)); + skills::fromIce(update.status, ret.status); return ret; } @@ -326,22 +368,23 @@ namespace armarx ActiveOrTerminatedSkillStatusUpdate::FromIce(const manager::dto::SkillStatusUpdate& update) { ActiveOrTerminatedSkillStatusUpdate ret( - skills::SkillExecutionId::FromIce(update.header.executionId), - skills::SkillParameterization::FromIce(update.header.usedParams, - update.header.usedCallbackInterface)); - skills::fromIce(update.header.status, ret.status); + skills::SkillExecutionID::FromIce(update.executionId), + skills::SkillParameterization::FromIce(update.usedParams, + update.usedCallbackInterface)); + skills::fromIce(update.status, ret.status); return ret; } ActiveOrTerminatedSkillStatusUpdate - ActiveOrTerminatedSkillStatusUpdate::FromIce(const provider::dto::SkillStatusUpdate& update, - const std::string& providerName) + ActiveOrTerminatedSkillStatusUpdate::FromIce( + const provider::dto::SkillStatusUpdate& update, + const std::optional<skills::ProviderID>& providerId) { ActiveOrTerminatedSkillStatusUpdate ret( - skills::SkillExecutionId::FromIce(update.header.executionId, providerName), - skills::SkillParameterization::FromIce(update.header.usedParams, - update.header.usedCallbackInterface)); - skills::fromIce(update.header.status, ret.status); + skills::SkillExecutionID::FromIce(update.executionId, providerId), + skills::SkillParameterization::FromIce(update.usedParams, + update.usedCallbackInterface)); + skills::fromIce(update.status, ret.status); return ret; } } // namespace skills diff --git a/source/RobotAPI/libraries/skills/core/SkillStatusUpdate.h b/source/RobotAPI/libraries/skills/core/SkillStatusUpdate.h index 536a169f6..368dbe8b4 100644 --- a/source/RobotAPI/libraries/skills/core/SkillStatusUpdate.h +++ b/source/RobotAPI/libraries/skills/core/SkillStatusUpdate.h @@ -46,24 +46,29 @@ namespace armarx SkillStatus toSkillStatus(const ActiveOrTerminatedSkillStatus&); SkillStatus toSkillStatus(const TerminatedSkillStatus&); - void toIce(provider::dto::Execution::Status& ret, const SkillStatus& status); - void toIce(provider::dto::Execution::Status& ret, - const ActiveOrTerminatedSkillStatus& status); - void toIce(provider::dto::Execution::Status& ret, const TerminatedSkillStatus& status); + void toIce(core::dto::Execution::Status& ret, const SkillStatus& status); + void toIce(core::dto::Execution::Status& ret, const ActiveOrTerminatedSkillStatus& status); + void toIce(core::dto::Execution::Status& ret, const TerminatedSkillStatus& status); - void fromIce(const provider::dto::Execution::Status& status, TerminatedSkillStatus& ret); - void fromIce(const provider::dto::Execution::Status& status, + void fromIce(const core::dto::Execution::Status& status, TerminatedSkillStatus& ret); + void fromIce(const core::dto::Execution::Status& status, ActiveOrTerminatedSkillStatus& ret); - void fromIce(const provider::dto::Execution::Status& status, SkillStatus& ret); + void fromIce(const core::dto::Execution::Status& status, SkillStatus& ret); + + TerminatedSkillStatus MergeSkillStatus(const TerminatedSkillStatus t1, + const TerminatedSkillStatus t2); + ActiveOrTerminatedSkillStatus MergeSkillStatus(const ActiveOrTerminatedSkillStatus t1, + const ActiveOrTerminatedSkillStatus t2); struct SkillStatusUpdateBase { // header - SkillExecutionId executionId; + SkillExecutionID executionId; SkillParameterization usedParameterization; SkillStatusUpdateBase() = delete; - SkillStatusUpdateBase(const SkillExecutionId& exec, const SkillParameterization& param); + SkillStatusUpdateBase(const SkillExecutionID& exec, const SkillParameterization& param); + SkillStatusUpdateBase(const SkillStatusUpdateBase&) = default; // data aron::data::DictPtr data = nullptr; @@ -92,7 +97,7 @@ namespace armarx static TerminatedSkillStatusUpdate FromIce(const provider::dto::SkillStatusUpdate& update, - const std::string& providerName); + const std::optional<skills::ProviderID>& providerId = std::nullopt); static TerminatedSkillStatusUpdate FromIce(const manager::dto::SkillStatusUpdate& update); @@ -119,7 +124,7 @@ namespace armarx static ActiveOrTerminatedSkillStatusUpdate FromIce(const provider::dto::SkillStatusUpdate& update, - const std::string& providerName); + const std::optional<skills::ProviderID>& providerId = std::nullopt); static ActiveOrTerminatedSkillStatusUpdate FromIce(const manager::dto::SkillStatusUpdate& update); @@ -132,6 +137,42 @@ namespace armarx using SkillStatusUpdateBase::SkillStatusUpdateBase; + bool + operator<(const SkillStatusUpdate& o) const + { + if (!hasBeenConstructed() and o.hasBeenConstructed()) + { + return true; + } + if (!hasBeenInitialized() and o.hasBeenInitialized()) + { + return true; + } + if (!hasBeenPrepared() and o.hasBeenPrepared()) + { + return true; + } + if (!hasBeenRunning() and o.hasBeenRunning()) + { + return true; + } + if (!hasBeenTerminated() and o.hasBeenTerminated()) + { + return true; + } + return false; + } + + bool + operator<=(const SkillStatusUpdate& o) const + { + if (status == o.status) + { + return true; + } + return *this < o; + } + bool hasBeenConstructed() const { @@ -167,8 +208,9 @@ namespace armarx provider::dto::SkillStatusUpdate toProviderIce() const; - static SkillStatusUpdate FromIce(const provider::dto::SkillStatusUpdate& update, - const std::string& providerName); + static SkillStatusUpdate + FromIce(const provider::dto::SkillStatusUpdate& update, + const std::optional<skills::ProviderID>& providerId = std::nullopt); static SkillStatusUpdate FromIce(const manager::dto::SkillStatusUpdate& update); }; diff --git a/source/RobotAPI/libraries/skills/manager/SkillManagerComponentPlugin.cpp b/source/RobotAPI/libraries/skills/manager/SkillManagerComponentPlugin.cpp index 057715f98..51694c8d9 100644 --- a/source/RobotAPI/libraries/skills/manager/SkillManagerComponentPlugin.cpp +++ b/source/RobotAPI/libraries/skills/manager/SkillManagerComponentPlugin.cpp @@ -18,6 +18,8 @@ namespace armarx::plugins void SkillManagerComponentPlugin::preOnConnectComponent() { + auto& p = parent<SkillManagerComponentPluginUser>(); + p.getProxy(myPrx, -1); } void @@ -44,56 +46,55 @@ namespace armarx::plugins } void - SkillManagerComponentPlugin::addProvider(const skills::ProviderInfo& info) + SkillManagerComponentPlugin::addProvider(const skills::ProviderInfo& providerInfo) { std::scoped_lock l(skillProviderMapMutex); - if (skillProviderMap.find(info.providerId.providerName) == skillProviderMap.end()) + if (skillProviderMap.find(providerInfo.providerId.providerName) == skillProviderMap.end()) { - ARMARX_INFO << "Adding a provider with name '" << info.providerId.providerName << "'."; - skillProviderMap.insert({info.providerId.providerName, info.provider}); + ARMARX_INFO << "Adding a provider with name '" << providerInfo.providerId.providerName + << "'."; + skillProviderMap.insert( + {providerInfo.providerId.providerName, providerInfo.providerInterface}); } else { - ARMARX_INFO << "Trying to add a provider with name '" << info.providerId.providerName + ARMARX_INFO << "Trying to add a provider with name '" + << providerInfo.providerId.providerName << "' but the provider already exists. " << "Overwriting the old provider info."; - skillProviderMap[info.providerId.providerName] = info.provider; + skillProviderMap[providerInfo.providerId.providerName] = providerInfo.providerInterface; } } void - SkillManagerComponentPlugin::removeProvider(const skills::ProviderID& id) + SkillManagerComponentPlugin::removeProvider(const skills::ProviderID& providerId) { std::scoped_lock l(skillProviderMapMutex); - if (auto it = skillProviderMap.find(id.providerName); it != skillProviderMap.end()) + if (auto it = skillProviderMap.find(providerId.providerName); it != skillProviderMap.end()) { - ARMARX_INFO << "Removing a provider with name '" << id.providerName << "'."; + ARMARX_INFO << "Removing a provider with name '" << providerId.providerName << "'."; skillProviderMap.erase(it); } else { - ARMARX_INFO << "Trying to remove a provider with name '" << id.providerName + ARMARX_INFO << "Trying to remove a provider with name '" << providerId.providerName << "' but it couldn't be found."; } } skills::SkillStatusUpdate - SkillManagerComponentPlugin::executeSkill( - const skills::SkillExecutionRequest& req, - const skills::callback::dti::SkillProviderCallbackInterfacePrx& myPrx) + SkillManagerComponentPlugin::executeSkill(const skills::SkillExecutionRequest& executionRequest) { + ARMARX_CHECK(executionRequest.skillId.fullySpecified()); + std::unique_lock l(skillProviderMapMutex); - skills::ProviderID provderId("INVALID PROVIDER NAME"); + skills::ProviderID provderId(executionRequest.skillId); // TODO: Really support regexes! - if (req.skillId.providerName == "*") - { - provderId = getFirstProviderNameThatHasSkill(req.skillId.skillName); - } - else if (not(req.skillId.providerName.empty())) + if (executionRequest.skillId.providerId->providerName == "*") { - provderId = skills::ProviderID(req.skillId); + provderId = getFirstProviderNameThatHasSkill(executionRequest.skillId.skillName); } @@ -115,15 +116,21 @@ namespace armarx::plugins try { - skills::SkillExecutionRequest exInfo( - req.skillId, req.executorName, req.params, myPrx); + skills::SkillExecutionRequest provider_executionRequest( + executionRequest.skillId, + executionRequest.executorName, + executionRequest.params, + myPrx); - auto async = provider->begin_executeSkill(exInfo.toProviderIce()); + auto async = + provider->begin_executeSkill(provider_executionRequest.toProviderIce()); l.unlock(); // allow parallel e.g. stopping - auto up = provider->end_executeSkill(async); + auto provider_statusUpdate_ice = provider->end_executeSkill(async); // convert to manager view - return skills::SkillStatusUpdate::FromIce(up, provderId.providerName); + auto statusUpdate = + skills::SkillStatusUpdate::FromIce(provider_statusUpdate_ice, provderId); + return statusUpdate; } catch (...) { @@ -147,23 +154,20 @@ namespace armarx::plugins } } - skills::SkillExecutionId + skills::SkillExecutionID SkillManagerComponentPlugin::executeSkillAsync( - const skills::SkillExecutionRequest& req, - const skills::callback::dti::SkillProviderCallbackInterfacePrx& myPrx) + const skills::SkillExecutionRequest& executionRequest) { + ARMARX_CHECK(executionRequest.skillId.fullySpecified()); + std::unique_lock l(skillProviderMapMutex); - skills::ProviderID provderId("INVALID PROVIDER NAME"); + skills::ProviderID provderId(executionRequest.skillId); // TODO: Really support regexes! - if (req.skillId.providerName == "*") + if (executionRequest.skillId.providerId->providerName == "*") { - provderId = getFirstProviderNameThatHasSkill(req.skillId.skillName); - } - else if (not(req.skillId.providerName.empty())) - { - provderId = req.skillId.providerName; + provderId = getFirstProviderNameThatHasSkill(executionRequest.skillId.skillName); } @@ -185,15 +189,22 @@ namespace armarx::plugins try { - skills::SkillExecutionRequest exInfo( - req.skillId, req.executorName, req.params, myPrx); + skills::SkillExecutionRequest provider_executionRequest( + executionRequest.skillId, + executionRequest.executorName, + executionRequest.params, + myPrx); - auto async = provider->begin_executeSkillAsync(exInfo.toProviderIce()); + auto async = + provider->begin_executeSkillAsync(provider_executionRequest.toProviderIce()); l.unlock(); // allow parallel e.g. stopping - auto up = provider->end_executeSkillAsync(async); + auto provider_executionID_ice = provider->end_executeSkillAsync(async); // convert to manager view - return skills::SkillExecutionId::FromIce(up, provderId.providerName); + auto executionId = + skills::SkillExecutionID::FromIce(provider_executionID_ice, provderId); + executionId.skillId.providerId = provderId; + return executionId; } catch (...) { @@ -218,70 +229,137 @@ namespace armarx::plugins } void - SkillManagerComponentPlugin::addSkillParameters(const skills::SkillExecutionId& id, + SkillManagerComponentPlugin::addSkillParameters(const skills::SkillExecutionID& executionId, const aron::data::DictPtr& data) { + ARMARX_CHECK(executionId.skillId.fullySpecified()); + std::unique_lock l(skillProviderMapMutex); - if (auto it = skillProviderMap.find(skills::ProviderID(id.skillId.providerName)); + if (auto it = skillProviderMap.find(*executionId.skillId.providerId); it != skillProviderMap.end()) { - const auto& providerName = it->first; + const auto& providerId = it->first; const auto& provider = it->second; if (!provider) { ARMARX_WARNING << __PRETTY_FUNCTION__ << ": Found disconnected skill provider '" - << providerName << "'. Removing it from skills."; + << providerId << "'. Removing it from skills."; skillProviderMap.erase(it); return; } try { - auto async = - provider->begin_addSkillParameters(id.toProviderIce(), data->toAronDictDTO()); + auto async = provider->begin_addSkillParameters(executionId.toProviderIce(), + data->toAronDictDTO()); l.unlock(); // allow parallel e.g. stopping - return provider->end_addSkillParameters(async); + provider->end_addSkillParameters(async); + return; } catch (...) { ARMARX_WARNING << __PRETTY_FUNCTION__ << ": Found buggy skill provider '" - << providerName << "'. Removing it from skills on next execute."; + << providerId << "'. Removing it from skills on next execute."; } } } void - SkillManagerComponentPlugin::abortSkill(const skills::SkillExecutionId& id) + SkillManagerComponentPlugin::abortSkill(const skills::SkillExecutionID& executionId) { + ARMARX_CHECK(executionId.skillId.fullySpecified()); + std::unique_lock l(skillProviderMapMutex); - if (auto it = skillProviderMap.find(id.skillId.providerName); it != skillProviderMap.end()) + if (auto it = skillProviderMap.find(*executionId.skillId.providerId); + it != skillProviderMap.end()) { - const auto& providerName = it->first; + const auto& providerId = it->first; const auto& provider = it->second; if (!provider) { ARMARX_WARNING << __PRETTY_FUNCTION__ << ": Found disconnected skill provider '" - << providerName << "'. Removing it from skills."; + << providerId << "'. Removing it from skills."; skillProviderMap.erase(it); return; } try { - auto async = provider->begin_abortSkill(id.toProviderIce()); + auto async = provider->begin_abortSkill(executionId.toProviderIce()); l.unlock(); // allow parallel e.g. stopping - return provider->end_abortSkill(async); + provider->end_abortSkill(async); + return; } catch (...) { ARMARX_WARNING << __PRETTY_FUNCTION__ << ": Found buggy skill provider '" - << providerName << "'. Removing it from skills on next execute."; + << providerId << "'. Removing it from skills on next execute."; } } } + std::optional<skills::SkillDescription> + SkillManagerComponentPlugin::getSkillDescription(const skills::SkillID& skillId) + { + ARMARX_CHECK(skillId.fullySpecified()); + + std::unique_lock l(skillProviderMapMutex); + if (auto it = skillProviderMap.find(*skillId.providerId); it != skillProviderMap.end()) + { + const auto& providerId = it->first; + const auto& provider = it->second; + + if (!provider) + { + ARMARX_WARNING << __PRETTY_FUNCTION__ << ": Found disconnected skill provider '" + << providerId << "'. Removing it from skills."; + skillProviderMap.erase(it); + + throw skills::error::SkillException(__PRETTY_FUNCTION__, + "Skill execution failed. Could not query a " + "status update of a skill of provider '" + + providerId.toString() + + "' because the provider does not exist."); + } + + try + { + auto async = provider->begin_getSkillDescription(skillId.toProviderIce()); + l.unlock(); // allow parallel e.g. stopping + auto provider_desc_ice = provider->end_getSkillDescription(async); + + if (not provider_desc_ice) + { + return std::nullopt; + } + + // convert to manager view + auto desc = + skills::SkillDescription::FromIce(provider_desc_ice.value(), providerId); + return desc; + } + catch (...) + { + ARMARX_WARNING << __PRETTY_FUNCTION__ + << ": Found disconnected or buggy skill provider '" << providerId + << "' during execution. Removing it from skills."; + skillProviderMap.erase(it); + + throw skills::error::SkillException(__PRETTY_FUNCTION__, + "Skill execution failed. Could not query a " + "status update of a skill of provider '" + + providerId.toString() + + "' because the provider does not exist."); + } + } + else + { + return std::nullopt; + } + } + std::map<skills::SkillID, skills::SkillDescription> SkillManagerComponentPlugin::getSkillDescriptions() { @@ -290,13 +368,13 @@ namespace armarx::plugins std::scoped_lock l(skillProviderMapMutex); for (auto it = skillProviderMap.cbegin(); it != skillProviderMap.cend();) { - const auto& providerName = it->first; + const auto& providerId = it->first; const auto& provider = it->second; if (!provider) { ARMARX_WARNING << __PRETTY_FUNCTION__ << ": Found disconnected skill provider '" - << providerName << "'. Removing it from skills."; + << providerId << "'. Removing it from skills."; it = skillProviderMap.erase(it); continue; } @@ -305,9 +383,11 @@ namespace armarx::plugins { skills::provider::dto::SkillDescriptionMap m = provider->getSkillDescriptions(); - for (const auto& [k, v] : m) + for (const auto& [provider_skillId_ice, skillDescription_ice] : m) { - ret.insert({skills::SkillID::FromIce(k), skills::SkillDescription::FromIce(v)}); + ret.insert( + {skills::SkillID::FromIce(provider_skillId_ice, providerId), + skills::SkillDescription::FromIce(skillDescription_ice, providerId)}); } ++it; @@ -315,7 +395,7 @@ namespace armarx::plugins catch (...) { ARMARX_WARNING << __PRETTY_FUNCTION__ << ": Found buggy skill provider '" - << providerName << "'. Removing it from skills."; + << providerId << "'. Removing it from skills."; it = skillProviderMap.erase(it); } } @@ -323,10 +403,13 @@ namespace armarx::plugins } std::optional<skills::SkillStatusUpdate> - SkillManagerComponentPlugin::getSkillExecutionStatus(const skills::SkillExecutionId& execId) + SkillManagerComponentPlugin::getSkillExecutionStatus( + const skills::SkillExecutionID& executionId) { + ARMARX_CHECK(executionId.skillId.fullySpecified()); + std::unique_lock l(skillProviderMapMutex); - if (auto it = skillProviderMap.find(execId.skillId.providerName); + if (auto it = skillProviderMap.find(*executionId.skillId.providerId); it != skillProviderMap.end()) { const auto& providerId = it->first; @@ -347,12 +430,19 @@ namespace armarx::plugins try { - auto async = provider->begin_getSkillExecutionStatus(execId.toProviderIce()); + auto async = provider->begin_getSkillExecutionStatus(executionId.toProviderIce()); l.unlock(); // allow parallel e.g. stopping - auto up = provider->end_getSkillExecutionStatus(async); + auto provider_statusUpdate_ice = provider->end_getSkillExecutionStatus(async); + + if (not provider_statusUpdate_ice) + { + return std::nullopt; + } // convert to manager view - return skills::SkillStatusUpdate::FromIce(up, providerId.providerName); + auto statusUpdate = skills::SkillStatusUpdate::FromIce( + provider_statusUpdate_ice.value(), providerId); + return statusUpdate; } catch (...) { @@ -370,15 +460,14 @@ namespace armarx::plugins } else { - // no actove skill. Return null return std::nullopt; } } - std::map<skills::SkillExecutionId, skills::SkillStatusUpdate> + std::map<skills::SkillExecutionID, skills::SkillStatusUpdate> SkillManagerComponentPlugin::getSkillExecutionStatuses() { - std::map<skills::SkillExecutionId, skills::SkillStatusUpdate> ret; + std::map<skills::SkillExecutionID, skills::SkillStatusUpdate> ret; std::scoped_lock l(skillProviderMapMutex); for (auto it = skillProviderMap.cbegin(); it != skillProviderMap.cend();) @@ -398,10 +487,12 @@ namespace armarx::plugins { auto m = provider->getSkillExecutionStatuses(); - for (const auto& [k, v] : m) + for (const auto& [provider_executionId_ice, provider_statusUpdate_ice] : m) { - ret.insert({skills::SkillExecutionId::FromIce(k, providerId.providerName), - skills::SkillStatusUpdate::FromIce(v, providerId.providerName)}); + ret.insert( + {skills::SkillExecutionID::FromIce(provider_executionId_ice, providerId), + skills::SkillStatusUpdate::FromIce(provider_statusUpdate_ice, + providerId)}); } it++; } @@ -449,11 +540,8 @@ namespace armarx const skills::manager::dto::SkillExecutionRequest& info, const Ice::Current&) { - skills::callback::dti::SkillProviderCallbackInterfacePrx myPrx; - getProxy(myPrx, -1); - auto e = skills::SkillExecutionRequest::FromIce(info); - return this->plugin->executeSkill(e, myPrx).toManagerIce(); + return this->plugin->executeSkill(e).toManagerIce(); } skills::manager::dto::SkillExecutionID @@ -461,11 +549,8 @@ namespace armarx const skills::manager::dto::SkillExecutionRequest& info, const Ice::Current& current) { - skills::callback::dti::SkillProviderCallbackInterfacePrx myPrx; - getProxy(myPrx, -1); - auto e = skills::SkillExecutionRequest::FromIce(info); - return this->plugin->executeSkillAsync(e, myPrx).toManagerIce(); + return this->plugin->executeSkillAsync(e).toManagerIce(); } void @@ -475,7 +560,7 @@ namespace armarx const Ice::Current& current) { auto a = armarx::aron::data::Dict::FromAronDictDTO(params); - auto e = skills::SkillExecutionId::FromIce(info); + auto e = skills::SkillExecutionID::FromIce(info); this->plugin->addSkillParameters(e, a); } @@ -483,14 +568,14 @@ namespace armarx SkillManagerComponentPluginUser::abortSkill(const skills::manager::dto::SkillExecutionID& id, const Ice::Current& current) { - auto i = skills::SkillExecutionId::FromIce(id); + auto i = skills::SkillExecutionID::FromIce(id); this->plugin->abortSkill(i); } void SkillManagerComponentPluginUser::updateStatusForSkill( const skills::provider::dto::SkillStatusUpdate& statusUpdate, - const skills::provider::dto::ProviderID& pid, + const skills::callback::dto::ProviderID& pid, const Ice::Current&) { (void)statusUpdate; @@ -507,24 +592,37 @@ namespace armarx for (const auto& [k, v] : m) { - ret.insert({k.toManagerIce(), v.toIce()}); + ret.insert({k.toManagerIce(), v.toManagerIce()}); } return ret; } - skills::manager::dto::SkillStatusUpdate + IceUtil::Optional<skills::manager::dto::SkillDescription> + SkillManagerComponentPluginUser::getSkillDescription(const skills::manager::dto::SkillID& id, + const Ice::Current& current) + { + auto e = skills::SkillID::FromIce(id); + auto o = this->plugin->getSkillDescription(e); + if (o.has_value()) + { + return o->toManagerIce(); + } + return {}; + } + + IceUtil::Optional<skills::manager::dto::SkillStatusUpdate> SkillManagerComponentPluginUser::getSkillExecutionStatus( const skills::manager::dto::SkillExecutionID& executionId, const Ice::Current& current) { - auto e = skills::SkillExecutionId::FromIce(executionId); + auto e = skills::SkillExecutionID::FromIce(executionId); auto o = this->plugin->getSkillExecutionStatus(e); if (o.has_value()) { return o->toManagerIce(); } - return {}; // TODO!! + return {}; } skills::manager::dto::SkillStatusUpdateMap diff --git a/source/RobotAPI/libraries/skills/manager/SkillManagerComponentPlugin.h b/source/RobotAPI/libraries/skills/manager/SkillManagerComponentPlugin.h index 5aaadd6e6..57b0250a1 100644 --- a/source/RobotAPI/libraries/skills/manager/SkillManagerComponentPlugin.h +++ b/source/RobotAPI/libraries/skills/manager/SkillManagerComponentPlugin.h @@ -11,6 +11,11 @@ #include <RobotAPI/libraries/skills/core/SkillExecutionRequest.h> #include <RobotAPI/libraries/skills/core/SkillStatusUpdate.h> +namespace armarx +{ + class SkillManagerComponentPluginUser; // forward declaration +} + namespace armarx::plugins { class SkillManagerComponentPlugin : public ComponentPlugin @@ -28,32 +33,34 @@ namespace armarx::plugins void removeProvider(const skills::ProviderID& id); - skills::SkillStatusUpdate - executeSkill(const skills::SkillExecutionRequest& req, - const skills::callback::dti::SkillProviderCallbackInterfacePrx& prx); + skills::SkillStatusUpdate executeSkill(const skills::SkillExecutionRequest& req); - skills::SkillExecutionId - executeSkillAsync(const skills::SkillExecutionRequest& req, - const skills::callback::dti::SkillProviderCallbackInterfacePrx& prx); + skills::SkillExecutionID executeSkillAsync(const skills::SkillExecutionRequest& req); - void addSkillParameters(const skills::SkillExecutionId& id, + void addSkillParameters(const skills::SkillExecutionID& id, const aron::data::DictPtr& data); - void abortSkill(const skills::SkillExecutionId& id); + void abortSkill(const skills::SkillExecutionID& id); + + std::optional<skills::SkillDescription> getSkillDescription(const skills::SkillID& id); std::map<skills::SkillID, skills::SkillDescription> getSkillDescriptions(); std::optional<skills::SkillStatusUpdate> - getSkillExecutionStatus(const skills::SkillExecutionId& id); + getSkillExecutionStatus(const skills::SkillExecutionID& id); - std::map<skills::SkillExecutionId, skills::SkillStatusUpdate> getSkillExecutionStatuses(); + std::map<skills::SkillExecutionID, skills::SkillStatusUpdate> getSkillExecutionStatuses(); skills::ProviderID getFirstProviderNameThatHasSkill(const skills::SkillID& skillid); - protected: + private: + skills::manager::dti::SkillManagerInterfacePrx myPrx; + std::mutex skillProviderMapMutex; std::map<skills::ProviderID, skills::provider::dti::SkillProviderInterfacePrx> skillProviderMap; + + friend class armarx::SkillManagerComponentPluginUser; }; } // namespace armarx::plugins @@ -84,7 +91,7 @@ namespace armarx const Ice::Current& current) override; void updateStatusForSkill(const skills::provider::dto::SkillStatusUpdate& update, - const skills::provider::dto::ProviderID& id, + const skills::callback::dto::ProviderID& id, const Ice::Current& current) override; void abortSkill(const skills::manager::dto::SkillExecutionID& id, @@ -93,7 +100,11 @@ namespace armarx skills::manager::dto::SkillDescriptionMap getSkillDescriptions(const Ice::Current& current) override; - skills::manager::dto::SkillStatusUpdate + IceUtil::Optional<skills::manager::dto::SkillDescription> + getSkillDescription(const skills::manager::dto::SkillID& id, + const Ice::Current& current) override; + + IceUtil::Optional<skills::manager::dto::SkillStatusUpdate> getSkillExecutionStatus(const skills::manager::dto::SkillExecutionID& executionId, const Ice::Current& current) override; diff --git a/source/RobotAPI/libraries/skills/provider/PeriodicSkill.cpp b/source/RobotAPI/libraries/skills/provider/PeriodicSkill.cpp index 4df38fb17..56994fb33 100644 --- a/source/RobotAPI/libraries/skills/provider/PeriodicSkill.cpp +++ b/source/RobotAPI/libraries/skills/provider/PeriodicSkill.cpp @@ -45,7 +45,7 @@ namespace armarx::skills Skill::MainResult PeriodicSkill::main() { - core::time::Metronome metronome(frequency); + armarx::core::time::Metronome metronome(frequency); while (not Skill::checkWhetherSkillShouldStopASAP()) { diff --git a/source/RobotAPI/libraries/skills/provider/PeriodicSkill.h b/source/RobotAPI/libraries/skills/provider/PeriodicSkill.h index 60823be8c..b11239dcf 100644 --- a/source/RobotAPI/libraries/skills/provider/PeriodicSkill.h +++ b/source/RobotAPI/libraries/skills/provider/PeriodicSkill.h @@ -43,14 +43,14 @@ namespace armarx::skills StepResult stepOfSkill(); - private: + protected: /// Do not use anymore Skill::MainResult main() final; /// Override this method with your own step function virtual StepResult step(); - private: + protected: const armarx::Frequency frequency; }; diff --git a/source/RobotAPI/libraries/skills/provider/PeriodicSpecializedSkill.h b/source/RobotAPI/libraries/skills/provider/PeriodicSpecializedSkill.h index 83f9ae009..1c98f1126 100644 --- a/source/RobotAPI/libraries/skills/provider/PeriodicSpecializedSkill.h +++ b/source/RobotAPI/libraries/skills/provider/PeriodicSpecializedSkill.h @@ -56,15 +56,12 @@ namespace armarx::skills return this->step(); } - private: - using Skill::stopped; - using Skill::timeoutReached; - + protected: /// Do not use anymore Skill::MainResult main() final { - core::time::Metronome metronome(frequency); + armarx::core::time::Metronome metronome(frequency); while (not Skill::checkWhetherSkillShouldStopASAP()) { @@ -115,6 +112,10 @@ namespace armarx::skills } private: + using Skill::stopped; + using Skill::timeoutReached; + + protected: const armarx::Frequency frequency; }; diff --git a/source/RobotAPI/libraries/skills/provider/SkillContext.h b/source/RobotAPI/libraries/skills/provider/SkillContext.h index 9bdbc0f02..df5a90eb7 100644 --- a/source/RobotAPI/libraries/skills/provider/SkillContext.h +++ b/source/RobotAPI/libraries/skills/provider/SkillContext.h @@ -7,20 +7,21 @@ namespace armarx { namespace skills { - /* A base class for skill contexts. It is not required to use a context for skills but it eases the management of dependencies and properties for providers */ + /* A virtual base class for skill contexts. It is not required to use a context for skills but it eases the management of dependencies and properties for providers */ class SkillContext { public: SkillContext() = default; - virtual void defineProperties(const armarx::PropertyDefinitionsPtr& defs, const std::string& prefix) {}; + virtual void defineProperties(const armarx::PropertyDefinitionsPtr& defs, + const std::string& prefix){}; - virtual void onInit(armarx::Component& parent) {}; - virtual void onConnected(armarx::Component& parent) {}; - virtual void onDisconnected(armarx::Component& parent) {}; - virtual void onStopped(armarx::Component& parent) {}; + virtual void onInit(armarx::Component& parent){}; + virtual void onConnected(armarx::Component& parent){}; + virtual void onDisconnected(armarx::Component& parent){}; + virtual void onStopped(armarx::Component& parent){}; private: }; - } -} + } // namespace skills +} // namespace armarx diff --git a/source/RobotAPI/libraries/skills/provider/SkillFactory.h b/source/RobotAPI/libraries/skills/provider/SkillFactory.h index eadb1bab9..ea4cd5edb 100644 --- a/source/RobotAPI/libraries/skills/provider/SkillFactory.h +++ b/source/RobotAPI/libraries/skills/provider/SkillFactory.h @@ -11,9 +11,9 @@ namespace armarx class SkillFactory { public: - using FunT = std::function<std::unique_ptr<Skill>()>; + using FunTSkill = std::function<std::unique_ptr<Skill>()>; - SkillFactory(const SkillDescription& id, const FunT& f) : fun(f), desc(id) + SkillFactory(const FunTSkill& s) : createS(s) { } @@ -21,66 +21,36 @@ namespace armarx requires isSkill<_Skill> static std::unique_ptr<SkillFactory> - ForSkill(const SkillDescription& id, Args&&... args) + ForSkill(Args&&... args) { - return std::make_unique<SkillFactory>( - id, [&]() { return std::make_unique<_Skill>(std::forward<Args>(args)...); }); - } - - - template <class _Skill, class... Args> - requires isSkill<_Skill> + // capture params in new lambda + // (https://stackoverflow.com/questions/47496358/c-lambdas-how-to-capture-variadic-parameter-pack-from-the-upper-scope) + auto createS = [... args = std::forward<Args>(args)]() + { return std::make_unique<_Skill>(std::forward<Args>(args)...); }; - static std::unique_ptr<SkillFactory> - ForSkillDescriptionGetter(Args&&... args) - - { - return std::make_unique<SkillFactory>( - _Skill::GetSkillDescription(), - [&]() { return std::make_unique<_Skill>(std::forward<Args>(args)...); }); + auto ret = std::make_unique<SkillFactory>(createS); + return ret; } virtual std::unique_ptr<Skill> - createSkill() const - { - return fun(); - } - - const SkillDescription& - getSkillDescription() const + createSkill(const skills::ProviderID& pid) const { - return desc; + auto s = createS(); + s->setProviderId(pid); + return s; } - void - setOwner(const std::string& providerName) + virtual SkillDescription + createSkillDescription(const skills::ProviderID& pid) const { - ARMARX_CHECK(this->desc.skillId.providerName.empty()) - << "The owning provider of the factory for skill '" - << this->desc.skillId.skillName << "' was already set. This is not valid."; - this->desc.skillId.providerName = providerName; - } - - SkillID - getSkillID(const std::string& providerName) const - { - SkillID copy = getSkillID(); - copy.providerName = providerName; - return copy; - } - - const SkillID& - getSkillID() const - { - return desc.skillId; + auto s = createSkill(pid); + return s->getSkillDescription(); } protected: - FunT fun; - - SkillDescription desc; + FunTSkill createS; }; template <class T> diff --git a/source/RobotAPI/libraries/skills/provider/SkillProviderComponentPlugin.cpp b/source/RobotAPI/libraries/skills/provider/SkillProviderComponentPlugin.cpp index 3686ccb9f..c187b4ad4 100644 --- a/source/RobotAPI/libraries/skills/provider/SkillProviderComponentPlugin.cpp +++ b/source/RobotAPI/libraries/skills/provider/SkillProviderComponentPlugin.cpp @@ -3,6 +3,7 @@ #include <ArmarXCore/core/Component.h> #include <RobotAPI/libraries/aron/core/data/variant/primitive/All.h> +#include <RobotAPI/libraries/skills/core/ProviderInfo.h> namespace armarx::plugins { @@ -25,11 +26,10 @@ namespace armarx::plugins const std::string providerName = p.getName(); // register self to manager - skills::manager::dto::ProviderInfo i; - i.provider = myPrx; - i.providerId = {providerName}; - i.providedSkills = p.getSkillDescriptions(); - manager->addProvider(i); // add provider info to manager + skills::ProviderInfo i(skills::ProviderID(providerName), myPrx, getSkillDescriptions()); + + ARMARX_INFO << "Adding provider to manager: " << i.providerId; + manager->addProvider(i.toIce()); // add provider info to manager } void @@ -53,16 +53,6 @@ namespace armarx::plugins "The name of the SkillManager (or SkillMemory) proxy this provider belongs to."); } - void - SkillProviderComponentPlugin::addSkillFactory(const skills::LambdaSkill::FunT& f, - const skills::SkillDescription& desc) - { - auto fac = skills::SkillFactory::ForSkill<skills::LambdaSkill>(desc, desc, f); - // std::make_unique<skills::SkillFactory>( - // desc, [&]() { return std::make_unique<skills::LambdaSkill>(f, desc); }); - addSkillFactory(std::move(fac)); - } - void SkillProviderComponentPlugin::addSkillFactory(std::unique_ptr<skills::SkillFactory>&& fac) { @@ -72,11 +62,13 @@ namespace armarx::plugins } auto& p = parent<SkillProviderComponentPluginUser>(); - const std::string providerName = p.getName(); + const std::string componentName = p.getName(); + + const skills::ProviderID providerId({componentName}); // lock skills map const std::unique_lock l(skillFactoriesMutex); - auto skillId = fac->getSkillID(providerName); + auto skillId = fac->createSkillDescription(providerId).skillId; if (skillFactories.find(skillId) != skillFactories.end()) { @@ -85,11 +77,9 @@ namespace armarx::plugins return; } - ARMARX_INFO << "Adding skill `" << skillId << "` and set owning provider name to `" - << providerName << "` ."; - fac->setOwner(providerName); + ARMARX_INFO << "Adding skill `" << skillId << "` to component `" << componentName << "` ."; - skillFactories.emplace(fac->getSkillID(), std::move(fac)); + skillFactories.emplace(skillId, std::move(fac)); // if (connected) // { @@ -101,20 +91,31 @@ namespace armarx::plugins } skills::SkillFactory* - SkillProviderComponentPlugin::getSkillFactory(const armarx::skills::SkillID& skill) + SkillProviderComponentPlugin::addSkillFactory(const skills::SkillDescription& desc, + const skills::LambdaSkill::FunT& f) { - ARMARX_CHECK_GREATER(skillFactories.count(skill), 0) - << "Skill '" + skill.toString() + "' not found."; + return addSkillFactory<skills::LambdaSkill>(desc, f); + } - const std::unique_lock l(skillFactoriesMutex); - auto* facPtr = skillFactories.at(skill).get(); + skills::SkillFactory* + SkillProviderComponentPlugin::getSkillFactory(const armarx::skills::SkillID& skillId) + { + // 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."; + + auto* facPtr = skillFactories.at(skillId).get(); return static_cast<skills::SkillFactory*>(facPtr); } std::optional<skills::SkillStatusUpdate> SkillProviderComponentPlugin::getSkillExecutionStatus( - const skills::SkillExecutionId& execId) const + const skills::SkillExecutionID& execId) const { + ARMARX_CHECK(execId.skillId.skillSpecified()); + const std::unique_lock l(skillExecutionsMutex); if (skillExecutions.find(execId) != skillExecutions.end()) { @@ -126,10 +127,10 @@ namespace armarx::plugins return skillExecutions.at(execId).statusUpdate; } - std::map<skills::SkillExecutionId, skills::SkillStatusUpdate> + std::map<skills::SkillExecutionID, skills::SkillStatusUpdate> SkillProviderComponentPlugin::getSkillExecutionStatuses() const { - std::map<skills::SkillExecutionId, skills::SkillStatusUpdate> skillUpdates; + std::map<skills::SkillExecutionID, skills::SkillStatusUpdate> skillUpdates; const std::scoped_lock l(skillExecutionsMutex); for (const auto& [key, impl] : skillExecutions) @@ -143,6 +144,8 @@ namespace armarx::plugins std::optional<skills::SkillDescription> SkillProviderComponentPlugin::getSkillDescription(const skills::SkillID& skillId) const { + ARMARX_CHECK(skillId.fullySpecified()); + const std::unique_lock l(skillFactoriesMutex); if (skillFactories.find(skillId) != skillFactories.end()) { @@ -150,7 +153,7 @@ namespace armarx::plugins return std::nullopt; } - return skillFactories.at(skillId)->getSkillDescription(); + return skillFactories.at(skillId)->createSkillDescription(*skillId.providerId); } std::map<skills::SkillID, skills::SkillDescription> @@ -160,30 +163,34 @@ namespace armarx::plugins const std::unique_lock l(skillFactoriesMutex); for (const auto& [key, fac] : skillFactories) { - skillDesciptions.insert({key, fac->getSkillDescription()}); + ARMARX_CHECK(key.fullySpecified()); + skillDesciptions.insert({key, fac->createSkillDescription(*key.providerId)}); } return skillDesciptions; } skills::SkillStatusUpdate - SkillProviderComponentPlugin::executeSkill(const skills::SkillExecutionRequest& executionInfo) + SkillProviderComponentPlugin::executeSkill( + const skills::SkillExecutionRequest& executionRequest) { + ARMARX_CHECK(executionRequest.skillId.fullySpecified()); + // The skill will be executed in a seperate thread std::thread execution; // setup input args for skill execution - skills::SkillParameterization usedParameterization{executionInfo.params, - executionInfo.callbackInterface}; + skills::SkillParameterization usedParameterization{executionRequest.params, + executionRequest.callbackInterface}; - skills::SkillExecutionId execId( - executionInfo.skillId, executionInfo.executorName, armarx::core::time::DateTime::Now()); + skills::SkillExecutionID executionId(executionRequest.skillId, + executionRequest.executorName, + armarx::core::time::DateTime::Now()); - skills::SkillStatusUpdate ret{execId, usedParameterization}; + skills::SkillStatusUpdate ret{executionId, usedParameterization}; { auto l1 = std::unique_lock{skillFactoriesMutex}; - const auto& id = executionInfo.skillId; - const auto& fac = getSkillFactory(id); + const auto& fac = getSkillFactory(executionRequest.skillId); // async start execution. But we wait for the execution to finish at the end of this method execution = std::thread( @@ -194,11 +201,11 @@ namespace armarx::plugins const std::unique_lock l2{skillExecutionsMutex}; auto it = skillExecutions.emplace( std::piecewise_construct, - std::make_tuple(execId), - std::make_tuple(fac, execId, usedParameterization)); + std::make_tuple(executionId), + std::make_tuple(fac, executionId, usedParameterization)); ARMARX_CHECK(it.second) - << "For some reason a skill '" << execId.skillId.toString() + << "For some reason a skill '" << executionId.skillId.toString() << "' execution failed when instantiating the " "wrapper class and adding it to the internally used map. This " "should " @@ -221,7 +228,7 @@ namespace armarx::plugins // tidy up map of executions const std::unique_lock l2{skillExecutionsMutex}; - if (auto it = skillExecutions.find(execId); it != skillExecutions.end()) + if (auto it = skillExecutions.find(executionId); it != skillExecutions.end()) { skillExecutions.erase(it); } @@ -229,25 +236,27 @@ namespace armarx::plugins return ret; } - skills::SkillExecutionId + skills::SkillExecutionID SkillProviderComponentPlugin::executeSkillAsync( - const skills::SkillExecutionRequest& executionInfo) + const skills::SkillExecutionRequest& executionRequest) { + ARMARX_CHECK(executionRequest.skillId.fullySpecified()); + // The skill will be executed in a seperate thread std::thread execution; // setup input args for skill execution - skills::SkillParameterization usedParameterization{executionInfo.params, - executionInfo.callbackInterface}; + skills::SkillParameterization usedParameterization{executionRequest.params, + executionRequest.callbackInterface}; - skills::SkillExecutionId execId( - executionInfo.skillId, executionInfo.executorName, armarx::core::time::DateTime::Now()); + skills::SkillExecutionID executionId(executionRequest.skillId, + executionRequest.executorName, + armarx::core::time::DateTime::Now()); { auto l1 = std::unique_lock{skillFactoriesMutex}; - const auto& id = executionInfo.skillId; - const auto& fac = getSkillFactory(id); + const auto& fac = getSkillFactory(executionRequest.skillId); // async start execution. But we wait for the execution to finish at the end of this method execution = std::thread( @@ -258,11 +267,11 @@ namespace armarx::plugins const std::unique_lock l2{skillExecutionsMutex}; auto it = skillExecutions.emplace( std::piecewise_construct, - std::make_tuple(execId), - std::make_tuple(fac, execId, usedParameterization)); + std::make_tuple(executionId), + std::make_tuple(fac, executionId, usedParameterization)); ARMARX_CHECK(it.second) - << "For some reason a skill '" << execId.skillId.toString() + << "For some reason a skill '" << executionId.skillId.toString() << "' execution failed when instantiating the " "wrapper class and adding it to the internally used map. This " "should " @@ -278,18 +287,20 @@ namespace armarx::plugins } // release lock. We don't know how long the skill needs to finish and we have to release the lock for being able to abort the execution execution.detach(); - return execId; + return executionId; } void - SkillProviderComponentPlugin::addSkillParameters(const skills::SkillExecutionId& id, + SkillProviderComponentPlugin::addSkillParameters(const skills::SkillExecutionID& executionId, const armarx::aron::data::DictPtr& input) { + ARMARX_CHECK(executionId.skillId.fullySpecified()); + const std::scoped_lock l{skillExecutionsMutex}; - auto it = skillExecutions.find(id); + auto it = skillExecutions.find(executionId); if (it == skillExecutions.end()) { - ARMARX_INFO << "No acive execution for skill '" + id.skillId.toString() + + ARMARX_INFO << "No acive execution for skill '" + executionId.skillId.toString() + "' found! Ignoring prepareSkill request."; return; } @@ -297,7 +308,7 @@ namespace armarx::plugins std::scoped_lock l2{it->second.skillStatusesMutex}; if (it->second.statusUpdate.status != skills::SkillStatus::Preparing) { - ARMARX_INFO << "Could not prepare the skill '" + id.skillId.toString() + + ARMARX_INFO << "Could not prepare the skill '" + executionId.skillId.toString() + "' because its not in preparing phase."; return; } @@ -306,13 +317,15 @@ namespace armarx::plugins } void - SkillProviderComponentPlugin::abortSkill(const skills::SkillExecutionId& execId) + SkillProviderComponentPlugin::abortSkill(const skills::SkillExecutionID& executionId) { + ARMARX_CHECK(executionId.skillId.fullySpecified()); + const std::unique_lock l(skillExecutionsMutex); - auto it = skillExecutions.find(execId); + auto it = skillExecutions.find(executionId); if (it == skillExecutions.end()) { - ARMARX_INFO << "No acive execution for skill '" + execId.skillId.toString() + + ARMARX_INFO << "No acive execution for skill '" + executionId.skillId.toString() + "' found! Ignoring abortSkill request."; return; } @@ -329,26 +342,18 @@ namespace armarx addPlugin(plugin); } - void - SkillProviderComponentPluginUser::addSkillFactory(std::unique_ptr<skills::SkillFactory>&& skill) - { - plugin->addSkillFactory(std::move(skill)); - } - - void - SkillProviderComponentPluginUser::addSkillFactory(const skills::SkillDescription& desc, - const skills::LambdaSkill::FunT& f) - { - plugin->addSkillFactory(f, desc); - } - - skills::provider::dto::SkillDescription + IceUtil::Optional<skills::provider::dto::SkillDescription> SkillProviderComponentPluginUser::getSkillDescription( const skills::provider::dto::SkillID& skillId, const Ice::Current& /*unused*/) { auto id = skills::SkillID::FromIce(skillId, getName()); - return plugin->getSkillDescription(id)->toIce(); + auto o = plugin->getSkillDescription(id); + if (o.has_value()) + { + return o->toProviderIce(); + } + return {}; } skills::provider::dto::SkillDescriptionMap @@ -357,23 +362,23 @@ namespace armarx skills::provider::dto::SkillDescriptionMap ret; for (const auto& [k, v] : plugin->getSkillDescriptions()) { - ret.insert({k.toProviderIce(), v.toIce()}); + ret.insert({k.toProviderIce(), v.toProviderIce()}); } return ret; } - skills::provider::dto::SkillStatusUpdate + IceUtil::Optional<skills::provider::dto::SkillStatusUpdate> SkillProviderComponentPluginUser::getSkillExecutionStatus( const skills::provider::dto::SkillExecutionID& executionId, const Ice::Current& /*unused*/) { - auto execId = skills::SkillExecutionId::FromIce(executionId, getName()); + auto execId = skills::SkillExecutionID::FromIce(executionId, getName()); auto o = plugin->getSkillExecutionStatus(execId); if (o.has_value()) { return o->toProviderIce(); } - return {}; // TODO!! + return {}; } skills::provider::dto::SkillStatusUpdateMap @@ -393,7 +398,7 @@ namespace armarx const skills::provider::dto::SkillExecutionRequest& info, const Ice::Current& /*unused*/) { - auto exec = skills::SkillExecutionRequest::FromIce(info); + auto exec = skills::SkillExecutionRequest::FromIce(info, getName()); auto up = this->plugin->executeSkill(exec); return up.toProviderIce(); } @@ -403,7 +408,7 @@ namespace armarx const skills::provider::dto::SkillExecutionRequest& info, const Ice::Current& current /*unused*/) { - auto exec = skills::SkillExecutionRequest::FromIce(info); + auto exec = skills::SkillExecutionRequest::FromIce(info, getName()); auto id = this->plugin->executeSkillAsync(exec); return id.toProviderIce(); } @@ -414,7 +419,7 @@ namespace armarx const aron::data::dto::DictPtr& input, const Ice::Current& current /*unused*/) { - auto exec = skills::SkillExecutionId::FromIce(id, getName()); + auto exec = skills::SkillExecutionID::FromIce(id, getName()); auto prep = armarx::aron::data::Dict::FromAronDictDTO(input); this->plugin->addSkillParameters(exec, prep); } @@ -423,7 +428,7 @@ namespace armarx SkillProviderComponentPluginUser::abortSkill(const skills::provider::dto::SkillExecutionID& id, const Ice::Current& /*unused*/) { - auto exec = skills::SkillExecutionId::FromIce(id, getName()); + auto exec = skills::SkillExecutionID::FromIce(id, getName()); this->plugin->abortSkill(exec); } diff --git a/source/RobotAPI/libraries/skills/provider/SkillProviderComponentPlugin.h b/source/RobotAPI/libraries/skills/provider/SkillProviderComponentPlugin.h index 881b813c2..9550dec64 100644 --- a/source/RobotAPI/libraries/skills/provider/SkillProviderComponentPlugin.h +++ b/source/RobotAPI/libraries/skills/provider/SkillProviderComponentPlugin.h @@ -49,24 +49,37 @@ namespace armarx::plugins void preOnDisconnectComponent() override; - void addSkillFactory(const skills::LambdaSkill::FunT&, const skills::SkillDescription&); void addSkillFactory(std::unique_ptr<skills::SkillFactory>&&); - template <typename T, typename... Args> + skills::SkillFactory* addSkillFactory(const skills::SkillDescription&, + const skills::LambdaSkill::FunT&); - requires skills::isSkillFactory<T> T* - addSkillFactory(const skills::SkillID& id, Args&&... args) + template <class _Skill, typename... Args> + + requires skills::isSkill<_Skill> skills::SkillFactory* + addSkillFactory(Args&&... args) { - auto fac = std::make_unique<T>(id, std::forward<Args>(args)...); + auto fac = skills::SkillFactory::ForSkill<_Skill>(std::forward<Args>(args)...); auto* facPtr = fac.get(); addSkillFactory(std::move(fac)); - return static_cast<T*>(facPtr); + return static_cast<skills::SkillFactory*>(facPtr); + } + + template <typename _FactoryT, typename... Args> + + requires skills::isSkillFactory<_FactoryT> _FactoryT* + addCustomSkillFactory(Args&&... args) + { + auto fac = std::make_unique<_FactoryT>(std::forward<Args>(args)...); + auto* facPtr = fac.get(); + addCustomSkillFactory(std::move(fac)); + return static_cast<_FactoryT*>(facPtr); } // Ice forwards std::optional<skills::SkillStatusUpdate> - getSkillExecutionStatus(const skills::SkillExecutionId&) const; - std::map<skills::SkillExecutionId, skills::SkillStatusUpdate> + getSkillExecutionStatus(const skills::SkillExecutionID&) const; + std::map<skills::SkillExecutionID, skills::SkillStatusUpdate> getSkillExecutionStatuses() const; std::optional<skills::SkillDescription> getSkillDescription(const skills::SkillID&) const; @@ -74,13 +87,13 @@ namespace armarx::plugins skills::SkillStatusUpdate executeSkill(const skills::SkillExecutionRequest& executionInfo); - skills::SkillExecutionId + skills::SkillExecutionID executeSkillAsync(const skills::SkillExecutionRequest& executionInfo); - void addSkillParameters(const skills::SkillExecutionId& id, + void addSkillParameters(const skills::SkillExecutionID& id, const armarx::aron::data::DictPtr& params); - void abortSkill(const skills::SkillExecutionId& execId); + void abortSkill(const skills::SkillExecutionID& execId); private: skills::SkillFactory* getSkillFactory(const armarx::skills::SkillID& name); @@ -92,7 +105,7 @@ namespace armarx::plugins std::map<skills::SkillID, std::unique_ptr<skills::SkillFactory>> skillFactories; mutable std::mutex skillExecutionsMutex; - std::map<skills::SkillExecutionId, skills::detail::SkillImplementationWrapper> + std::map<skills::SkillExecutionID, skills::detail::SkillImplementationWrapper> skillExecutions; friend class armarx::SkillProviderComponentPluginUser; @@ -100,6 +113,7 @@ namespace armarx::plugins } // namespace armarx::plugins namespace armarx + { class SkillProviderComponentPluginUser : virtual public ManagedIceObject, @@ -109,14 +123,14 @@ namespace armarx SkillProviderComponentPluginUser(); // Ice Implementations - skills::provider::dto::SkillDescription + IceUtil::Optional<skills::provider::dto::SkillDescription> getSkillDescription(const skills::provider::dto::SkillID& skill, const Ice::Current& current = Ice::Current()) override; skills::provider::dto::SkillDescriptionMap getSkillDescriptions(const Ice::Current& current = Ice::Current()) override; - skills::provider::dto::SkillStatusUpdate + IceUtil::Optional<skills::provider::dto::SkillStatusUpdate> getSkillExecutionStatus(const skills::provider::dto::SkillExecutionID& executionId, const Ice::Current& current = Ice::Current()) override; @@ -144,14 +158,27 @@ namespace armarx protected: // utility - void addSkillFactory(const skills::SkillDescription&, const skills::LambdaSkill::FunT&); - void addSkillFactory(std::unique_ptr<skills::SkillFactory>&&); + skills::SkillFactory* + addSkillFactory(const skills::SkillDescription& desc, const skills::LambdaSkill::FunT& f) + { + auto ret = plugin->addSkillFactory(desc, f); + return ret; + } + + template <class _Skill, typename... Args> - template <typename T, typename... Args> - T* + requires skills::isSkill<_Skill> skills::SkillFactory* addSkillFactory(Args&&... args) { - return plugin->addSkillFactory<T>(std::forward<Args>(args)...); + return plugin->addSkillFactory<_Skill>(std::forward<Args>(args)...); + } + + template <typename _Fac, typename... Args> + + requires skills::isSkillFactory<_Fac> _Fac* + addCustomSkillFactory(Args&&... args) + { + return plugin->addSkillFactory<_Fac>(std::forward<Args>(args)...); } private: diff --git a/source/RobotAPI/libraries/skills/provider/SkillProxy.cpp b/source/RobotAPI/libraries/skills/provider/SkillProxy.cpp index 0c28fb5a6..3a969b281 100644 --- a/source/RobotAPI/libraries/skills/provider/SkillProxy.cpp +++ b/source/RobotAPI/libraries/skills/provider/SkillProxy.cpp @@ -6,79 +6,60 @@ namespace armarx { SkillProxy::SkillProxy(const manager::dti::SkillManagerInterfacePrx& manager, const SkillID& skillId) : - manager(manager), skillId(skillId) + manager(manager), + skillDescription(SkillDescription::FromIce( + manager->getSkillDescription(skillId.toManagerIce()).value())) { } SkillProxy::SkillProxy(const manager::dti::SkillManagerInterfacePrx& manager, - const std::string& skillProviderName, - const std::string& skillName) : - manager(manager), skillId(skillProviderName, skillName) - { - } - - SkillProxy::SkillProxy(const manager::dti::SkillManagerInterfacePrx& manager, - const std::string& skillProviderName, const SkillDescription& skillDesc) : - manager(manager), skillId(skillProviderName, skillDesc.skillId.skillName) + manager(manager), skillDescription(skillDesc) { + ARMARX_CHECK(skillDesc.skillId.fullySpecified()); } TerminatedSkillStatusUpdate - SkillProxy::executeFullSkill(const std::string& executorName, - const aron::data::DictPtr& params) + SkillProxy::executeSkill(const std::string& executorName, const aron::data::DictPtr& params) { skills::manager::dto::SkillExecutionRequest req; req.executorName = executorName; req.params = params->toAronDictDTO(); - req.skillId = skillId.toManagerIce(); + req.skillId = skillDescription.skillId.toManagerIce(); - auto terminatingUpdate = manager->executeSkill(req); - return TerminatedSkillStatusUpdate::FromIce(terminatingUpdate); + auto terminatingUpdateIce = manager->executeSkill(req); + return TerminatedSkillStatusUpdate::FromIce(terminatingUpdateIce); } - IceInternal::Handle<Ice::AsyncResult> - SkillProxy::begin_executeFullSkill(const std::string& executorName, - const aron::data::DictPtr& params) + SkillExecutionID + SkillProxy::executeSkillAsync(const std::string& executorName, + const aron::data::DictPtr& params) { skills::manager::dto::SkillExecutionRequest req; req.executorName = executorName; req.params = params->toAronDictDTO(); - req.skillId = skillId.toManagerIce(); + req.skillId = skillDescription.skillId.toManagerIce(); - auto future = manager->begin_executeSkill(req); - return future; + auto execReqIce = manager->executeSkillAsync(req); + return SkillExecutionID::FromIce(execReqIce); } void - SkillProxy::abortSkill(const std::string& executorName) + SkillProxy::abortSkill(const SkillExecutionID& id) { // TODO: This will be used in the future, do not remove it! - (void)executorName; - //manager->abortSkill(); + manager->abortSkill(id.toManagerIce()); } aron::data::DictPtr SkillProxy::getDefaultParameters(const std::string& profileName) { - // fabian.peller TODO: + if (profileName == "root") + { + return skillDescription.rootProfileParameterization; + } + // TODO @fabianPK return nullptr; } - - TerminatedSkillStatusUpdate - SkillProxy::executeFullSkillWithDefaultParams(const std::string& executorName, - const std::string& profileName, - const aron::data::DictPtr& params) - { - return executeFullSkill(executorName, params); - } - - IceInternal::Handle<Ice::AsyncResult> - SkillProxy::begin_executeFullSkillWithDefaultParams(const std::string& executorName, - const std::string& profileName, - const aron::data::DictPtr& params) - { - return begin_executeFullSkill(executorName, params); - } } // namespace skills } // namespace armarx diff --git a/source/RobotAPI/libraries/skills/provider/SkillProxy.h b/source/RobotAPI/libraries/skills/provider/SkillProxy.h index a77c86037..4cb09be79 100644 --- a/source/RobotAPI/libraries/skills/provider/SkillProxy.h +++ b/source/RobotAPI/libraries/skills/provider/SkillProxy.h @@ -13,38 +13,23 @@ namespace armarx SkillProxy(const manager::dti::SkillManagerInterfacePrx& manager, const SkillID& skillId); SkillProxy(const manager::dti::SkillManagerInterfacePrx& manager, - const std::string& skillProviderName, - const std::string& skillName); - SkillProxy(const manager::dti::SkillManagerInterfacePrx& manager, - const std::string& skillProviderName, const SkillDescription& skillDesc); // Provide a similar API as the skillprovider - TerminatedSkillStatusUpdate - executeFullSkill(const std::string& executorName, - const aron::data::DictPtr& params = nullptr); - IceInternal::Handle<Ice::AsyncResult> - begin_executeFullSkill(const std::string& executorName, - const aron::data::DictPtr& params = nullptr); + TerminatedSkillStatusUpdate executeSkill(const std::string& executorName, + const aron::data::DictPtr& params = nullptr); - void abortSkill(const std::string& executorName); + SkillExecutionID executeSkillAsync(const std::string& executorName, + const aron::data::DictPtr& params = nullptr); - // Utiliy methods - aron::data::DictPtr getDefaultParameters(const std::string& profileName); + void abortSkill(const SkillExecutionID& executorName); - TerminatedSkillStatusUpdate - executeFullSkillWithDefaultParams(const std::string& executorName, - const std::string& profileName, - const aron::data::DictPtr& params = nullptr); - IceInternal::Handle<Ice::AsyncResult> - begin_executeFullSkillWithDefaultParams(const std::string& executorName, - const std::string& profileName, - const aron::data::DictPtr& params = nullptr); + // Utiliy methods + aron::data::DictPtr getDefaultParameters(const std::string& profileName = "root"); private: - const manager::dti::SkillManagerInterfacePrx& manager; - - const SkillID skillId; + manager::dti::SkillManagerInterfacePrx manager; + SkillDescription skillDescription; }; } // namespace skills } // namespace armarx diff --git a/source/RobotAPI/libraries/skills/provider/SpecializedSkill.h b/source/RobotAPI/libraries/skills/provider/SpecializedSkill.h index c56953e46..9fc2beba6 100644 --- a/source/RobotAPI/libraries/skills/provider/SpecializedSkill.h +++ b/source/RobotAPI/libraries/skills/provider/SpecializedSkill.h @@ -14,6 +14,7 @@ namespace armarx class SpecializedSkill : public Skill { public: + using Base = Skill; using ParamType = AronT; struct SpecializedMainInput @@ -34,30 +35,9 @@ namespace armarx } - private: - /// Do not use anymore - Skill::InitResult - init() final - { - return InitResult{.status = TerminatedSkillStatus::Succeeded}; - } - - /// Do not use anymore - Skill::MainResult - main() final - { - ARMARX_IMPORTANT << "Dummy executing skill '" << description.skillId - << "'. Please overwrite this method."; - return Skill::MainResult{.status = TerminatedSkillStatus::Succeeded, - .data = nullptr}; - } - - /// Do not use anymore - Skill::ExitResult - exit() final - { - return ExitResult{.status = TerminatedSkillStatus::Succeeded}; - } + protected: + mutable std::mutex parametersMutex; + AronT parameters; }; } // namespace skills } // namespace armarx diff --git a/source/RobotAPI/libraries/skills/provider/detail/SkillImplementationWrapper.cpp b/source/RobotAPI/libraries/skills/provider/detail/SkillImplementationWrapper.cpp index bbe71e6ae..6846cca66 100644 --- a/source/RobotAPI/libraries/skills/provider/detail/SkillImplementationWrapper.cpp +++ b/source/RobotAPI/libraries/skills/provider/detail/SkillImplementationWrapper.cpp @@ -6,7 +6,7 @@ namespace armarx { SkillImplementationWrapper::SkillImplementationWrapper( const skills::SkillFactory* fac, - const skills::SkillExecutionId& execId, + const skills::SkillExecutionID& execId, const skills::SkillParameterization& param) : factory(fac), statusUpdate(execId, param) { @@ -57,11 +57,13 @@ namespace armarx // setup basic vars and lambdas // ------------------------------------------------------------------------------------- // 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 providerName = skillId.providerName; + const auto providerId = *skillId.providerId; const auto executorName = statusUpdate.executionId.executorName; ARMARX_INFO_S << "Executing skill: " << skillName; @@ -72,11 +74,15 @@ namespace armarx std::unique_lock l(skillStatusesMutex); statusUpdate.status = status; statusUpdate.data = data; - statusUpdate.usedParameterization.parameterization = skill->parameters; + if (skill) // if skill has been constructed + { + // update parameterization + statusUpdate.usedParameterization.parameterization = skill->getParameters(); + } - if (callback_interface) + if (callback_interface) // if callback interface is used { - skills::provider::dto::ProviderID pid({providerName}); + auto pid = providerId.toCallbackIce(); callback_interface->updateStatusForSkill(statusUpdate.toProviderIce(), pid); } }; @@ -110,7 +116,7 @@ namespace armarx // construct skill // ------------------------------------------------------------------------------------- updateStatus(SkillStatus::Constructing); - this->skill = this->factory->createSkill(); + this->skill = this->factory->createSkill(providerId); this->skill->executorName = (executorName); this->skill->callback = [&](const SkillStatus s, const armarx::aron::data::DictPtr& d) { updateStatus(s, d); }; @@ -131,15 +137,16 @@ namespace armarx // ------------------------------------------------------------------------------------- // Check params // ------------------------------------------------------------------------------------- - if (skill->description.acceptedType && initial_aron_params && - not(initial_aron_params->fullfillsType(skill->description.acceptedType))) - { - std::string message = - "SkillError 002: The Skill '" + skillName + - "' has a type and got parameters but the input does not match the type."; - ARMARX_ERROR_S << message; - return makeTerminationResult(message); - } + // NOT RELEVANT ANYMORE!! + // if (skill->getSkillDescription().acceptedType && initial_aron_params && + // not(initial_aron_params->fullfillsType(skill->getSkillDescription().acceptedType))) + // { + // std::string message = + // "SkillError 002: The Skill '" + skillName + + // "' has a type and got parameters but the input does not match the type."; + // ARMARX_ERROR_S << message; + // return makeTerminationResult(message); + // } auto exitAndMakeTerminationResult = [&](const std::string& message) @@ -181,11 +188,22 @@ namespace armarx // set initial parameters that were attached to the execution request skill->addParameters(initial_aron_params); - while (not skill->skillPreparationFinished()) + auto prepareRet = skill->prepareSkill(); + while (prepareRet.status == ActiveOrTerminatedSkillStatus::Running) { + ARMARX_INFO << deactivateSpam() << "Not all requirements for skill " + << skillName << " fulfilled. Waiting..."; + // wait... - skill->prepareSkill(); - std::this_thread::sleep_for(std::chrono::milliseconds(10)); + prepareRet = skill->prepareSkill(); + std::this_thread::sleep_for(std::chrono::milliseconds(50)); + } + + if (prepareRet.status != ActiveOrTerminatedSkillStatus::Succeeded) + { + std::string message = "SkillError 201: The prepare method of skill '" + + skillName + "' did not succeed."; + return exitAndMakeTerminationResult(message); } } diff --git a/source/RobotAPI/libraries/skills/provider/detail/SkillImplementationWrapper.h b/source/RobotAPI/libraries/skills/provider/detail/SkillImplementationWrapper.h index 8ae7dcf77..c57a05485 100644 --- a/source/RobotAPI/libraries/skills/provider/detail/SkillImplementationWrapper.h +++ b/source/RobotAPI/libraries/skills/provider/detail/SkillImplementationWrapper.h @@ -32,7 +32,7 @@ namespace armarx // ctor SkillImplementationWrapper(const skills::SkillFactory* fac, - const skills::SkillExecutionId&, + const skills::SkillExecutionID&, const skills::SkillParameterization&); // execute a skill. The parameterization is copied. T -- GitLab