5#include <experimental/memory>
10#include <shared_mutex>
17#include <Ice/Current.h>
18#include <IceUtil/Optional.h>
26#include <RobotAPI/interface/aron/Aron.h>
27#include <RobotAPI/interface/skills/SkillManagerInterface.h>
28#include <RobotAPI/interface/skills/SkillProviderInterface.h>
53 p.getProxy(myPrx, -1);
60 const std::string providerName = p.getName();
64 .providerInterface = myPrx,
67 ARMARX_INFO <<
"Adding provider to manager: " << i.providerId;
68 manager->addProvider(i.toIce());
75 std::string providerName = p.getName();
77 auto id = skills::manager::dto::ProviderID{providerName};
78 manager->removeProvider(
id);
84 std::vector<std::shared_ptr<skills::detail::SkillRuntime>> drained;
86 const std::unique_lock l(skillExecutionsMutex);
87 for (
auto& [
id, runtime] : skillExecutions)
89 drained.push_back(std::move(runtime));
91 skillExecutions.clear();
93 for (
auto& runtime : drained)
95 if (runtime && runtime->execution.joinable())
99 runtime->execution.join();
101 catch (
const std::exception& e)
113 skillFactories.clear();
119 std::string
prefix =
"skill.";
120 properties->component(
124 "The name of the SkillManager (or SkillMemory) proxy this provider belongs to.");
125 properties->topic<armarx::skills::SkillEventListenerInterface>(
126 "SkillEventListener",
prefix +
"tpc.sub.SkillEventListener");
138 const std::string componentName = p.getName();
143 const std::unique_lock l(skillFactoriesMutex);
144 auto skillId = fac->createSkillDescription(providerId).skillId;
146 if (skillFactories.find(skillId) != skillFactories.end())
148 ARMARX_WARNING <<
"Try to add a skill factory for skill '" + skillId.toString() +
149 "' which already exists in list. Ignoring this skill.";
153 ARMARX_INFO <<
"Adding skill `" << skillId <<
"` to component `" << componentName <<
"` .";
155 skillFactories.emplace(skillId, std::move(fac));
180 if (skillFactories.count(skillId) == 0)
182 ARMARX_INFO <<
"Could not find a skill factory for id: " << skillId;
186 auto* facPtr = skillFactories.at(skillId).get();
190 std::optional<skills::SkillStatusUpdate>
196 const std::shared_lock l(skillExecutionsMutex);
197 auto it = skillExecutions.find(execId);
198 if (it == skillExecutions.end())
205 std::scoped_lock l2{it->second->skillStatusesMutex};
206 return it->second->statusUpdate;
209 std::map<skills::SkillExecutionID, skills::SkillStatusUpdate>
212 std::map<skills::SkillExecutionID, skills::SkillStatusUpdate> skillUpdates;
214 const std::shared_lock l(skillExecutionsMutex);
215 for (
const auto& [key, impl] : skillExecutions)
217 const std::scoped_lock l2(impl->skillStatusesMutex);
218 skillUpdates.insert({key, impl->statusUpdate});
223 std::optional<skills::SkillDescription>
228 const std::shared_lock l(skillFactoriesMutex);
229 if (skillFactories.find(skillId) == skillFactories.end())
231 std::stringstream ss;
232 ss <<
"Skill description for skill '" + skillId.
toString() +
233 "' not found! Found instead: {"
235 for (
const auto& [k, _] : skillFactories)
237 ss <<
"\t" << k.toString() <<
"\n";
245 return skillFactories.at(skillId)->createSkillDescription(*skillId.
providerId);
248 std::map<skills::SkillID, skills::SkillDescription>
251 std::map<skills::SkillID, skills::SkillDescription> skillDesciptions;
252 const std::shared_lock l(skillFactoriesMutex);
253 for (
const auto& [key, fac] : skillFactories)
256 skillDesciptions.insert({key, fac->createSkillDescription(*key.providerId)});
258 return skillDesciptions;
269 .executionStartedTime =
275 std::shared_ptr<skills::detail::SkillRuntime> runtime;
276 std::vector<std::shared_ptr<skills::detail::SkillRuntime>> finishedToJoin;
278 auto l1 = std::unique_lock{skillFactoriesMutex};
280 const auto& fac = getSkillFactory(executionId.skillId);
281 ARMARX_CHECK(fac) <<
"Could not find a factory for skill " << executionId.skillId;
284 const std::unique_lock l2{skillExecutionsMutex};
289 finishedToJoin = collectFinishedExecutions_locked();
291 runtime = std::make_shared<skills::detail::SkillRuntime>(
296 skillExecutions.emplace(executionId, runtime);
300 runtime->setLocalMinimumLoggingLevel(loggingLevel);
307 runtime->execution = std::thread(
312 auto x = runtime->executeSkill();
313 ret.result =
x.result;
316 catch (std::exception& e)
319 "skill. Exception was: "
327 for (
auto& finished : finishedToJoin)
329 if (finished && finished->execution.joinable())
331 finished->execution.join();
334 finishedToJoin.clear();
336 if (runtime && runtime->execution.joinable())
338 runtime->execution.join();
351 std::shared_ptr<skills::detail::SkillRuntime> runtime;
352 std::vector<std::shared_ptr<skills::detail::SkillRuntime>> finishedToJoin;
354 auto l1 = std::unique_lock{skillFactoriesMutex};
356 const auto& fac = getSkillFactory(executionRequest.
skillId);
360 const std::unique_lock l2{skillExecutionsMutex};
363 finishedToJoin = collectFinishedExecutions_locked();
369 if (skillExecutions.count(executionId) > 0)
371 ARMARX_ERROR <<
"SkillsExecutionID already exists! This is undefined behaviour "
372 "and should not occur!";
375 runtime = std::make_shared<skills::detail::SkillRuntime>(
380 skillExecutions.emplace(executionId, runtime);
382 ARMARX_INFO <<
"Setting skill runtime's logging level to `"
384 runtime->setLocalMinimumLoggingLevel(loggingLevel);
390 runtime->execution = std::thread(
395 auto x = runtime->executeSkill();
398 catch (std::exception& e)
401 "skill. Exception was: "
409 for (
auto& finished : finishedToJoin)
411 if (finished && finished->execution.joinable())
413 finished->execution.join();
416 finishedToJoin.clear();
422 std::scoped_lock l(runtime->skillStatusesMutex);
424 if (runtime->statusUpdate.hasBeenConstructed())
430 std::this_thread::sleep_for(std::chrono::milliseconds(20));
442 std::shared_ptr<skills::detail::SkillRuntime> runtime;
444 std::shared_lock l{skillExecutionsMutex};
445 auto it = skillExecutions.find(executionId);
446 if (it == skillExecutions.end())
449 "' found! Ignoring prepareSkill request.";
452 runtime = it->second;
455 std::scoped_lock l2{runtime->skillStatusesMutex};
459 "' because its not in preparing phase.";
463 runtime->updateSkillParameters(input);
472 std::shared_ptr<skills::detail::SkillRuntime> runtime;
474 std::shared_lock l(skillExecutionsMutex);
475 auto it = skillExecutions.find(executionId);
476 if (it == skillExecutions.end())
479 "' found! Ignoring abortSkill request.";
482 runtime = it->second;
485 runtime->stopSkill();
490 std::scoped_lock l2(runtime->skillStatusesMutex);
491 auto status = runtime->statusUpdate;
493 if (
status.hasBeenTerminated())
498 std::this_thread::sleep_for(std::chrono::milliseconds(20));
509 std::shared_ptr<skills::detail::SkillRuntime> runtime;
511 std::shared_lock l(skillExecutionsMutex);
512 auto it = skillExecutions.find(executionId);
513 if (it == skillExecutions.end())
516 "' found! Ignoring abortSkill request.";
519 runtime = it->second;
522 runtime->stopSkill();
533 std::shared_ptr<skills::detail::SkillRuntime>>>
536 std::shared_lock l(skillExecutionsMutex);
537 snapshot.reserve(skillExecutions.size());
538 for (
const auto& [
id, runtime] : skillExecutions)
540 snapshot.emplace_back(
id, runtime);
543 for (
auto& [
id, runtime] : snapshot)
545 ARMARX_DEBUG <<
"updating subskill status for " <<
id.toString() <<
" with "
547 runtime->updateSubSkillStatus(statusUpdate);
551 const skills::manager::dti::SkillManagerInterfacePrx&
557 std::vector<std::shared_ptr<skills::detail::SkillRuntime>>
558 SkillProviderComponentPlugin::collectFinishedExecutions_locked()
566 std::vector<std::shared_ptr<skills::detail::SkillRuntime>> ret;
567 for (
auto it = skillExecutions.begin(); it != skillExecutions.end();)
569 const auto& runtime = it->second;
570 bool terminated =
false;
572 std::scoped_lock statusLock(runtime->skillStatusesMutex);
573 terminated = runtime->statusUpdate.hasBeenTerminated();
577 ret.push_back(std::move(it->second));
578 it = skillExecutions.erase(it);
596 IceUtil::Optional<skills::provider::dto::SkillDescription>
598 const skills::provider::dto::SkillID& skillId,
599 const Ice::Current& )
602 auto o = plugin->getSkillDescription(
id);
605 return o->toProviderIce();
610 skills::provider::dto::SkillDescriptionMap
613 skills::provider::dto::SkillDescriptionMap ret;
614 for (
const auto& [k, v] : plugin->getSkillDescriptions())
616 ret.insert({k.toProviderIce(), v.toProviderIce()});
621 IceUtil::Optional<skills::provider::dto::SkillStatusUpdate>
623 const skills::provider::dto::SkillExecutionID& executionId,
624 const Ice::Current& )
628 auto o = plugin->getSkillExecutionStatus(execId);
631 return o->toProviderIce();
636 skills::provider::dto::SkillStatusUpdateMap
639 skills::provider::dto::SkillStatusUpdateMap ret;
640 for (
const auto& [k, v] : plugin->getSkillExecutionStatuses())
642 ret.insert({k.toProviderIce(), v.toProviderIce()});
648 skills::provider::dto::SkillStatusUpdate
650 const skills::provider::dto::SkillExecutionRequest& info,
651 const Ice::Current& )
655 auto up = this->plugin->executeSkill(exec);
656 return up.toProviderIce();
659 skills::provider::dto::SkillExecutionID
661 const skills::provider::dto::SkillExecutionRequest& info,
662 const Ice::Current& current )
666 auto id = this->plugin->executeSkillAsync(exec);
670 skills::provider::dto::ParameterUpdateResult
672 const skills::provider::dto::SkillExecutionID&
id,
674 const Ice::Current& current )
676 skills::provider::dto::ParameterUpdateResult res;
681 res.success = this->plugin->updateSkillParameters(exec, prep);
685 skills::provider::dto::AbortSkillResult
687 const Ice::Current& )
689 skills::provider::dto::AbortSkillResult res;
692 res.success = this->plugin->abortSkill(exec);
696 skills::provider::dto::AbortSkillResult
698 const skills::provider::dto::SkillExecutionID&
id,
699 const Ice::Current& )
701 skills::provider::dto::AbortSkillResult res;
704 res.success = this->plugin->abortSkillAsync(exec);
710 const skills::provider::dto::SkillStatusUpdate& statusUpdate,
711 const std::string& providerName,
712 const Ice::Current& )
715 status.executionId.skillId.providerId.emplace().providerName = providerName;
716 plugin->updateSubSkillStatus(
status);
static std::string levelToString(MessageTypeT type)
MessageTypeT getEffectiveLoggingLevel() const
ManagedIceObject & parent()
const std::string & prefix() const
PluginT * addPlugin(const std::string prefix="", ParamsT &&... params)
std::string getName() const
Retrieve name of object.
IceUtil::Optional< skills::provider::dto::SkillStatusUpdate > getSkillExecutionStatus(const skills::provider::dto::SkillExecutionID &executionId, const Ice::Current ¤t=Ice::Current()) override
skills::provider::dto::SkillStatusUpdateMap getSkillExecutionStatuses(const Ice::Current ¤t=Ice::Current()) override
SkillProviderComponentPluginUser()
skills::provider::dto::AbortSkillResult abortSkill(const skills::provider::dto::SkillExecutionID &skill, const Ice::Current ¤t=Ice::Current()) override
IceUtil::Optional< skills::provider::dto::SkillDescription > getSkillDescription(const skills::provider::dto::SkillID &skill, const Ice::Current ¤t=Ice::Current()) override
skills::provider::dto::SkillStatusUpdate executeSkill(const skills::provider::dto::SkillExecutionRequest &executionInfo, const Ice::Current ¤t=Ice::Current()) override
skills::provider::dto::SkillExecutionID executeSkillAsync(const skills::provider::dto::SkillExecutionRequest &executionInfo, const Ice::Current ¤t=Ice::Current()) override
skills::provider::dto::AbortSkillResult abortSkillAsync(const skills::provider::dto::SkillExecutionID &skill, const Ice::Current ¤t=Ice::Current()) override
const std::experimental::observer_ptr< plugins::SkillProviderComponentPlugin > & getSkillProviderPlugin() const
void reportSkillEvent(const skills::provider::dto::SkillStatusUpdate &statusUpdate, const std::string &providerName, const Ice::Current ¤t) override
skills::provider::dto::ParameterUpdateResult updateSkillParameters(const skills::provider::dto::SkillExecutionID &executionId, const armarx::aron::data::dto::DictPtr ¶meters, const Ice::Current ¤t=Ice::Current()) override
skills::provider::dto::SkillDescriptionMap getSkillDescriptions(const Ice::Current ¤t=Ice::Current()) override
static PointerType FromAronDictDTO(const data::dto::DictPtr &aron)
skills::SkillExecutionID executeSkillAsync(const skills::SkillExecutionRequest &executionInfo)
bool abortSkill(const skills::SkillExecutionID &execId)
skills::SkillStatusUpdate executeSkill(const skills::SkillExecutionRequest &executionInfo)
std::optional< skills::SkillStatusUpdate > getSkillExecutionStatus(const skills::SkillExecutionID &) const
void preOnInitComponent() override
std::optional< skills::SkillDescription > getSkillDescription(const skills::SkillID &) const
void preOnConnectComponent() override
void postOnConnectComponent() override
void postCreatePropertyDefinitions(PropertyDefinitionsPtr &properties) override
const skills::manager::dti::SkillManagerInterfacePrx & skillManager() const
std::map< skills::SkillExecutionID, skills::SkillStatusUpdate > getSkillExecutionStatuses() const
void addSkillFactory(std::unique_ptr< skills::SkillBlueprint > &&)
bool updateSkillParameters(const skills::SkillExecutionID &id, const armarx::aron::data::DictPtr ¶ms)
std::map< skills::SkillID, skills::SkillDescription > getSkillDescriptions() const
void preOnDisconnectComponent() override
void updateSubSkillStatus(const skills::SkillStatusUpdate &statusUpdate)
bool abortSkillAsync(const skills::SkillExecutionID &execId)
std::function< TerminatedSkillStatus()> FunctionType
callback::dti::SkillProviderCallbackInterfacePrx callbackInterface
static SkillExecutionRequest FromIce(const manager::dto::SkillExecutionRequest &)
armarx::aron::data::DictPtr parameters
provider::dto::SkillExecutionRequest toProviderIce() const
std::string toString() const
std::optional< ProviderID > providerId
bool isFullySpecified() const
bool isSkillSpecified() const
static SkillID FromIce(const manager::dto::SkillID &)
#define ARMARX_CHECK(expression)
Shortcut for ARMARX_CHECK_EXPRESSION.
#define ARMARX_INFO
The normal logging level.
#define ARMARX_ERROR
The logging level for unexpected behaviour, that must be fixed.
#define ARMARX_DEBUG
The logging level for output that is only interesting while debugging.
#define ARMARX_WARNING
The logging level for unexpected behaviour, but not a serious problem.
#define ARMARX_VERBOSE
The logging level for verbose information.
::IceInternal::Handle< Dict > DictPtr
std::shared_ptr< Dict > DictPtr
This file is part of ArmarX.
SkillStatus toSkillStatus(const ActiveOrTerminatedSkillStatus &d)
This file offers overloads of toIce() and fromIce() functions for STL container types.
IceUtil::Handle< class PropertyDefinitionContainer > PropertyDefinitionsPtr
PropertyDefinitions smart pointer type.
std::string toString() const
static SkillExecutionID FromIce(const skills::manager::dto::SkillExecutionID &)
SkillExecutionID executionId
static SkillStatusUpdate FromIce(const provider::dto::SkillStatusUpdate &update, const std::optional< skills::ProviderID > &providerId=std::nullopt)