SkillImplementationWrapper.cpp
Go to the documentation of this file.
2 
4 
6 #include <RobotAPI/libraries/skills/core/aron/SkillErrorResult.aron.generated.h>
8 
9 namespace armarx
10 {
11  namespace skills::detail
12  {
14  const skills::SkillBlueprint* fac,
15  const skills::SkillExecutionID& execId,
16  const aron::data::DictPtr& initial_parameters,
17  const skills::callback::dti::SkillProviderCallbackInterfacePrx& callbackInterface) :
18  factory(fac), statusUpdate{{execId, initial_parameters, callbackInterface}}
19  {
20  }
21 
22  // ask a skill to stop
23  void
25  {
26  while (this->skill == nullptr)
27  {
29  << "Trying to stop a skill that has not been constructed yet... "
30  "Waiting until construction...";
31  std::this_thread::sleep_for(std::chrono::milliseconds(100));
32  }
33 
34  this->skill->notifySkillToStop();
35  }
36 
37  void
39  {
40  while (this->skill == nullptr)
41  {
43  << "Trying to add params to a skill that has not been constructed "
44  "yet... Waiting until construction...";
45  std::this_thread::sleep_for(std::chrono::milliseconds(100));
46  }
47 
48  this->skill->updateParameters(i);
49  }
50 
53  {
54  std::scoped_lock l(this->executionMutex);
55  // -------------------------------------------------------------------------------------
56  // sanity check
57  // -------------------------------------------------------------------------------------
58  ARMARX_CHECK(this->skill == nullptr)
59  << "A SKILL HAS ALREADY BEEN CONSTRUCTED. THIS SHOULD NOT HAPPEN!!";
60 
61 
62  // -------------------------------------------------------------------------------------
63  // setup basic vars and lambdas
64  // -------------------------------------------------------------------------------------
65  // actually we should lock... however this is only read access and the members are const throughout the execution...
67 
68  const auto& initial_aron_params = statusUpdate.parameters;
69  const auto& callback_interface = statusUpdate.callbackInterface;
70  const auto& skillId = statusUpdate.executionId.skillId;
71  const auto& skillName = skillId.skillName;
72  const auto& providerId = *skillId.providerId;
73  const auto& executorName = statusUpdate.executionId.executorName;
74  const auto& manager =
75  skills::manager::dti::SkillManagerInterfacePrx::checkedCast(callback_interface);
76 
77  ARMARX_INFO_S << "Executing skill: " << skillName;
78 
79  auto updateStatus =
80  [&](const SkillStatus status, const aron::data::DictPtr& data = nullptr)
81  {
82  std::unique_lock l(skillStatusesMutex);
84 
86  if (skill) // if skill has been constructed
87  {
88  // update parameterization
89  statusUpdate.parameters = skill->getParameters();
90  }
91 
92  if (callback_interface) // if callback interface is used
93  {
94  auto pid = providerId.toCallbackIce();
95  callback_interface->updateStatusForSkill(statusUpdate.toProviderIce(), pid);
96  }
97  };
98 
99  {
100  std::unique_lock l(skillStatusesMutex);
101 
102  // ---------------------------------------------------------------------------------
103  // check times
104  // ---------------------------------------------------------------------------------
108  {
109  ARMARX_WARNING_S << "SkillError 001: For some reason the skill '"
110  << skillId.toString()
111  << "' has been scheduled > 1s ago. The execution should start "
112  "much faster! Continue, but this is bad behavior..";
113  }
114  }
115 
116  // -------------------------------------------------------------------------------------
117  // construct skill
118  // -------------------------------------------------------------------------------------
119  ARMARX_INFO_S << "Construct skill: " << skillName;
120 
121  updateStatus(SkillStatus::Constructing);
122  ARMARX_CHECK_NOT_NULL(factory) << "Skill Factory is a nullptr";
123  this->skill = this->factory->createSkill(providerId);
124  this->skill->setExecutorName(executorName);
125  this->skill->setManager(manager);
126  this->skill->setCallback([&](const SkillStatus s, const armarx::aron::data::DictPtr& d)
127  { updateStatus(s, d); });
128 
129  // set initial parameters that were attached to the execution request (only add as we are not sure whether some updates already arrived)
130  this->updateSkillParameters(initial_aron_params);
131 
132  auto makeAbortedResult = [&](const std::string& errorCode,
133  const aron::data::DictPtr& data,
134  const std::string& message)
135  {
136  armarx::skills::arondto::SkillErrorResult errorResult;
137  errorResult.errorCode = errorCode;
138  errorResult.data = data;
139  errorResult.errorMessage = message;
140 
141  updateStatus(SkillStatus::Aborted, errorResult.toAron());
142 
143  std::unique_lock l(skillStatusesMutex);
144  auto terminated = TerminatedSkillStatusUpdate{
146  .parameters = statusUpdate.parameters,
147  .callbackInterface = statusUpdate.callbackInterface,
148  .result = statusUpdate.result}};
149  terminated.status = TerminatedSkillStatus::Aborted;
150  return terminated;
151  };
152 
153 
154  auto makeFailedResult = [&](const std::string& errorCode,
155  const aron::data::DictPtr& data,
156  const std::string& message)
157  {
158  armarx::skills::arondto::SkillErrorResult errorResult;
159  errorResult.errorCode = errorCode;
160  errorResult.data = data;
161  errorResult.errorMessage = message;
162 
163  updateStatus(SkillStatus::Failed, errorResult.toAron());
164 
165  std::unique_lock l(skillStatusesMutex);
166  auto terminated = TerminatedSkillStatusUpdate{
168  .parameters = statusUpdate.parameters,
169  .callbackInterface = statusUpdate.callbackInterface,
170  .result = statusUpdate.result}};
171  terminated.status = TerminatedSkillStatus::Failed;
172  return terminated;
173  };
174 
175  // -------------------------------------------------------------------------------------
176  // Check params
177  // -------------------------------------------------------------------------------------
178  // NOT RELEVANT ANYMORE!!
179  // if (skill->getSkillDescription().acceptedType && initial_aron_params &&
180  // not(initial_aron_params->fullfillsType(skill->getSkillDescription().acceptedType)))
181  // {
182  // std::string message =
183  // "SkillError 002: The Skill '" + skillName +
184  // "' has a type and got parameters but the input does not match the type.";
185  // ARMARX_ERROR_S << message;
186  // return makeTerminationResult(message);
187  // }
188 
189 
190  auto exitAndMakeFailedResult = [&](const std::string& errorCode,
191  const aron::data::DictPtr& data,
192  const std::string& message)
193  {
194  skill->exitSkill(); // try to exit skill. Ignore return value
195  return makeFailedResult(errorCode, data, message);
196  };
197  auto exitAndMakeAbortedResult = [&](const std::string& errorCode,
198  const aron::data::DictPtr& data,
199  const std::string& message)
200  {
201  skill->exitSkill(); // try to exit skill. Ignore return value
202  return makeAbortedResult(errorCode, data, message);
203  };
204 
205  // Construction succeeded!
206  // -------------------------------------------------------------------------------------
207  // Init skill
208  // -------------------------------------------------------------------------------------
209  ARMARX_INFO_S << "Init skill: " << skillName;
210  updateStatus(SkillStatus::Initializing);
211 
212  try
213  {
214  Skill::InitResult initRet = skill->initSkill();
216  {
217  std::string message = "SkillError 101: The initialization of skill '" +
218  skillName + "' did not succeed.";
219  return exitAndMakeFailedResult("101", nullptr, message);
220  }
221  }
222  catch (const error::SkillAbortedException& ex)
223  {
224  return exitAndMakeAbortedResult("101x", nullptr, GetHandledExceptionString());
225  }
226  catch (const error::SkillFailedException& ex)
227  {
228  return exitAndMakeFailedResult("101x", nullptr, GetHandledExceptionString());
229  }
230  catch (const std::exception& ex)
231  {
232  std::string message =
233  "SkillError 101e: An error occured during the initialization of skill '" +
234  skillName + "'. The error was: " + GetHandledExceptionString();
236  return exitAndMakeFailedResult("101e", nullptr, message);
237  }
238 
239  // Init succeeded!
240  // -------------------------------------------------------------------------------------
241  // Prepare skill
242  // -------------------------------------------------------------------------------------
243  ARMARX_INFO_S << "Prepare skill: " << skillName;
244  updateStatus(SkillStatus::Preparing);
245 
246  try
247  {
248  auto prepareRet = skill->prepareSkill();
249  while (prepareRet.status == ActiveOrTerminatedSkillStatus::Running)
250  {
251  ARMARX_INFO << deactivateSpam() << "Not all requirements for skill "
252  << skillName << " fulfilled. Waiting...";
253 
254  // wait...
255  std::this_thread::sleep_for(std::chrono::milliseconds(50));
256  prepareRet = skill->prepareSkill();
257  }
258 
259  if (prepareRet.status != ActiveOrTerminatedSkillStatus::Succeeded)
260  {
261  std::string message = "SkillError 201: The prepare method of skill '" +
262  skillName + "' did not succeed.";
264  return exitAndMakeFailedResult("201", nullptr, message);
265  }
266  }
267  catch (const error::SkillAbortedException& ex)
268  {
269  return exitAndMakeAbortedResult("201x", nullptr, GetHandledExceptionString());
270  }
271  catch (const error::SkillFailedException& ex)
272  {
273  return exitAndMakeFailedResult("201x", nullptr, GetHandledExceptionString());
274  }
275  catch (const std::exception& ex)
276  {
277  std::string message = "SkillError 201e: An error occured during waiting for skill "
278  "dependencies of skill '" +
279  skillName +
280  "'. The error was: " + GetHandledExceptionString();
282  return exitAndMakeFailedResult("201e", nullptr, message);
283  }
284 
285  // Prepare succeeded!
286  // -------------------------------------------------------------------------------------
287  // Main of skill
288  // -------------------------------------------------------------------------------------
289  // execute. If the skill fails for some reason, from this point it will always execute its exit function.
290  ARMARX_INFO_S << "Main skill: " << skillName;
291  updateStatus(SkillStatus::Running);
292 
293  Skill::MainResult mainRet;
294  try
295  {
296  mainRet = skill->mainOfSkill();
297  if (mainRet.status == TerminatedSkillStatus::Failed)
298  {
299  std::string message =
300  "SkillError 501: The main method of skill '" + skillName + "' did fail.";
301 
302  return exitAndMakeFailedResult("501", mainRet.data, message);
303  }
304  else if (mainRet.status == TerminatedSkillStatus::Aborted)
305  {
306  std::string message =
307  "SkillError 501: The main method of skill '" + skillName + "' got aborted.";
308  return exitAndMakeAbortedResult("501", mainRet.data, message);
309  }
310  }
311  catch (const error::SkillAbortedException& ex)
312  {
313  return exitAndMakeAbortedResult("501x", mainRet.data, GetHandledExceptionString());
314  }
315  catch (const error::SkillFailedException& ex)
316  {
317  return exitAndMakeFailedResult("501x", mainRet.data, GetHandledExceptionString());
318  }
319  catch (const std::exception& ex)
320  {
321  std::string message =
322  "SkillError 501e: An error occured during the main method of skill '" +
323  skillName + "'. The error was: " + GetHandledExceptionString();
325  return exitAndMakeFailedResult("501e", mainRet.data, message);
326  }
327 
328  // Main succeeded!
329  // -------------------------------------------------------------------------------------
330  // Exit of skill
331  // -------------------------------------------------------------------------------------
332  ARMARX_INFO_S << "Exit skill: " << skillName;
333  try
334  {
335  Skill::ExitResult exitRet = skill->exitSkill();
337  {
338  std::string message = "SkillError 601: The exit method of skill '" + skillName +
339  "' did not succeed.";
340  return makeFailedResult("601", mainRet.data, message);
341  }
342  }
343  catch (const error::SkillAbortedException& ex)
344  {
345  return makeAbortedResult("601x", mainRet.data, GetHandledExceptionString());
346  }
347  catch (const error::SkillFailedException& ex)
348  {
349  return makeFailedResult("601x", mainRet.data, GetHandledExceptionString());
350  }
351  catch (const std::exception& ex)
352  {
353  std::string message =
354  "SkillError 601e: An error occured during the exit method of skill '" +
355  skillName + "'. The error was: " + GetHandledExceptionString();
357  return makeFailedResult("601e", mainRet.data, message);
358  }
359 
360  // Exit succeeded!
361  // All succeeded!
362  {
363  updateStatus(SkillStatus::Succeeded, mainRet.data);
364 
365  // return result of main method
366  std::unique_lock l(skillStatusesMutex);
368  {.executionId = statusUpdate.executionId,
369  .parameters = statusUpdate.parameters,
370  .callbackInterface = statusUpdate.callbackInterface}};
371  ret.result = mainRet.data;
373  return ret;
374  }
375  }
376  } // namespace skills::detail
377 } // namespace armarx
armarx::skills::Skill::ExitResult::status
TerminatedSkillStatus status
Definition: Skill.h:48
armarx::skills::SkillExecutionID
Definition: SkillExecutionID.h:15
armarx::aron::ret
ReaderT::InputType T & ret
Definition: rw.h:13
armarx::skills::TerminatedSkillStatus::Succeeded
@ Succeeded
Exception.h
armarx::skills::SkillExecutionID::executorName
std::string executorName
Definition: SkillExecutionID.h:18
armarx::skills::TerminatedSkillStatus::Aborted
@ Aborted
armarx::skills::SkillStatus::Aborted
@ Aborted
LocalException.h
armarx::skills::ActiveOrTerminatedSkillStatus::Succeeded
@ Succeeded
armarx::skills::error::SkillAbortedException
Definition: Exception.h:53
armarx::skills::detail::SkillRuntime::statusUpdate
SkillStatusUpdate statusUpdate
Definition: SkillImplementationWrapper.h:29
armarx::skills::SkillID::skillName
std::string skillName
Definition: SkillID.h:41
armarx::core::time::DateTime::Now
static DateTime Now()
Definition: DateTime.cpp:51
ARMARX_CHECK_NOT_NULL
#define ARMARX_CHECK_NOT_NULL(ptr)
This macro evaluates whether ptr is not null and if it turns out to be false it will throw an Express...
Definition: ExpressionException.h:206
armarx::skills::SkillStatusUpdate::status
SkillStatus status
Definition: SkillStatusUpdate.h:118
armarx::skills::detail::SkillRuntime::skillStatusesMutex
std::mutex skillStatusesMutex
Definition: SkillImplementationWrapper.h:28
SkillImplementationWrapper.h
armarx::skills::SkillExecutionID::executionStartedTime
armarx::core::time::DateTime executionStartedTime
Definition: SkillExecutionID.h:19
armarx::skills::SkillStatusUpdateBase::callbackInterface
callback::dti::SkillProviderCallbackInterfacePrx callbackInterface
Definition: SkillStatusUpdate.h:63
message
message(STATUS "Boost-Library-Dir: " "${Boost_LIBRARY_DIRS}") message(STATUS "Boost-LIBRARIES
Definition: CMakeLists.txt:8
armarx::skills::SkillStatusUpdateBase::executionId
SkillExecutionID executionId
Definition: SkillStatusUpdate.h:61
Dict.h
armarx::skills::SkillStatusUpdateBase::result
aron::data::DictPtr result
Definition: SkillStatusUpdate.h:66
armarx::skills::error::SkillFailedException
Definition: Exception.h:61
ARMARX_CHECK
#define ARMARX_CHECK(expression)
Shortcut for ARMARX_CHECK_EXPRESSION.
Definition: ExpressionException.h:82
deactivateSpam
SpamFilterDataPtr deactivateSpam(SpamFilterDataPtr const &spamFilter, float deactivationDurationSec, const std::string &identifier, bool deactivate)
Definition: Logging.cpp:75
armarx::skills::detail::SkillRuntime::executeSkill
TerminatedSkillStatusUpdate executeSkill()
Definition: SkillImplementationWrapper.cpp:52
armarx::GetHandledExceptionString
std::string GetHandledExceptionString()
Definition: Exception.cpp:165
armarx::status
status
Definition: FiniteStateMachine.h:244
armarx::core::time::Duration::Seconds
static Duration Seconds(std::int64_t seconds)
Constructs a duration in seconds.
Definition: Duration.cpp:72
armarx::skills::SkillStatusUpdate::toProviderIce
provider::dto::SkillStatusUpdate toProviderIce() const
Definition: SkillStatusUpdate.cpp:297
armarx::skills::detail::SkillRuntime::updateSkillParameters
void updateSkillParameters(const aron::data::DictPtr &i)
Definition: SkillImplementationWrapper.cpp:38
ARMARX_ERROR_S
#define ARMARX_ERROR_S
Definition: Logging.h:216
data
uint8_t data[1]
Definition: EtherCATFrame.h:68
armarx::skills::SkillStatus::Preparing
@ Preparing
armarx::skills::detail::SkillRuntime::stopSkill
void stopSkill()
Definition: SkillImplementationWrapper.cpp:24
armarx::skills::Skill::MainResult
A result struct for th main method of a skill.
Definition: Skill.h:39
ARMARX_WARNING_S
#define ARMARX_WARNING_S
Definition: Logging.h:213
armarx::skills::ActiveOrTerminatedSkillStatus::Running
@ Running
armarx::skills::Skill::ExitResult
A result struct for skill exit function.
Definition: Skill.h:46
armarx::skills::TerminatedSkillStatusUpdate
Definition: SkillStatusUpdate.h:74
armarx::aron::data::DictPtr
std::shared_ptr< Dict > DictPtr
Definition: Dict.h:41
armarx::skills::Skill::MainResult::status
TerminatedSkillStatus status
Definition: Skill.h:41
armarx::skills::SkillStatus::Initializing
@ Initializing
armarx::skills::TerminatedSkillStatus::Failed
@ Failed
armarx::skills::SkillBlueprint
Definition: SkillFactory.h:11
ARMARX_INFO
#define ARMARX_INFO
Definition: Logging.h:181
armarx::skills::Skill::InitResult::status
TerminatedSkillStatus status
Definition: Skill.h:29
armarx::skills::SkillStatusUpdateBase::parameters
aron::data::DictPtr parameters
Definition: SkillStatusUpdate.h:62
armarx::skills::SkillExecutionID::skillId
SkillID skillId
Definition: SkillExecutionID.h:17
armarx::skills::Skill::MainResult::data
aron::data::DictPtr data
Definition: Skill.h:42
armarx::skills::Skill::InitResult
A result struct for skill initialization.
Definition: Skill.h:27
armarx::skills::SkillStatus::Running
@ Running
ARMARX_INFO_S
#define ARMARX_INFO_S
Definition: Logging.h:202
armarx::skills::SkillStatus::Constructing
@ Constructing
armarx::skills::SkillID::isFullySpecified
bool isFullySpecified() const
Definition: SkillID.cpp:78
armarx::ctrlutil::s
double s(double t, double s0, double v0, double a0, double j)
Definition: CtrlUtil.h:33
armarx::skills::detail::SkillRuntime::SkillRuntime
SkillRuntime(const skills::SkillBlueprint *fac, const skills::SkillExecutionID &, const aron::data::DictPtr &, const skills::callback::dti::SkillProviderCallbackInterfacePrx &)
Definition: SkillImplementationWrapper.cpp:13
armarx
This file offers overloads of toIce() and fromIce() functions for STL container types.
Definition: ArmarXTimeserver.cpp:27
armarx::skills::SkillStatus
SkillStatus
Definition: SkillStatusUpdate.h:15
armarx::skills::SkillStatus::Succeeded
@ Succeeded
armarx::skills::SkillStatus::Failed
@ Failed