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