Skill.cpp
Go to the documentation of this file.
1 #include "Skill.h"
2 
3 namespace armarx
4 {
5  namespace skills
6  {
8  description(desc)
9  {
10  // replace constructor if you want to have a specific logging tag
11  Logging::setTag("armarx::skills::" + description.skillName);
12  }
13 
14  // install a local condition via a lambda
15  void Skill::installConditionWithCallback(std::function<bool()>&& f, std::function<void()>&& cb)
16  {
17  std::lock_guard l(callbacksMutex);
18  callbacks.push_back({f, cb});
19  }
20 
21  bool Skill::isSkillAvailable(const InitInput &in) const
22  {
23  return this->isAvailable(in);
24  }
25 
26  bool Skill::isAvailable(const InitInput& in) const
27  {
28  (void) in;
29  return true;
30  }
31 
32  void Skill::resetSkill()
33  {
34  //ARMARX_IMPORTANT << "Resetting skill '" << description.skillName << "'";
35 
36  // resetting log times
39 
40  // resetting master running variable
41  running = false;
42 
43  // resetting conditional variables
44  stopped = false;
45  timeoutReached = false;
46 
47  this->reset();
48  }
49 
50  void Skill::waitForDependenciesOfSkill()
51  {
52  //ARMARX_IMPORTANT << "Waiting for dependencies of skill '" << description.skillName << "'";
53  this->waitForDependencies();
54  }
55 
56  void Skill::_init()
57  {
58  //ARMARX_IMPORTANT << "Initializing skill '" << description.skillName << "'";
59  callbacks.clear();
60  running = true;
62 
63  // install timeout condition
64  installConditionWithCallback(
65  [&](){ return (armarx::core::time::DateTime::Now() >= (started + description.timeout)); },
66  [&](){ notifyTimeoutReached(); }
67  );
68 
69  conditionCheckingThread = std::thread([&]()
70  {
71  armarx::core::time::Metronome metronome(conditionCheckingThreadFrequency);
72  while (running) // when the skill ends/aborts this variable will be set to false
73  {
74  {
75  std::scoped_lock l(callbacksMutex);
76  for (auto& p : callbacks)
77  {
78  auto& f = p.first;
79  auto& cb = p.second;
80  if (f())
81  {
82  cb();
83  }
84  }
85  }
86  const auto sleepDuration = metronome.waitForNextTick();
87  if (not sleepDuration.isPositive())
88  {
89  ARMARX_WARNING << deactivateSpam() << "PeriodicSkill: execution took too long (" << -sleepDuration << " vs " << conditionCheckingThreadFrequency.toCycleDuration() << ")";
90  }
91  }
92  });
93  }
94  Skill::InitResult Skill::initSkill(const InitInput& in)
95  {
96  this->_init();
97  return this->init(in);
98  }
99 
100  void Skill::_main()
101  {
102  // Nothing here yet...
103  }
104  Skill::MainResult Skill::mainOfSkill(const MainInput& in)
105  {
106  this->_main();
107  return this->main(in);
108  }
109 
110  void Skill::_exit()
111  {
112  // ARMARX_IMPORTANT << "Exiting Skill '" << description.skillName << "'";
113  running = false; // stop checking conditions
114 
115  if (conditionCheckingThread.joinable())
116  {
117  conditionCheckingThread.join();
118  }
120  }
121  Skill::ExitResult Skill::exitSkill(const ExitInput& in)
122  {
123  auto ret = this->exit(in);
124  this->_exit();
125  return ret;
126  }
127 
128  void Skill::notifyTimeoutReached()
129  {
130  timeoutReached = true;
131  onTimeoutReached();
132  }
133 
134  Skill::MainResult Skill::MakeAbortedResult(aron::data::DictPtr data)
135  {
136  return MainResult{
137  .status = TerminatedSkillStatus::Aborted,
138  .data = data,
139  };
140  }
141 
142  void Skill::notifySkillToStopASAP()
143  {
144  stopped = true;
145  onStopRequested();
146  }
147 
148  bool Skill::checkWhetherSkillShouldStopASAP() const
149  {
150  return stopped || timeoutReached;
151  }
152 
153  // condition effects
154  void Skill::onTimeoutReached()
155  {
156  }
157  void Skill::onStopRequested()
158  {
159  }
160 
161  // reset all local variables
162  void Skill::reset()
163  {
164  // Default nothing to reset
165  }
166 
167  // Wait if needed
168  void Skill::waitForDependencies()
169  {
170  // Default wait for nothing
171  }
172 
173  // always called before execute (should not take longer than 100ms)
174  Skill::InitResult Skill::init(const InitInput&)
175  {
176  // Default nothing to init
177  return {.status = TerminatedSkillStatus::Succeeded};
178  }
179 
180  // always called after execute or if skill fails (should not take longer than 100ms)
181  Skill::ExitResult Skill::exit(const ExitInput&)
182  {
183  // Default nothing to exit
184  return {.status = TerminatedSkillStatus::Succeeded};
185  }
186 
187  Skill::MainResult Skill::main(const MainInput& in)
188  {
189  // This is just a dummy implementation
190  ARMARX_IMPORTANT << "Dummy executing skill '" << description.skillName << "'. Please overwrite this method.";
191  return {.status = TerminatedSkillStatus::Succeeded, .data = nullptr};
192  }
193 
194  Skill::MainResult Skill::executeFullSkill(const MainInput& in)
195  {
196  this->resetSkill();
197  this->initSkill(InitInput{.executorName = in.executorName, .params = in.params});
198  auto ret = this->mainOfSkill(in);
199  this->exitSkill(ExitInput{.executorName = in.executorName, .params = in.params});
200  return ret;
201  }
202  }
203 }
armarx::aron::ret
ReaderT::InputType T & ret
Definition: rw.h:21
skills
This file is part of ArmarX.
armarx::skills::Skill::MainInput::executorName
std::string executorName
Definition: Skill.h:47
armarx::skills::Skill::MainInput
Definition: Skill.h:45
ARMARX_IMPORTANT
#define ARMARX_IMPORTANT
Definition: Logging.h:183
armarx::armem::mns::isAvailable
bool isAvailable(const Prx &proxy)
Definition: Registry.cpp:90
armarx::skills::SkillDescription
Definition: SkillDescription.h:16
armarx::skills::Skill::Skill
Skill()=delete
armarx::core::time::DateTime::Now
static DateTime Now()
Definition: DateTime.cpp:55
deactivateSpam
SpamFilterDataPtr deactivateSpam(SpamFilterDataPtr const &spamFilter, float deactivationDurationSec, const std::string &identifier, bool deactivate)
Definition: Logging.cpp:72
armarx::skills::Skill::ExitInput::executorName
std::string executorName
Definition: Skill.h:65
Skill.h
armarx::skills::Skill::ExitInput
Definition: Skill.h:63
armarx::skills::Skill::MainResult
Definition: Skill.h:52
armarx::skills::Skill::InitInput::executorName
std::string executorName
Definition: Skill.h:41
armarx::skills::Skill::ExitResult
Definition: Skill.h:58
armarx::core::time::Metronome::waitForNextTick
Duration waitForNextTick()
Wait and block until the target period is met.
Definition: Metronome.cpp:31
armarx::aron::data::DictPtr
std::shared_ptr< Dict > DictPtr
Definition: Dict.h:41
armarx::skills::Skill::MainResult::status
TerminatedSkillStatus status
Definition: Skill.h:54
armarx::core::time::Metronome
Simple rate limiter for use in loops to maintain a certain frequency given a clock.
Definition: Metronome.h:35
armarx::skills::Skill::InitResult
Definition: Skill.h:34
armarx::skills::Skill::MainInput::params
aron::data::DictPtr params
Definition: Skill.h:48
ARMARX_WARNING
#define ARMARX_WARNING
Definition: Logging.h:186
armarx::skills::Skill::InitInput
Definition: Skill.h:39
main
int main(int argc, char *argv[])
Definition: Admin.cpp:45
armarx::core::time::DateTime::Invalid
static DateTime Invalid()
Definition: DateTime.cpp:60
armarx
This file offers overloads of toIce() and fromIce() functions for STL container types.
Definition: ArmarXTimeserver.cpp:28