StateWatcher.cpp
Go to the documentation of this file.
1 /*
2  * This file is part of ArmarX.
3  *
4  * Copyright (C) 2011-2016, High Performance Humanoid Technologies (H2T), Karlsruhe Institute of Technology (KIT), all rights reserved.
5  *
6  * ArmarX is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License version 2 as
8  * published by the Free Software Foundation.
9  *
10  * ArmarX is distributed in the hope that it will be useful, but
11  * WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13  * GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with this program. If not, see <http://www.gnu.org/licenses/>.
17  *
18  * @package
19  * @author
20  * @date
21  * @copyright http://www.gnu.org/licenses/gpl-2.0.txt
22  * GNU General Public License
23  */
24 #include "StateWatcher.h"
25 
26 #include <iterator>
27 
28 #include <ArmarXCore/core/services/profiler/Profiler.h> // for ProfilerPtr
34 
35 #include "view/TransitionItem.h"
36 
37 namespace armarx
38 {
40  {
41  }
42 
43  void
45  {
46  usingTopic("StateReportingTopic");
47  }
48 
49  void
51  {
52 
53  qRegisterMetaType<statechartmodel::TransitionCPtr>("TransitionCPtr");
54  qRegisterMetaType<statechartmodel::StateInstancePtr>("StateInstancePtr");
57  subscriptionTask->start();
58  }
59 
60  void
62  {
63  subscriptionTask->stop();
64  try
65  {
66  clear();
67  }
68  catch (...)
69  {
70  }
71  }
72 
73  void
75  {
76  SubscriptionMap tempList;
77  {
78  std::unique_lock lock(mapMutex);
79  tempList.swap(subscriptionQueue);
80  }
81  ARMARX_DEBUG << tempList.size() << " new subscriptions received";
82  for (auto& elem : tempList)
83  {
84  StateIceBasePtr iceState = elem.first;
85  statechartmodel::StatePtr state = elem.second.first;
86  StateItem* stateItem = elem.second.second;
87  StateListenerDataMap::iterator it;
88  {
89  std::unique_lock lock(mapMutex);
90  it = stateMap.find(iceState->globalStateIdentifier);
91  if (it != stateMap.end() && state && it->second.states.count(state) > 0)
92  {
93  continue;
94  }
95  if (it != stateMap.end() && stateItem && it->second.stateItems.count(stateItem) > 0)
96  {
97  continue;
98  }
99  }
100  ARMARX_VERBOSE << "subscribing : " << iceState->globalStateIdentifier;
101  try
102  {
103 
105  if (it != stateMap.end())
106  {
107  data = it->second;
108  }
109  data.iceState = iceState;
110  if (state)
111  {
112  data.states.insert(state);
113  }
114  if (stateItem)
115  {
116  data.stateItems.insert(stateItem);
117  }
118 
119  std::unique_lock lock(mapMutex);
120  stateMap[iceState->globalStateIdentifier] = data;
121  // ARMARX_IMPORTANT << "subscribed to " << iceState->globalStateIdentifier;
122  }
123  catch (...)
124  {
126  }
127  }
128  }
129 
130  bool
132  {
133  std::unique_lock lock(mapMutex);
134  if (!iceState)
135  {
136  ARMARX_WARNING << "Ice State NULL";
137  return false;
138  }
139  if (!state)
140  {
141  ARMARX_WARNING << "State NULL: " << iceState->globalStateIdentifier;
142  return false;
143  }
144  StateItem* item = nullptr;
145  subscriptionQueue.push_back(std::make_pair(iceState, std::make_pair(state, item)));
146  return true;
147  }
148 
149  bool
151  {
152  std::unique_lock lock(mapMutex);
153  for (auto& pair : stateMap)
154  {
155  for (auto item : pair.second.stateItems)
156  {
157  if (item == state)
158  {
159  pair.second.stateItems.erase(state);
160  return true;
161  }
162  }
163  }
164  return false;
165  }
166 
167  bool
168  StateWatcher::subscribeToState(StateIceBasePtr iceState, StateItem* state)
169  {
170  std::unique_lock lock(mapMutex);
171  if (!iceState)
172  {
173  ARMARX_WARNING << "Ice State NULL";
174  return false;
175  }
176  if (!state)
177  {
178  ARMARX_WARNING << "State NULL: " << iceState->globalStateIdentifier;
179  return false;
180  }
181  subscriptionQueue.push_back(
182  std::make_pair(iceState, std::make_pair(statechartmodel::StatePtr(), state)));
183  return true;
184  }
185 
186  VariantPtr
188  const std::string paramMapType) const
189  {
190  std::unique_lock lock(mapMutex);
191  try
192  {
193  for (const auto& stateData : stateMap)
194  {
195  if (stateData.second.states.count(state))
196  {
197  // ARMARX_INFO << "Checking: " << "Found";
198  StringValueMap map(false);
199  for (auto& entry : stateData.second.parameters.at(paramMapType))
200  {
201  map.addElement(entry.first, entry.second->value);
202  }
203  return new Variant(map);
204  }
205  }
206  }
207  catch (...)
208  {
210  }
211 
212  return VariantPtr();
213  }
214 
217  const std::string paramMapType) const
218  {
219  std::unique_lock lock(mapMutex);
220  // try
221  {
222  for (const auto& stateData : stateMap)
223  {
224  if (stateData.second.states.count(state))
225  {
226  // ARMARX_INFO << "Checking: " << "Found";
227  ARMARX_INFO << "query state: "
228  << stateData.second.iceState->globalStateIdentifier;
229 
230  auto it = stateData.second.parameters.find(paramMapType);
231  if (it == stateData.second.parameters.end())
232  {
233  std::stringstream s;
234  for (auto& e : stateData.second.parameters)
235  {
236  s << e.first << ", ";
237  }
238  throw LocalException()
239  << "could not find " << paramMapType << " available: " << s.str();
240  }
241  return it->second;
242  }
243  }
244  }
245  // catch (...)
246  // {
247  // handleExceptions();
248  // }
249 
250  return StateParameterMap();
251  }
252 
253  void
255  {
256  std::unique_lock lock(mapMutex);
257 
258  stateMap.clear();
259  }
260 
261  std::string
262  StateWatcher::ExtractStateName(const std::string globalIdString)
263  {
264  if (globalIdString.find("->") == std::string::npos)
265  {
266  return globalIdString;
267  }
268  return globalIdString.substr(globalIdString.find_last_of("->") + 1);
269  }
270 
271  std::string
273  {
274  return "StateWatcher";
275  }
276 
277  void
279  const std::string&,
280  Ice::Int,
281  Ice::Int,
282  const Ice::Current&)
283  {
284  }
285 
286  void
287  StateWatcher::reportEvent(const ProfilerEvent& event, const Ice::Current&)
288  {
289  try
290  {
291  std::string stateIdentifier = event.parentName;
292  if (event.functionName !=
294  {
295  std::unique_lock lock(mapMutex);
296  auto it = stateMap.find(stateIdentifier);
297  if (it == stateMap.end())
298  {
299  ARMARX_VERBOSE << "Could not find state with id " << stateIdentifier;
300  return;
301  }
302  const StateListenerData& data = it->second;
303  for (auto& state : data.states)
304  {
305  if (state)
306  {
307  QMetaObject::invokeMethod(state.get(),
308  "setActiveSubstate",
311  // auto subState = state->getActiveSubstate();
312  // if (subState)
313  // {
314  // QMetaObject::invokeMethod(subState.get(), "setActive", Q_ARG(bool, false));
315  // }
316  }
317  }
318  }
319  }
320  catch (...)
321  {
323  }
324  }
325 
326  void
327  StateWatcher::reportStatechartTransition(const ProfilerStatechartTransition& event,
328  const Ice::Current&)
329  {
330  try
331  {
332  std::unique_lock lock(mapMutex);
333 
334  {
335  ARMARX_DEBUG << "Got event reported for active state changed: "
336  << event.parentStateIdentifier;
337  auto it = stateMap.find(event.parentStateIdentifier);
338  if (it == stateMap.end())
339  {
340  ARMARX_VERBOSE << "Could not find state with id "
341  << event.parentStateIdentifier;
342  return;
343  }
344  const StateListenerData& data = it->second;
345  for (const statechartmodel::StatePtr& state : data.states)
346  {
347  auto activeSubstate = state->getActiveSubstate();
348  if (activeSubstate)
349  {
350  // QMetaObject::invokeMethod(activeSubstate.get(), "setActive", Q_ARG(bool, false));
351  }
352  std::string activeSubstateName = ExtractStateName(event.targetStateIdentifier);
353  if (!activeSubstateName.empty())
354  {
355  auto it =
356  state->getSubstates().find(QString::fromStdString(activeSubstateName));
357  if (it != state->getSubstates().end())
358  {
359  statechartmodel::StateInstancePtr substate = *it;
360  if (substate)
361  {
362  ARMARX_DEBUG << "Invoking setActive for " << activeSubstateName;
363  QMetaObject::invokeMethod(
364  state.get(),
365  "setActiveSubstate",
366  Q_ARG(statechartmodel::StateInstancePtr, substate));
367  // QMetaObject::invokeMethod(substate.get(), "setActive", Q_ARG(bool, true));
368  }
369  }
370  else
371  {
372  ARMARX_INFO << "could not find state " << activeSubstateName;
373  }
374  }
375  else
376  {
377  QMetaObject::invokeMethod(state.get(),
378  "setActiveSubstate",
381  }
382  }
383  for (auto item : data.stateItems)
384  {
385  std::string activeSubstateName = ExtractStateName(event.targetStateIdentifier);
386  QMetaObject::invokeMethod(
387  item,
388  "setActiveSubstate",
389  Q_ARG(QString, QString::fromStdString(activeSubstateName)));
390  // QMetaObject::invokeMethod(item->getParentStateItem()->setActiveSubstate(QString::fromStdString(activeSubstateName));
391  }
392  }
393 
394  {
395  // ARMARX_IMPORTANT << "Got event reported for event: " << event->eventReceiverName;
396  auto it = stateMap.find(event.parentStateIdentifier);
397  if (it == stateMap.end())
398  {
399  ARMARX_VERBOSE << "Could not find state with id "
400  << event.parentStateIdentifier;
401  return;
402  }
403  const StateListenerData& data = it->second;
404  for (const statechartmodel::StatePtr& state : data.states)
405  {
406  statechartmodel::StateCPtr cstate = state;
407 
408  std::string eventName = event.eventName;
409  std::string sourceStateName = ExtractStateName(event.sourceStateIdentifier);
410  std::string destinationStateName =
411  ExtractStateName(event.targetStateIdentifier);
412 
413  if (state && !eventName.empty() && !destinationStateName.empty())
414  {
415  if (auto t =
416  state->findTransition(QString::fromStdString(eventName),
417  QString::fromStdString(sourceStateName),
418  QString::fromStdString(destinationStateName)))
419  {
420  ARMARX_DEBUG << "Invoking transition highlight for " << eventName
421  << " from " << sourceStateName << " to "
422  << destinationStateName;
423  QMetaObject::invokeMethod(state.get(),
424  "setTransitionActivated",
426  }
427  else
428  {
429  auto ct = cstate->getStartTransition();
430  if (ct && eventName == "InitialTransition")
431  {
432  ARMARX_DEBUG << "Invoking inital transition highlight for "
433  << state->getStateName();
434  QMetaObject::invokeMethod(
435  state.get(),
436  "setTransitionActivated",
438  }
439  else
440  {
441  ARMARX_VERBOSE << "Cannot find transition " << eventName
442  << " for highlighting "
443  << QString::fromStdString(sourceStateName) << " -> "
444  << QString::fromStdString(destinationStateName);
445  }
446  }
447  }
448  }
449  for (auto item : data.stateItems)
450  {
451  QString eventName = QString::fromStdString(event.eventName);
452  QString sourceStateName =
453  QString::fromStdString(ExtractStateName(event.sourceStateIdentifier));
454  QString destinationStateName =
455  QString::fromStdString(ExtractStateName(event.targetStateIdentifier));
456  if (item && !eventName.isEmpty() && !destinationStateName.isEmpty())
457  {
458  for (auto t : item->getTransitionItems())
459  {
460  statechartmodel::StateCPtr stateclass =
461  item->getStateInstance()->getStateClass();
462  if ((t->getTransition()->eventName == eventName &&
463  t->getTransition()->sourceState->getInstanceName() ==
464  sourceStateName) ||
465  (stateclass &&
466  t->getTransition() == stateclass->getStartTransition() &&
467  eventName == "InitialTransition"))
468  {
469  QMetaObject::invokeMethod(
470  t, "highlightAnimation", Q_ARG(int, 10000));
471  // t->highlightAnimation(10000);
472  }
473  }
474  }
475  }
476  }
477  }
478  catch (...)
479  {
480  ARMARX_DEBUG << "updating state " << event.parentStateIdentifier << " failed";
481  }
482  }
483 
484  void
485  StateWatcher::reportStatechartInputParameters(const ProfilerStatechartParameters& event,
486  const Ice::Current&)
487  {
488  std::unique_lock lock(mapMutex);
489  // ARMARX_INFO << "input update for " << event.stateIdentifier << " content: " << StateUtilFunctions::getDictionaryString(event.parameterMap);
490  stateMap[event.stateIdentifier].parameters["inputParameters"] = event.parameterMap;
491  }
492 
493  void
494  StateWatcher::reportStatechartLocalParameters(const ProfilerStatechartParameters& event,
495  const Ice::Current&)
496  {
497  std::unique_lock lock(mapMutex);
498  // ARMARX_INFO << "local update for " << event.stateIdentifier << " content: " << StateUtilFunctions::getDictionaryString(event.parameterMap);
499  stateMap[event.stateIdentifier].parameters["localParameters"] = event.parameterMap;
500  }
501 
502  void
503  StateWatcher::reportStatechartOutputParameters(const ProfilerStatechartParameters& event,
504  const Ice::Current&)
505  {
506  std::unique_lock lock(mapMutex);
507  // ARMARX_INFO << "output update for " << event.stateIdentifier << " content: " << StateUtilFunctions::getDictionaryString(event.parameterMap);
508  stateMap[event.stateIdentifier].parameters["outputParameters"] = event.parameterMap;
509  }
510 
511  void
512  StateWatcher::reportProcessCpuUsage(const ProfilerProcessCpuUsage&, const Ice::Current&)
513  {
514  }
515 
516  void
517  StateWatcher::reportProcessMemoryUsage(const ProfilerProcessMemoryUsage&, const Ice::Current&)
518  {
519  }
520 
521  void
522  StateWatcher::reportEventList(const ProfilerEventList&, const Ice::Current&)
523  {
524  }
525 
526  void
527  StateWatcher::reportStatechartTransitionList(const ProfilerStatechartTransitionList& data,
528  const Ice::Current& c)
529  {
530  for (auto& elem : data)
531  {
533  }
534  }
535 
536  void
537  StateWatcher::reportStatechartInputParametersList(const ProfilerStatechartParametersList& data,
538  const Ice::Current& c)
539  {
540  for (auto& elem : data)
541  {
543  }
544  }
545 
546  void
547  StateWatcher::reportStatechartLocalParametersList(const ProfilerStatechartParametersList& data,
548  const Ice::Current& c)
549  {
550  for (auto& elem : data)
551  {
553  }
554  }
555 
556  void
557  StateWatcher::reportStatechartOutputParametersList(const ProfilerStatechartParametersList& data,
558  const Ice::Current& c)
559  {
560  for (auto& elem : data)
561  {
563  }
564  }
565 
566  void
567  StateWatcher::reportProcessCpuUsageList(const ProfilerProcessCpuUsageList&, const Ice::Current&)
568  {
569  }
570 
571  void
572  StateWatcher::reportProcessMemoryUsageList(const ProfilerProcessMemoryUsageList&,
573  const Ice::Current&)
574  {
575  }
576 } // namespace armarx
armarx::StateWatcher::ExtractStateName
static std::string ExtractStateName(const std::string globalIdString)
Definition: StateWatcher.cpp:262
armarx::Variant
The Variant class is described here: Variants.
Definition: Variant.h:223
ARMARX_VERBOSE
#define ARMARX_VERBOSE
Definition: Logging.h:187
armarx::StateWatcher::unsubscribeState
bool unsubscribeState(StateItem *state)
Definition: StateWatcher.cpp:150
armarx::StateWatcher::reportNetworkTraffic
void reportNetworkTraffic(const std::string &, const std::string &, Ice::Int, Ice::Int, const Ice::Current &) override
Definition: StateWatcher.cpp:278
armarx::StateWatcher::reportStatechartOutputParameters
void reportStatechartOutputParameters(const ProfilerStatechartParameters &, const Ice::Current &) override
Definition: StateWatcher.cpp:503
armarx::StateWatcher::subscribeToState
bool subscribeToState(StateIceBasePtr iceState, StateItem *state)
Definition: StateWatcher.cpp:168
armarx::StateWatcher::StateListenerData
Definition: StateWatcher.h:40
armarx::StateWatcher::mapMutex
std::mutex mapMutex
Definition: StateWatcher.h:73
armarx::StateWatcher::reportStatechartOutputParametersList
void reportStatechartOutputParametersList(const ProfilerStatechartParametersList &, const Ice::Current &) override
Definition: StateWatcher.cpp:557
VariantContainer.h
armarx::StateWatcher::reportStatechartTransitionList
void reportStatechartTransitionList(const ProfilerStatechartTransitionList &, const Ice::Current &) override
Definition: StateWatcher.cpp:527
armarx::StateWatcher::onDisconnectComponent
void onDisconnectComponent() override
Hook for subclass.
Definition: StateWatcher.cpp:61
armarx::StateWatcher::getStateParameter
VariantPtr getStateParameter(statechartmodel::StatePtr state, const std::string paramMapType) const
Definition: StateWatcher.cpp:187
armarx::StateWatcher::clear
void clear()
Definition: StateWatcher.cpp:254
c
constexpr T c
Definition: UnscentedKalmanFilterTest.cpp:46
armarx::StateWatcher::reportProcessMemoryUsageList
void reportProcessMemoryUsageList(const ProfilerProcessMemoryUsageList &, const Ice::Current &) override
Definition: StateWatcher.cpp:572
StateUtilFunctions.h
armarx::Profiler::Profiler::eFunctionStart
@ eFunctionStart
Definition: Profiler.h:96
armarx::Profiler::Profiler::GetEventName
static std::string GetEventName(Profiler::EventType eventType)
getEventName maps enum values from armarx::Profiler::Profiler::EventType to strings
Definition: Profiler.cpp:33
Term.h
armarx::StateWatcher::subscriptionQueue
SubscriptionMap subscriptionQueue
Definition: StateWatcher.h:78
armarx::statechartmodel::StateInstancePtr
std::shared_ptr< StateInstance > StateInstancePtr
Definition: StateInstance.h:146
armarx::StateWatcher::reportProcessMemoryUsage
void reportProcessMemoryUsage(const ProfilerProcessMemoryUsage &, const Ice::Current &) override
Definition: StateWatcher.cpp:517
armarx::StateWatcher::reportEvent
void reportEvent(const ProfilerEvent &, const Ice::Current &) override
Definition: StateWatcher.cpp:287
armarx::StateWatcher::reportProcessCpuUsage
void reportProcessCpuUsage(const ProfilerProcessCpuUsage &, const Ice::Current &) override
Definition: StateWatcher.cpp:512
IceInternal::Handle< Variant >
armarx::StateWatcher::reportStatechartInputParameters
void reportStatechartInputParameters(const ProfilerStatechartParameters &event, const Ice::Current &) override
Definition: StateWatcher.cpp:485
StringValueMap.h
armarx::VariantPtr
IceInternal::Handle< Variant > VariantPtr
Definition: Variant.h:41
armarx::StateWatcher::reportProcessCpuUsageList
void reportProcessCpuUsageList(const ProfilerProcessCpuUsageList &, const Ice::Current &) override
Definition: StateWatcher.cpp:567
armarx::StateWatcher::onInitComponent
void onInitComponent() override
Pure virtual hook for the subclass.
Definition: StateWatcher.cpp:44
armarx::StateWatcher::subscriptionTask
PeriodicTask< StateWatcher >::pointer_type subscriptionTask
Definition: StateWatcher.h:79
armarx::statechartmodel::StateParameterMap
QMap< QString, StateParameterPtr > StateParameterMap
Definition: StateParameter.h:46
data
uint8_t data[1]
Definition: EtherCATFrame.h:68
ARMARX_DEBUG
#define ARMARX_DEBUG
Definition: Logging.h:184
Event.h
armarx::StateWatcher::stateMap
StateListenerDataMap stateMap
Definition: StateWatcher.h:72
armarx::StateWatcher::subscriptionFunction
void subscriptionFunction()
Definition: StateWatcher.cpp:74
armarx::StringValueMap::addElement
void addElement(const std::string &key, const VariantContainerBasePtr &variantContainer, const Ice::Current &c=Ice::emptyCurrent) override
Definition: StringValueMap.cpp:91
armarx::StateWatcher::reportEventList
void reportEventList(const ProfilerEventList &, const Ice::Current &) override
Definition: StateWatcher.cpp:522
armarx::StateWatcher::StateWatcher
StateWatcher()
Definition: StateWatcher.cpp:39
armarx::StateWatcher::SubscriptionMap
std::vector< std::pair< StateIceBasePtr, std::pair< statechartmodel::StatePtr, StateItem * > >> SubscriptionMap
Definition: StateWatcher.h:77
TransitionItem.h
armarx::ManagedIceObject::usingTopic
void usingTopic(const std::string &name, bool orderedPublishing=false)
Registers a proxy for subscription after initialization.
Definition: ManagedIceObject.cpp:254
armarx::StateWatcher::getDefaultName
std::string getDefaultName() const override
Retrieve default name of component.
Definition: StateWatcher.cpp:272
Profiler.h
ARMARX_INFO
#define ARMARX_INFO
Definition: Logging.h:181
armarx::StateWatcher::onConnectComponent
void onConnectComponent() override
Pure virtual hook for the subclass.
Definition: StateWatcher.cpp:50
armarx::StateWatcher::reportStatechartInputParametersList
void reportStatechartInputParametersList(const ProfilerStatechartParametersList &data, const Ice::Current &) override
Definition: StateWatcher.cpp:537
StateWatcher.h
armarx::statechartmodel::TransitionCPtr
std::shared_ptr< const Transition > TransitionCPtr
Definition: Transition.h:91
armarx::VariantType::Int
const VariantTypeId Int
Definition: Variant.h:917
armarx::statechartmodel::StatePtr
std::shared_ptr< State > StatePtr
Definition: State.h:48
armarx::StateItem
Definition: StateItem.h:58
armarx::StateWatcher::reportStatechartTransition
void reportStatechartTransition(const ProfilerStatechartTransition &event, const Ice::Current &) override
Definition: StateWatcher.cpp:327
armarx::StateWatcher::getStateParameterMap
::armarx::StateParameterMap getStateParameterMap(statechartmodel::StatePtr state, const std::string paramMapType) const
Definition: StateWatcher.cpp:216
armarx::PeriodicTask
Definition: ArmarXManager.h:70
armarx::handleExceptions
void handleExceptions()
Definition: Exception.cpp:157
ARMARX_WARNING
#define ARMARX_WARNING
Definition: Logging.h:193
armarx::statechartmodel::StateCPtr
std::shared_ptr< const State > StateCPtr
Definition: XmlWriter.h:45
armarx::StateWatcher::reportStatechartLocalParameters
void reportStatechartLocalParameters(const ProfilerStatechartParameters &event, const Ice::Current &) override
Definition: StateWatcher.cpp:494
armarx::StringValueMap
The StringValueMap class is a subclass of VariantContainer and is comparable to a std::map<std::strin...
Definition: StringValueMap.h:47
armarx::StateWatcher::reportStatechartLocalParametersList
void reportStatechartLocalParametersList(const ProfilerStatechartParametersList &, const Ice::Current &) override
Definition: StateWatcher.cpp:547
armarx::ctrlutil::s
double s(double t, double s0, double v0, double a0, double j)
Definition: CtrlUtil.h:33
armarx
This file offers overloads of toIce() and fromIce() functions for STL container types.
Definition: ArmarXTimeserver.cpp:27