SkillProviderComponentPlugin.cpp
Go to the documentation of this file.
2
3#include <chrono>
4#include <exception>
5#include <experimental/memory>
6#include <map>
7#include <memory>
8#include <mutex>
9#include <optional>
10#include <shared_mutex>
11#include <sstream>
12#include <string>
13#include <thread>
14#include <tuple>
15#include <utility>
16
17#include <Ice/Current.h>
18#include <Ice/LocalException.h>
19#include <IceUtil/Optional.h>
20
27
28#include <RobotAPI/interface/aron/Aron.h>
29#include <RobotAPI/interface/skills/SkillManagerInterface.h>
30#include <RobotAPI/interface/skills/SkillProviderInterface.h>
43
44namespace armarx::plugins
45{
46 void
50
51 void
57
58 void
60 {
62 const std::string providerName = p.getName();
63
64 // register self to manager
65 skills::ProviderInfo i{.providerId = skills::ProviderID{.providerName = providerName},
66 .providerInterface = myPrx,
67 .providedSkills = getSkillDescriptions()};
68
69 ARMARX_INFO << "Adding provider to manager: " << i.providerId;
70 manager->addProvider(i.toIce()); // add provider info to manager
71 }
72
73 void
75 {
77 std::string providerName = p.getName();
78
79 auto id = skills::manager::dto::ProviderID{providerName};
80 try
81 {
82 manager->removeProvider(id);
83 }
84 catch (const Ice::LocalException& e)
85 {
86 ARMARX_WARNING << "Failed to remove provider '" << providerName
87 << "' from the skill manager: " << e.what();
88 }
89
90 // Drain all in-flight executions before tearing down the runtimes.
91 // Joining must happen before destroying the SkillRuntime objects
92 // because each runtime owns its own std::thread, which must not be
93 // destroyed while joinable (would call std::terminate).
94 std::vector<std::shared_ptr<skills::detail::SkillRuntime>> drained;
95 {
96 const std::unique_lock l(skillExecutionsMutex);
97 for (auto& [id, runtime] : skillExecutions)
98 {
99 drained.push_back(std::move(runtime));
100 }
101 skillExecutions.clear();
102 }
103 ARMARX_INFO << "Waiting for " << drained.size()
104 << " skill executions to finish before disconnect.";
105 for (auto& runtime : drained)
106 {
107 if (not runtime or not runtime->execution.joinable())
108 {
109 continue;
110 }
111 try
112 {
113 runtime->stopSkill();
114 }
115 catch (...)
116 {
117 ARMARX_WARNING << "Failed to stop skill execution '"
118 << runtime->statusUpdate.executionId.skillId
119 << "' during disconnect: " << GetHandledExceptionString();
120 }
121
122 const auto deadline = std::chrono::steady_clock::now() + std::chrono::seconds(5);
123 bool terminated = false;
124 while (not terminated and std::chrono::steady_clock::now() < deadline)
125 {
126 {
127 std::scoped_lock l(runtime->skillStatusesMutex);
128 terminated = runtime->statusUpdate.hasBeenTerminated();
129 }
130 if (not terminated)
131 {
132 std::this_thread::sleep_for(std::chrono::milliseconds(20));
133 }
134 }
135
136 if (terminated)
137 {
138 runtime->execution.join();
139 }
140 else
141 {
142 ARMARX_WARNING << "Skill execution '" << runtime->statusUpdate.executionId.skillId
143 << "' did not terminate within 5s during disconnect. Detaching.";
144 runtime->execution.detach();
145 }
146 }
147 drained.clear();
148
149 // remove all skills
150 ARMARX_INFO << "Removing all skills";
151 skillFactories.clear();
152 }
153
154 void
156 {
157 std::string prefix = "skill.";
158 properties->component(
159 manager,
160 "SkillMemory",
161 prefix + "SkillManager",
162 "The name of the SkillManager (or SkillMemory) proxy this provider belongs to.");
163 properties->topic<armarx::skills::SkillEventListenerInterface>(
164 "SkillEventListener", prefix + "tpc.sub.SkillEventListener");
165 }
166
167 void
168 SkillProviderComponentPlugin::addSkillFactory(std::unique_ptr<skills::SkillBlueprint>&& fac)
169 {
170 if (!fac)
171 {
172 return;
173 }
174
176 const std::string componentName = p.getName();
177
178 const skills::ProviderID providerId({componentName});
179
180 // lock skills map
181 const std::unique_lock l(skillFactoriesMutex);
182 auto skillId = fac->createSkillDescription(providerId).skillId;
183
184 if (skillFactories.find(skillId) != skillFactories.end())
185 {
186 ARMARX_WARNING << "Try to add a skill factory for skill '" + skillId.toString() +
187 "' which already exists in list. Ignoring this skill.";
188 return;
189 }
190
191 ARMARX_INFO << "Adding skill `" << skillId << "` to component `" << componentName << "` .";
192
193 skillFactories.emplace(skillId, std::move(fac));
194
195
196 // if (connected)
197 // {
198 // // if skill is added after onConnect we have to set the proxies manually.
199 // std::string providerName = parent().getName();
200 // s.first->second.skill->manager = manager;
201 // s.first->second.skill->providerName = providerName;
202 // }
203 }
204
211
213 SkillProviderComponentPlugin::getSkillFactory(const armarx::skills::SkillID& skillId)
214 {
215 // NON BLOCKING: WE ASSERT THAT THE LOCK IS ALREADY TAKEN
217
218 if (skillFactories.count(skillId) == 0)
219 {
220 ARMARX_INFO << "Could not find a skill factory for id: " << skillId;
221 return nullptr;
222 }
223
224 auto* facPtr = skillFactories.at(skillId).get();
225 return static_cast<skills::SkillBlueprint*>(facPtr);
226 }
227
228 std::optional<skills::SkillStatusUpdate>
230 const skills::SkillExecutionID& execId) const
231 {
233
234 const std::shared_lock l(skillExecutionsMutex);
235 auto it = skillExecutions.find(execId);
236 if (it == skillExecutions.end())
237 {
238 ARMARX_WARNING << "Skill execution for skill '" + execId.skillId.toString() +
239 "' not found!";
240 return std::nullopt;
241 }
242
243 std::scoped_lock l2{it->second->skillStatusesMutex};
244 return it->second->statusUpdate;
245 }
246
247 std::map<skills::SkillExecutionID, skills::SkillStatusUpdate>
249 {
250 std::map<skills::SkillExecutionID, skills::SkillStatusUpdate> skillUpdates;
251
252 const std::shared_lock l(skillExecutionsMutex);
253 for (const auto& [key, impl] : skillExecutions)
254 {
255 const std::scoped_lock l2(impl->skillStatusesMutex);
256 skillUpdates.insert({key, impl->statusUpdate});
257 }
258 return skillUpdates;
259 }
260
261 std::optional<skills::SkillDescription>
263 {
265
266 const std::shared_lock l(skillFactoriesMutex);
267 if (skillFactories.find(skillId) == skillFactories.end())
268 {
269 std::stringstream ss;
270 ss << "Skill description for skill '" + skillId.toString() +
271 "' not found! Found instead: {"
272 << "\n";
273 for (const auto& [k, _] : skillFactories)
274 {
275 ss << "\t" << k.toString() << "\n";
276 }
277 ss << "}";
278 ARMARX_WARNING << ss.str();
279
280 return std::nullopt;
281 }
282
283 return skillFactories.at(skillId)->createSkillDescription(*skillId.providerId);
284 }
285
286 std::map<skills::SkillID, skills::SkillDescription>
288 {
289 std::map<skills::SkillID, skills::SkillDescription> skillDesciptions;
290 const std::shared_lock l(skillFactoriesMutex);
291 for (const auto& [key, fac] : skillFactories)
292 {
293 ARMARX_CHECK(key.isFullySpecified());
294 skillDesciptions.insert({key, fac->createSkillDescription(*key.providerId)});
295 }
296 return skillDesciptions;
297 }
298
301 const skills::SkillExecutionRequest& executionRequest)
302 {
303 ARMARX_CHECK(executionRequest.skillId.isFullySpecified());
304
305 skills::SkillExecutionID executionId{.skillId = executionRequest.skillId,
306 .executorName = executionRequest.executorName,
307 .executionStartedTime =
309
311 {executionId, executionRequest.parameters, executionRequest.callbackInterface}};
312
313 std::shared_ptr<skills::detail::SkillRuntime> runtime;
314 std::vector<std::shared_ptr<skills::detail::SkillRuntime>> finishedToJoin;
315 {
316 auto l1 = std::unique_lock{skillFactoriesMutex};
317
318 const auto& fac = getSkillFactory(executionId.skillId);
319 ARMARX_CHECK(fac) << "Could not find a factory for skill " << executionId.skillId;
320
321 {
322 const std::unique_lock l2{skillExecutionsMutex};
323
324 // Drop terminated executions from the map. Joining must be
325 // done outside the lock to avoid blocking other API calls
326 // while we wait for a thread to finish.
327 finishedToJoin = collectFinishedExecutions_locked();
328
329 runtime = std::make_shared<skills::detail::SkillRuntime>(
330 fac,
331 executionId,
332 executionRequest.parameters,
333 executionRequest.callbackInterface);
334 skillExecutions.emplace(executionId, runtime);
335 auto const loggingLevel = parent().getEffectiveLoggingLevel();
336 ARMARX_VERBOSE << "Setting skill runtime's logging level to `"
337 << armarx::LogSender::levelToString(loggingLevel) << "`.";
338 runtime->setLocalMinimumLoggingLevel(loggingLevel);
339
340 // Capture the shared_ptr by VALUE so the runtime is kept
341 // alive for as long as the lambda runs, even if the map
342 // entry is erased concurrently. `ret` is captured by
343 // reference because we join the thread before returning
344 // from this function.
345 runtime->execution = std::thread(
346 [runtime, &ret]()
347 {
348 try
349 {
350 auto x = runtime->executeSkill();
351 ret.result = x.result;
352 ret.status = armarx::skills::toSkillStatus(x.status);
353 }
354 catch (std::exception& e)
355 {
356 ARMARX_WARNING << "Got an uncaught exception when executing a "
357 "skill. Exception was: "
358 << e.what();
359 }
360 });
361 }
362 } // 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
363
364 // Drain previously finished executions outside the lock.
365 for (auto& finished : finishedToJoin)
366 {
367 if (finished && finished->execution.joinable())
368 {
369 finished->execution.join();
370 }
371 }
372 finishedToJoin.clear();
373
374 if (runtime && runtime->execution.joinable())
375 {
376 runtime->execution.join();
377 }
378 return ret;
379 }
380
383 const skills::SkillExecutionRequest& executionRequest)
384 {
385 ARMARX_CHECK(executionRequest.skillId.isFullySpecified());
386
387 skills::SkillExecutionID executionId;
388
389 std::shared_ptr<skills::detail::SkillRuntime> runtime;
390 std::vector<std::shared_ptr<skills::detail::SkillRuntime>> finishedToJoin;
391 {
392 auto l1 = std::unique_lock{skillFactoriesMutex};
393
394 const auto& fac = getSkillFactory(executionRequest.skillId);
395 ARMARX_CHECK(fac) << "Could not find a factory for skill " << executionRequest.skillId;
396
397 {
398 const std::unique_lock l2{skillExecutionsMutex};
399
400 // Drop terminated executions from the map.
401 finishedToJoin = collectFinishedExecutions_locked();
402
403 executionId = skills::SkillExecutionID{executionRequest.skillId,
404 executionRequest.executorName,
406
407 if (skillExecutions.count(executionId) > 0)
408 {
409 ARMARX_ERROR << "SkillsExecutionID already exists! This is undefined behaviour "
410 "and should not occur!";
411 }
412
413 runtime = std::make_shared<skills::detail::SkillRuntime>(
414 fac,
415 executionId,
416 executionRequest.parameters,
417 executionRequest.callbackInterface);
418 skillExecutions.emplace(executionId, runtime);
419 auto const loggingLevel = parent().getEffectiveLoggingLevel();
420 ARMARX_INFO << "Setting skill runtime's logging level to `"
421 << armarx::LogSender::levelToString(loggingLevel) << "`.";
422 runtime->setLocalMinimumLoggingLevel(loggingLevel);
423
424 // Capture the shared_ptr by VALUE. The function returns
425 // before the thread finishes, so a reference capture would
426 // dangle as soon as the local `runtime` variable is
427 // destroyed -> use-after-free.
428 runtime->execution = std::thread(
429 [runtime]()
430 {
431 try
432 {
433 auto x = runtime->executeSkill();
434 (void)x;
435 }
436 catch (std::exception& e)
437 {
438 ARMARX_WARNING << "Got an uncaught exception when executing a "
439 "skill. Exception was: "
440 << e.what();
441 }
442 });
443 }
444 }
445
446 // Drain previously finished executions outside the lock.
447 for (auto& finished : finishedToJoin)
448 {
449 if (finished && finished->execution.joinable())
450 {
451 finished->execution.join();
452 }
453 }
454 finishedToJoin.clear();
455
456 // wait until skill is constructed. This assures, that a status update exists.
457 while (true)
458 {
459 {
460 std::scoped_lock l(runtime->skillStatusesMutex);
461
462 if (runtime->statusUpdate.hasBeenConstructed())
463 {
464 break;
465 }
466 }
467
468 std::this_thread::sleep_for(std::chrono::milliseconds(20));
469 }
470
471 return executionId;
472 }
473
474 bool
476 const armarx::aron::data::DictPtr& input)
477 {
479
480 std::shared_ptr<skills::detail::SkillRuntime> runtime;
481 {
482 std::shared_lock l{skillExecutionsMutex};
483 auto it = skillExecutions.find(executionId);
484 if (it == skillExecutions.end())
485 {
486 ARMARX_INFO << "No acive execution for skill '" + executionId.skillId.toString() +
487 "' found! Ignoring prepareSkill request.";
488 return false;
489 }
490 runtime = it->second;
491 }
492
493 std::scoped_lock l2{runtime->skillStatusesMutex};
494 if (runtime->statusUpdate.status != skills::SkillStatus::Preparing)
495 {
496 ARMARX_INFO << "Could not prepare the skill '" + executionId.skillId.toString() +
497 "' because its not in preparing phase.";
498 return false;
499 }
500
501 runtime->updateSkillParameters(input);
502 return true;
503 }
504
505 bool
507 {
509
510 std::shared_ptr<skills::detail::SkillRuntime> runtime;
511 {
512 std::shared_lock l(skillExecutionsMutex);
513 auto it = skillExecutions.find(executionId);
514 if (it == skillExecutions.end())
515 {
516 ARMARX_INFO << "No acive execution for skill '" + executionId.skillId.toString() +
517 "' found! Ignoring abortSkill request.";
518 return false;
519 }
520 runtime = it->second;
521 }
522
523 runtime->stopSkill();
524
525 while (true)
526 {
527 {
528 std::scoped_lock l2(runtime->skillStatusesMutex);
529 auto status = runtime->statusUpdate;
530
531 if (status.hasBeenTerminated())
532 {
533 break;
534 }
535 }
536 std::this_thread::sleep_for(std::chrono::milliseconds(20));
537 }
538
539 return true;
540 }
541
542 bool
544 {
546
547 std::shared_ptr<skills::detail::SkillRuntime> runtime;
548 {
549 std::shared_lock l(skillExecutionsMutex);
550 auto it = skillExecutions.find(executionId);
551 if (it == skillExecutions.end())
552 {
553 ARMARX_INFO << "No active execution for skill '" + executionId.skillId.toString() +
554 "' found! Ignoring abortSkill request.";
555 return false;
556 }
557 runtime = it->second;
558 }
559
560 runtime->stopSkill();
561 return true;
562 }
563
564 void
566 const skills::SkillStatusUpdate& statusUpdate)
567 {
568 // Snapshot the runtimes under the lock so we can call into them
569 // without holding the lock (sub-skill status updates can be slow).
570 std::vector<std::pair<skills::SkillExecutionID,
571 std::shared_ptr<skills::detail::SkillRuntime>>>
572 snapshot;
573 {
574 std::shared_lock l(skillExecutionsMutex);
575 snapshot.reserve(skillExecutions.size());
576 for (const auto& [id, runtime] : skillExecutions)
577 {
578 snapshot.emplace_back(id, runtime);
579 }
580 }
581 for (auto& [id, runtime] : snapshot)
582 {
583 ARMARX_DEBUG << "updating subskill status for " << id.toString() << " with "
584 << statusUpdate.executionId.toString();
585 runtime->updateSubSkillStatus(statusUpdate);
586 }
587 }
588
589 const skills::manager::dti::SkillManagerInterfacePrx&
591 {
592 return manager;
593 }
594
595 std::vector<std::shared_ptr<skills::detail::SkillRuntime>>
596 SkillProviderComponentPlugin::collectFinishedExecutions_locked()
597 {
598 // Caller MUST hold an exclusive lock on skillExecutionsMutex.
599 // We move terminated entries OUT of the map (under the lock) and
600 // return them, so the caller can join the threads outside the lock.
601 // The caller is responsible for joining; the SkillRuntime will be
602 // destroyed when its shared_ptr ref count drops to zero, which is
603 // safe only AFTER the embedded std::thread has been joined.
604 std::vector<std::shared_ptr<skills::detail::SkillRuntime>> ret;
605 for (auto it = skillExecutions.begin(); it != skillExecutions.end();)
606 {
607 const auto& runtime = it->second;
608 bool terminated = false;
609 {
610 std::scoped_lock statusLock(runtime->skillStatusesMutex);
611 terminated = runtime->statusUpdate.hasBeenTerminated();
612 }
613 if (terminated)
614 {
615 ret.push_back(std::move(it->second));
616 it = skillExecutions.erase(it);
617 }
618 else
619 {
620 ++it;
621 }
622 }
623 return ret;
624 }
625} // namespace armarx::plugins
626
627namespace armarx
628{
633
634 IceUtil::Optional<skills::provider::dto::SkillDescription>
636 const skills::provider::dto::SkillID& skillId,
637 const Ice::Current& /*unused*/)
638 {
639 auto id = skills::SkillID::FromIce(skillId, skills::ProviderID{.providerName = getName()});
640 auto o = plugin->getSkillDescription(id);
641 if (o.has_value())
642 {
643 return o->toProviderIce();
644 }
645 return {};
646 }
647
648 skills::provider::dto::SkillDescriptionMap
650 {
651 skills::provider::dto::SkillDescriptionMap ret;
652 for (const auto& [k, v] : plugin->getSkillDescriptions())
653 {
654 ret.insert({k.toProviderIce(), v.toProviderIce()});
655 }
656 return ret;
657 }
658
659 IceUtil::Optional<skills::provider::dto::SkillStatusUpdate>
661 const skills::provider::dto::SkillExecutionID& executionId,
662 const Ice::Current& /*unused*/)
663 {
665 executionId, skills::ProviderID{.providerName = getName()});
666 auto o = plugin->getSkillExecutionStatus(execId);
667 if (o.has_value())
668 {
669 return o->toProviderIce();
670 }
671 return {};
672 }
673
674 skills::provider::dto::SkillStatusUpdateMap
676 {
677 skills::provider::dto::SkillStatusUpdateMap ret;
678 for (const auto& [k, v] : plugin->getSkillExecutionStatuses())
679 {
680 ret.insert({k.toProviderIce(), v.toProviderIce()});
681 }
682 return ret;
683 }
684
685 // Please not that this method waits until the skill can be scheduled!
686 skills::provider::dto::SkillStatusUpdate
688 const skills::provider::dto::SkillExecutionRequest& info,
689 const Ice::Current& /*unused*/)
690 {
692 info, skills::ProviderID{.providerName = getName()});
693 auto up = this->plugin->executeSkill(exec);
694 return up.toProviderIce();
695 }
696
697 skills::provider::dto::SkillExecutionID
699 const skills::provider::dto::SkillExecutionRequest& info,
700 const Ice::Current& current /*unused*/)
701 {
703 info, skills::ProviderID{.providerName = getName()});
704 auto id = this->plugin->executeSkillAsync(exec);
705 return id.toProviderIce();
706 }
707
708 skills::provider::dto::ParameterUpdateResult
710 const skills::provider::dto::SkillExecutionID& id,
711 const aron::data::dto::DictPtr& input,
712 const Ice::Current& current /*unused*/)
713 {
714 skills::provider::dto::ParameterUpdateResult res;
715
716 auto exec =
719 res.success = this->plugin->updateSkillParameters(exec, prep);
720 return res;
721 }
722
723 skills::provider::dto::AbortSkillResult
724 SkillProviderComponentPluginUser::abortSkill(const skills::provider::dto::SkillExecutionID& id,
725 const Ice::Current& /*unused*/)
726 {
727 skills::provider::dto::AbortSkillResult res;
728 auto exec =
730 res.success = this->plugin->abortSkill(exec);
731 return res;
732 }
733
734 skills::provider::dto::AbortSkillResult
736 const skills::provider::dto::SkillExecutionID& id,
737 const Ice::Current& /*unused*/)
738 {
739 skills::provider::dto::AbortSkillResult res;
740 auto exec =
742 res.success = this->plugin->abortSkillAsync(exec);
743 return res;
744 }
745
746 void
748 const skills::provider::dto::SkillStatusUpdate& statusUpdate,
749 const std::string& providerName,
750 const Ice::Current& /*current*/)
751 {
752 auto status = skills::SkillStatusUpdate::FromIce(statusUpdate);
753 status.executionId.skillId.providerId.emplace().providerName = providerName;
754 plugin->updateSubSkillStatus(status);
755 }
756
759 {
760 return plugin;
761 }
762} // namespace armarx
static std::string levelToString(MessageTypeT type)
MessageTypeT getEffectiveLoggingLevel() const
Definition Logging.cpp:130
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 &current=Ice::Current()) override
skills::provider::dto::SkillStatusUpdateMap getSkillExecutionStatuses(const Ice::Current &current=Ice::Current()) override
skills::provider::dto::AbortSkillResult abortSkill(const skills::provider::dto::SkillExecutionID &skill, const Ice::Current &current=Ice::Current()) override
IceUtil::Optional< skills::provider::dto::SkillDescription > getSkillDescription(const skills::provider::dto::SkillID &skill, const Ice::Current &current=Ice::Current()) override
skills::provider::dto::SkillStatusUpdate executeSkill(const skills::provider::dto::SkillExecutionRequest &executionInfo, const Ice::Current &current=Ice::Current()) override
skills::provider::dto::SkillExecutionID executeSkillAsync(const skills::provider::dto::SkillExecutionRequest &executionInfo, const Ice::Current &current=Ice::Current()) override
skills::provider::dto::AbortSkillResult abortSkillAsync(const skills::provider::dto::SkillExecutionID &skill, const Ice::Current &current=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 &current) override
skills::provider::dto::ParameterUpdateResult updateSkillParameters(const skills::provider::dto::SkillExecutionID &executionId, const armarx::aron::data::dto::DictPtr &parameters, const Ice::Current &current=Ice::Current()) override
skills::provider::dto::SkillDescriptionMap getSkillDescriptions(const Ice::Current &current=Ice::Current()) override
static PointerType FromAronDictDTO(const data::dto::DictPtr &aron)
Definition Dict.cpp:131
static DateTime Now()
Definition DateTime.cpp:51
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
std::optional< skills::SkillDescription > getSkillDescription(const skills::SkillID &) const
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 &params)
std::map< skills::SkillID, skills::SkillDescription > getSkillDescriptions() const
void updateSubSkillStatus(const skills::SkillStatusUpdate &statusUpdate)
bool abortSkillAsync(const skills::SkillExecutionID &execId)
std::function< TerminatedSkillStatus()> FunctionType
Definition LambdaSkill.h:12
callback::dti::SkillProviderCallbackInterfacePrx callbackInterface
static SkillExecutionRequest FromIce(const manager::dto::SkillExecutionRequest &)
provider::dto::SkillExecutionRequest toProviderIce() const
std::string toString() const
Definition SkillID.cpp:68
std::optional< ProviderID > providerId
Definition SkillID.h:40
bool isFullySpecified() const
Definition SkillID.cpp:78
bool isSkillSpecified() const
Definition SkillID.cpp:84
static SkillID FromIce(const manager::dto::SkillID &)
Definition SkillID.cpp:36
#define ARMARX_CHECK(expression)
Shortcut for ARMARX_CHECK_EXPRESSION.
#define ARMARX_INFO
The normal logging level.
Definition Logging.h:179
#define ARMARX_ERROR
The logging level for unexpected behaviour, that must be fixed.
Definition Logging.h:194
#define ARMARX_DEBUG
The logging level for output that is only interesting while debugging.
Definition Logging.h:182
#define ARMARX_WARNING
The logging level for unexpected behaviour, but not a serious problem.
Definition Logging.h:191
#define ARMARX_VERBOSE
The logging level for verbose information.
Definition Logging.h:185
::IceInternal::Handle< Dict > DictPtr
std::shared_ptr< Dict > DictPtr
Definition Dict.h:42
This file is part of ArmarX.
SkillStatus toSkillStatus(const ActiveOrTerminatedSkillStatus &d)
This file offers overloads of toIce() and fromIce() functions for STL container types.
std::string GetHandledExceptionString()
IceUtil::Handle< class PropertyDefinitionContainer > PropertyDefinitionsPtr
PropertyDefinitions smart pointer type.
static SkillExecutionID FromIce(const skills::manager::dto::SkillExecutionID &)
static SkillStatusUpdate FromIce(const provider::dto::SkillStatusUpdate &update, const std::optional< skills::ProviderID > &providerId=std::nullopt)