SkillManagerWrapper.cpp
Go to the documentation of this file.
1 #include "SkillManagerWrapper.h"
2 
3 #include <mutex>
4 #include <optional>
5 
6 #include <SimoxUtility/algorithm/string/string_tools.h>
7 
9 
11 
12 namespace armarx::skills::gui
13 {
14  using StatusMap = std::map<skills::SkillExecutionID, skills::SkillStatusUpdate>;
15  using SkillMap =
16  std::map<skills::ProviderID, std::map<skills::SkillID, skills::SkillDescription>>;
17 
18  StatusMap
19  SkillManagerWrapper::fetchExecutionsFromMemory()
20  {
21  if (!memory)
22  {
23  // check if null
24  return {};
25  }
26 
27  try
28  {
29  std::scoped_lock l(mutex_memory);
30 
31  // we return this map
32  StatusMap statusMap;
33 
34  auto currentManagerStatuses =
35  memory->ice_invocationTimeout(10000)->getSkillExecutionStatuses();
36 
37  // iterate over raw data and convert to common types
38  for (const auto& [k, v] : currentManagerStatuses)
39  {
40  auto executionId = skills::SkillExecutionID::FromIce(k);
41  auto statusUpdate = skills::SkillStatusUpdate::FromIce(v);
42 
43  // update maps
44  statusMap[executionId] = statusUpdate;
45  }
46  return statusMap;
47  }
48  catch (Ice::Exception const& e)
49  {
51  << "Unhandled Ice exception encountered while updating executions. Exception was: "
52  << e;
53  emit connectionUpdate("Could not fetch executions", e.what());
54  emit disableAutoUpdate();
55  return {};
56  }
57  catch (...)
58  {
59  ARMARX_WARNING << "Unknown exception encountered while updating executions.";
60  return {};
61  }
62  }
63 
64  // check if search strings occur in the skill name in order
65  bool
66  matches(std::string skillName, std::vector<std::string>& searches)
67  {
68  size_t index = 0;
69  for (std::string& substring : searches)
70  {
71  size_t occurance = skillName.find(substring, index);
72  if (occurance == std::string::npos)
73  {
74  return false;
75  }
76 
77 
78  // we found an occurance
79  index = occurance;
80  }
81  return true;
82  }
83 
84  SkillManagerWrapper::Snapshot
85  SkillManagerWrapper::filterUpdate(Snapshot update)
86  {
87  // empty search => do not filter
88  if (this->currentSkillSearch.empty())
89  {
90  return update;
91  }
92 
93  Snapshot filtered;
94 
95  // for now we don't change the executions
96  filtered.statuses = update.statuses;
97 
98  std::vector<std::string> substrings;
99 
100  {
101  std::vector<std::string> rawSubstrings = simox::alg::split(currentSkillSearch);
102  for (auto& string : rawSubstrings)
103  {
104  substrings.push_back(simox::alg::to_lower(string));
105  }
106  }
107 
108 
109  for (auto& provider_and_descrMap : update.skills)
110  {
111  using DescriptionMap = std::map<skills::SkillID, skills::SkillDescription>;
112 
113  DescriptionMap& descriptionMap = provider_and_descrMap.second;
114  skills::ProviderID provider = provider_and_descrMap.first;
115 
116  for (auto& skill_and_description : descriptionMap)
117  {
118  skills::SkillID sid = skill_and_description.first;
119  skills::SkillDescription descr = skill_and_description.second;
120 
121  if (matches(simox::alg::to_lower(sid.skillName), substrings))
122  {
123  // add to map
124  filtered.skills[provider][sid] = descr;
125  }
126  }
127  }
128 
129  return filtered;
130  }
131 
132  SkillMap
133  SkillManagerWrapper::fetchSkillsFromMemory()
134  {
135  if (!memory)
136  {
137  return {};
138  }
139 
140  try
141  {
142  std::scoped_lock l(mutex_memory);
143 
145 
146  auto managerSkills = memory->ice_invocationTimeout(5000)->getSkillDescriptions();
147 
148  for (const auto& [sid, desc] : managerSkills)
149  {
150  auto description = skills::SkillDescription::FromIce(desc);
151  auto skillId = skills::SkillID::FromIce(sid);
152  auto providerId = skillId.providerId.value_or(
153  skills::ProviderID{.providerName = "UNKNOWN PROVIDER NAME"});
154 
155  ARMARX_CHECK(skillId.isFullySpecified());
156 
157  auto& providedSkillsMap = skills[providerId]; // create new if not existing
158  providedSkillsMap.insert({skillId, description});
159  }
160 
161  return skills;
162  }
163  catch (Ice::Exception const& e)
164  {
166  << "Unhandled Ice exception encountered while updating skills. Exception was: "
167  << e;
168  emit connectionUpdate("Could not fetch skills", e.what());
169  emit disableAutoUpdate();
170  return {};
171  }
172  catch (...)
173  {
174  ARMARX_WARNING << "Unknown exception encountered while updating skills.";
175  return {};
176  }
177  }
178 
179  void
181  skills::manager::dti::SkillManagerInterfacePrx const& updatedMemory)
182  {
183  std::scoped_lock l(mutex_memory);
184  this->memory = updatedMemory;
185  }
186 
187  void
189  {
190  // clear memory
191 
192  std::scoped_lock l(mutex_memory);
193  this->memory = nullptr;
194  }
195 
196  void
197  SkillManagerWrapper::acceptSearchRequest(std::string const& search)
198  {
199  this->currentSkillSearch = search;
200  emit searchAccepted();
201  }
202 
203  void
205  {
206  ARMARX_IMPORTANT << "Stopping all running executions.";
207 
208  StatusMap executions;
209 
210  // we ALWAYS want the newest information when stopping all!
211  // e.g. there is some new skill not known to the GUI which we explicitely want to stop too.
212  // the stop-all function is often used in an emergency, so we'll live with the extra call...
213  try
214  {
215  executions = this->fetchExecutionsFromMemory();
216  }
217  catch (...) // if any error occurs, we use the snapshot as backup. better to miss a skill
218  // than to not do anything.
219  {
220  executions = this->getExecutions();
221  }
222 
223  for (auto& [executionId, status] : executions)
224  {
225  // select all running executions...
226  if (!status.hasBeenTerminated())
227  {
228  // ... and kill them.
229  this->stopExecution(executionId, 3);
230  }
231  }
232  }
233 
234  void
236  {
237  std::scoped_lock l(mutex_snapshot);
238 
239  snapshot.skills = fetchSkillsFromMemory();
240  snapshot.statuses = fetchExecutionsFromMemory();
241 
242  // notify registered widgets of update
243  emit updateAvailable(filterUpdate(snapshot));
244  }
245 
246  std::vector<Parameters>
248  {
249  if (this->skillParameterExecutionHistory.find(sid) ==
250  this->skillParameterExecutionHistory.end())
251  {
252  return {};
253  }
254  return this->skillParameterExecutionHistory[sid];
255  }
256 
257  void
259  const Parameters& params)
260  {
261  if (this->skillParameterExecutionHistory.find(sid) ==
262  this->skillParameterExecutionHistory.end())
263  {
264  // no history exists for this skill. Assign new
265  this->skillParameterExecutionHistory.insert({sid, {params}});
266  }
267  else
268  {
269  // history already exists. Append to list
270  this->skillParameterExecutionHistory[sid].emplace_back(params);
271  }
272  }
273 
274  std::optional<Parameters>
276  {
277  auto parameterList = getParameterHistoryForSkill(sid);
278  if (parameterList.empty())
279  {
280  return std::nullopt;
281  }
282  return parameterList.back();
283  }
284 
285  const std::optional<ProviderID>
287  {
288  // check if id already contains a provider. If so, this function should not have been called!
289  if (skillId.isProviderSpecified())
290  {
291  ARMARX_WARNING << "The memory snapshot was searched for any provider, when a provider "
292  "was specified.";
293  // we continue, but this might result in unexpected behaviour...
294  }
295 
296  for (auto& [prov, skillMap] : map)
297  {
298  for (auto& [skill, desc] : skillMap)
299  {
300  if (skill == skillId)
301  {
302  return prov;
303  }
304  }
305  }
306  return std::nullopt;
307  }
308 
309  SkillMap
311  {
312  std::scoped_lock l(mutex_snapshot);
313 
314  Snapshot filtered = filterUpdate(snapshot);
315 
316  return filtered.skills;
317  }
318 
319  SkillMap
321  {
322  std::scoped_lock l(mutex_snapshot);
323 
324  return snapshot.skills;
325  }
326 
327  StatusMap
329  {
330  std::scoped_lock l(mutex_snapshot);
331  return snapshot.statuses;
332  }
333 
334  void
336  const unsigned int max_retries)
337  {
338  // memory???
339  if (!memory)
340  {
341  return;
342  }
343 
344  unsigned int retries = max_retries;
345  bool retry = false;
346 
347  do
348  {
349  try
350  {
351  ARMARX_INFO << "Aborting skill '" << executionId.skillId.skillName << "'...";
352  std::scoped_lock l(mutex_memory);
353  this->memory->ice_invocationTimeout(5000)->abortSkillAsync(
354  executionId.toManagerIce());
355  }
356  catch (Ice::Exception const& e)
357  {
358  retry = true;
359  ARMARX_ERROR << "Unhandeled Ice exception while aborting skill '"
360  << executionId.skillId.skillName << "'.";
361  emit connectionUpdate("Could not abort skill " + executionId.skillId.skillName,
362  e.what());
363  }
364  catch (...)
365  {
366  retry = true;
367  ARMARX_ERROR << "Unhandled error while aborting skill '"
368  << executionId.skillId.skillName << "'.";
369  }
370 
371  if (retry)
372  {
373  retries -= 1;
374 
375  if (retries > 0)
376  {
377  ARMARX_WARNING << "There where errors aborting skills. Retrying...";
378  }
379  else
380  {
381  ARMARX_ERROR << "Couldn't abort all skills after " << max_retries
382  << " tries. Giving up.";
383  retry = false;
384  }
385  }
386  } while (retry);
387  }
388 
389  void
391  aron::data::DictPtr const params)
392  {
393  // Memory???
394  if (!memory)
395  {
396  return;
397  }
398 
399  auto providerId = skillId.providerId;
400  if (!providerId.has_value())
401  {
402  ARMARX_IMPORTANT << "The skill: '" << skillId.skillName
403  << "' has been requested to be executed, but no provider was "
404  "given. Aborting...";
405  return;
406  }
407 
408  std::map<skills::SkillID, skills::SkillDescription> skillDescriptions;
409  if (this->UPDATE_ON_EXECUTION_REQUEST)
410  {
411  skillDescriptions = this->fetchSkillsFromMemory().at(providerId.value());
412  }
413  else
414  {
415  skillDescriptions = this->getSkills().at(providerId.value());
416  }
417 
418  if (skillDescriptions.find(skillId) == skillDescriptions.end())
419  {
420  ARMARX_IMPORTANT << "The Skill: '" << skillId.skillName
421  << "' has been requested to be executed, but no skill description was "
422  "found. Aborting...";
423  return;
424  }
425 
426  char hostname[HOST_NAME_MAX];
427  gethostname(hostname, HOST_NAME_MAX);
428 
430  .skillId = skillId,
431  .executorName = "Skills.Manager GUI (hostname: " + std::string(hostname) + ")",
432  .parameters = params};
433 
434  ARMARX_CHECK(skillId.isFullySpecified()); // sanity check
435 
436  ARMARX_IMPORTANT << "Executing skill from GUI: " << skillId << ".";
437 
438  try
439  {
440  std::scoped_lock l(mutex_memory);
441  memory->ice_invocationTimeout(5000)->executeSkillAsync(req.toManagerIce());
442  }
443  catch (Ice::Exception const& e)
444  {
445  ARMARX_ERROR << "Unhandeled Ice exception while executing skill '" << skillId.skillName
446  << "'. Aborting...";
447  emit connectionUpdate("Execution failed of skill " + skillId.skillName, e.what());
448  }
449  catch (...)
450  {
451  ARMARX_ERROR << "Unhandled error while executing skill '" << skillId.skillName
452  << "'. Aborting...";
453  }
454  }
455 
456 
457 } // namespace armarx::skills::gui
armarx::skills::SkillExecutionID
Definition: SkillExecutionID.h:15
skills
This file is part of ArmarX.
armarx::skills::gui::SkillManagerWrapper::startExecutionWithParams
void startExecutionWithParams(skills::SkillID &skillId, aron::data::DictPtr const params)
Attempts to start an execution with given parameters.
Definition: SkillManagerWrapper.cpp:390
armarx::skills::gui::SkillManagerWrapper::updateAvailable
void updateAvailable(Snapshot update)
ARMARX_IMPORTANT
#define ARMARX_IMPORTANT
Definition: Logging.h:190
armarx::skills::SkillStatusUpdate::FromIce
static SkillStatusUpdate FromIce(const provider::dto::SkillStatusUpdate &update, const std::optional< skills::ProviderID > &providerId=std::nullopt)
Definition: SkillStatusUpdate.cpp:369
armarx::skills::gui::SkillManagerWrapper::updateFromMemory
void updateFromMemory()
Requests this wrapper to overwrite its own state from memory.
Definition: SkillManagerWrapper.cpp:235
armarx::skills::SkillExecutionRequest::skillId
skills::SkillID skillId
Definition: SkillExecutionRequest.h:25
index
uint8_t index
Definition: EtherCATFrame.h:59
armarx::skills::gui::StatusMap
std::map< skills::SkillExecutionID, skills::SkillStatusUpdate > StatusMap
Definition: SkillExecutionTreeWidget.h:12
armarx::skills::SkillID::skillName
std::string skillName
Definition: SkillID.h:41
armarx::skills::gui::SkillManagerWrapper::disconnectMemory
void disconnectMemory()
Disconnects the interface from memory.
Definition: SkillManagerWrapper.cpp:188
armarx::skills::gui::SkillManagerWrapper::connectionUpdate
void connectionUpdate(std::string const &message, std::string const &error)
armarx::skills::SkillID::providerId
std::optional< ProviderID > providerId
Definition: SkillID.h:40
armarx::skills::gui::SkillManagerWrapper::getLatestParametersForSkill
std::optional< Parameters > getLatestParametersForSkill(const skills::SkillID &sid)
Definition: SkillManagerWrapper.cpp:275
armarx::skills::gui::SkillManagerWrapper::searchAccepted
void searchAccepted()
armarx::skills::gui::Parameters
aron::data::DictPtr Parameters
Definition: SkillManagerWrapper.h:21
armarx::memory
Brief description of class memory.
Definition: memory.h:38
ARMARX_CHECK
#define ARMARX_CHECK(expression)
Shortcut for ARMARX_CHECK_EXPRESSION.
Definition: ExpressionException.h:82
armarx::skills::gui::SkillManagerWrapper::findFirstProvider
static const std::optional< skills::ProviderID > findFirstProvider(SkillMap const &map, SkillID const &skillId)
Definition: SkillManagerWrapper.cpp:286
armarx::skills::SkillID::isProviderSpecified
bool isProviderSpecified() const
Definition: SkillID.cpp:90
armarx::skills::SkillExecutionID::toManagerIce
skills::manager::dto::SkillExecutionID toManagerIce() const
Definition: SkillExecutionID.cpp:11
SkillManagerWrapper.h
armarx::skills::gui::SkillManagerWrapper::getExecutions
StatusMap getExecutions()
Returns the latest status snapshot.
Definition: SkillManagerWrapper.cpp:328
armarx::skills::SkillExecutionRequest
Definition: SkillExecutionRequest.h:13
armarx::skills::gui::SkillManagerWrapper::addParametersToHistory
void addParametersToHistory(const skills::SkillID &sid, const Parameters &params)
Definition: SkillManagerWrapper.cpp:258
armarx::skills::gui::SkillManagerWrapper::Snapshot
Definition: SkillManagerWrapper.h:82
armarx::status
status
Definition: FiniteStateMachine.h:244
armarx::skills::gui::SkillManagerWrapper::Snapshot::skills
SkillMap skills
Definition: SkillManagerWrapper.h:85
armarx::skills::gui::SkillMap
std::map< skills::ProviderID, std::map< skills::SkillID, skills::SkillDescription > > SkillMap
Definition: SkillManagerWrapper.cpp:16
armarx::skills::gui::SkillManagerWrapper::getSkillsFiltered
SkillMap getSkillsFiltered()
Returns the latest skills snapshot.
Definition: SkillManagerWrapper.cpp:310
armarx::skills::SkillID::FromIce
static SkillID FromIce(const manager::dto::SkillID &)
Definition: SkillID.cpp:36
armarx::skills::gui
Definition: PeriodicUpdateWidget.cpp:11
ARMARX_ERROR
#define ARMARX_ERROR
Definition: Logging.h:196
SkillExecutionRequest.h
armarx::armem::server::ltm::util::mongodb::detail::update
bool update(mongocxx::collection &coll, const nlohmann::json &query, const nlohmann::json &update)
Definition: mongodb.cpp:68
armarx::aron::data::DictPtr
std::shared_ptr< Dict > DictPtr
Definition: Dict.h:41
armarx::ctrlutil::v
double v(double t, double v0, double a0, double j)
Definition: CtrlUtil.h:39
ARMARX_INFO
#define ARMARX_INFO
Definition: Logging.h:181
armarx::skills::gui::matches
bool matches(std::string skillName, std::vector< std::string > &searches)
Definition: SkillManagerWrapper.cpp:66
armarx::skills::SkillExecutionID::skillId
SkillID skillId
Definition: SkillExecutionID.h:17
armarx::skills::SkillExecutionID::FromIce
static SkillExecutionID FromIce(const skills::manager::dto::SkillExecutionID &)
Definition: SkillExecutionID.cpp:31
armarx::skills::gui::SkillManagerWrapper::Snapshot::statuses
StatusMap statuses
Definition: SkillManagerWrapper.h:84
Logging.h
armarx::skills::gui::SkillManagerWrapper::disableAutoUpdate
void disableAutoUpdate()
ARMARX_WARNING
#define ARMARX_WARNING
Definition: Logging.h:193
armarx::skills::gui::SkillManagerWrapper::stopAllExecutions
void stopAllExecutions()
Stops all available (and running) executions.
Definition: SkillManagerWrapper.cpp:204
armarx::skills::SkillDescription::FromIce
static SkillDescription FromIce(const provider::dto::SkillDescription &i, const std::optional< ProviderID > &=std::nullopt)
Definition: SkillDescription.cpp:39
armarx::skills::gui::SkillManagerWrapper::getParameterHistoryForSkill
std::vector< Parameters > getParameterHistoryForSkill(const skills::SkillID &sid)
Definition: SkillManagerWrapper.cpp:247
armarx::skills::SkillID
Definition: SkillID.h:14
armarx::skills::SkillID::isFullySpecified
bool isFullySpecified() const
Definition: SkillID.cpp:78
armarx::skills::gui::SkillManagerWrapper::getSkills
SkillMap getSkills()
Returns the latest skills snapshot.
Definition: SkillManagerWrapper.cpp:320
armarx::skills::gui::SkillManagerWrapper::acceptSearchRequest
void acceptSearchRequest(std::string const &search)
Applies the search word to the update filter.
Definition: SkillManagerWrapper.cpp:197
armarx::skills::gui::SkillManagerWrapper::connectMemory
void connectMemory(skills::manager::dti::SkillManagerInterfacePrx const &updatedMemory)
Updates the memory pointer.
Definition: SkillManagerWrapper.cpp:180
armarx::split
std::vector< std::string > split(const std::string &source, const std::string &splitBy, bool trimElements=false, bool removeEmptyElements=false)
Definition: StringHelpers.cpp:38
armarx::skills::gui::SkillManagerWrapper::stopExecution
void stopExecution(skills::SkillExecutionID const &executionId, const unsigned int max_retries=0)
Attempts to stop an execution.
Definition: SkillManagerWrapper.cpp:335