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 #include "view/TransitionItem.h"
27 
28 #include <iterator>
29 
31 
35 #include <ArmarXCore/core/services/profiler/Profiler.h> // for ProfilerPtr
36 
37 
38 namespace armarx
39 {
41  {
42  }
43 
44 
46  {
47  usingTopic("StateReportingTopic");
48  }
49 
51  {
52 
53  qRegisterMetaType<statechartmodel::TransitionCPtr>("TransitionCPtr");
54  qRegisterMetaType<statechartmodel::StateInstancePtr>("StateInstancePtr");
56  subscriptionTask->start();
57  }
58 
60  {
61  subscriptionTask->stop();
62  try
63  {
64  clear();
65  }
66  catch (...)
67  {
68 
69  }
70  }
71 
73  {
74  SubscriptionMap tempList;
75  {
76  std::unique_lock lock(mapMutex);
77  tempList.swap(subscriptionQueue);
78  }
79  ARMARX_DEBUG << tempList.size() << " new subscriptions received";
80  for (auto& elem : tempList)
81  {
82  StateIceBasePtr iceState = elem.first;
83  statechartmodel::StatePtr state = elem.second.first;
84  StateItem* stateItem = elem.second.second;
85  StateListenerDataMap::iterator it;
86  {
87  std::unique_lock lock(mapMutex);
88  it = stateMap.find(iceState->globalStateIdentifier);
89  if (it != stateMap.end() && state && it->second.states.count(state) > 0)
90  {
91  continue;
92  }
93  if (it != stateMap.end() && stateItem && it->second.stateItems.count(stateItem) > 0)
94  {
95  continue;
96  }
97  }
98  ARMARX_VERBOSE << "subscribing : " << iceState->globalStateIdentifier;
99  try
100  {
101 
103  if (it != stateMap.end())
104  {
105  data = it->second;
106  }
107  data.iceState = iceState;
108  if (state)
109  {
110  data.states.insert(state);
111  }
112  if (stateItem)
113  {
114  data.stateItems.insert(stateItem);
115  }
116 
117  std::unique_lock lock(mapMutex);
118  stateMap[iceState->globalStateIdentifier] = data;
119  // ARMARX_IMPORTANT << "subscribed to " << iceState->globalStateIdentifier;
120  }
121  catch (...)
122  {
124  }
125  }
126 
127  }
128 
129  bool StateWatcher::subscribeToState(StateIceBasePtr iceState, statechartmodel::StatePtr state)
130  {
131  std::unique_lock lock(mapMutex);
132  if (!iceState)
133  {
134  ARMARX_WARNING << "Ice State NULL";
135  return false;
136  }
137  if (!state)
138  {
139  ARMARX_WARNING << "State NULL: " << iceState->globalStateIdentifier;
140  return false;
141  }
142  StateItem* item = nullptr;
143  subscriptionQueue.push_back(std::make_pair(iceState, std::make_pair(state, item)));
144  return true;
145  }
146 
148  {
149  std::unique_lock lock(mapMutex);
150  for (auto& pair : stateMap)
151  {
152  for (auto item : pair.second.stateItems)
153  {
154  if (item == state)
155  {
156  pair.second.stateItems.erase(state);
157  return true;
158  }
159  }
160  }
161  return false;
162  }
163 
164  bool StateWatcher::subscribeToState(StateIceBasePtr iceState, StateItem* state)
165  {
166  std::unique_lock lock(mapMutex);
167  if (!iceState)
168  {
169  ARMARX_WARNING << "Ice State NULL";
170  return false;
171  }
172  if (!state)
173  {
174  ARMARX_WARNING << "State NULL: " << iceState->globalStateIdentifier;
175  return false;
176  }
177  subscriptionQueue.push_back(std::make_pair(iceState, std::make_pair(statechartmodel::StatePtr(), state)));
178  return true;
179  }
180 
181  VariantPtr StateWatcher::getStateParameter(statechartmodel::StatePtr state, const std::string paramMapType) const
182  {
183  std::unique_lock lock(mapMutex);
184  try
185  {
186  for (const auto& stateData : stateMap)
187  {
188  if (stateData.second.states.count(state))
189  {
190  // ARMARX_INFO << "Checking: " << "Found";
191  StringValueMap map(false);
192  for (auto& entry : stateData.second.parameters.at(paramMapType))
193  {
194  map.addElement(entry.first, entry.second->value);
195  }
196  return new Variant(map);
197  }
198  }
199  }
200  catch (...)
201  {
203  }
204 
205  return VariantPtr();
206  }
207 
209  {
210  std::unique_lock lock(mapMutex);
211  // try
212  {
213  for (const auto& stateData : stateMap)
214  {
215  if (stateData.second.states.count(state))
216  {
217  // ARMARX_INFO << "Checking: " << "Found";
218  ARMARX_INFO << "query state: " << stateData.second.iceState->globalStateIdentifier;
219 
220  auto it = stateData.second.parameters.find(paramMapType);
221  if (it == stateData.second.parameters.end())
222  {
223  std::stringstream s;
224  for (auto& e : stateData.second.parameters)
225  {
226  s << e.first << ", ";
227  }
228  throw LocalException() << "could not find " << paramMapType << " available: " << s.str();
229 
230  }
231  return it->second;
232  }
233  }
234  }
235  // catch (...)
236  // {
237  // handleExceptions();
238  // }
239 
240  return StateParameterMap();
241  }
242 
244  {
245  std::unique_lock lock(mapMutex);
246 
247  stateMap.clear();
248  }
249 
250  std::string StateWatcher::ExtractStateName(const std::string globalIdString)
251  {
252  if (globalIdString.find("->") == std::string::npos)
253  {
254  return globalIdString;
255  }
256  return globalIdString.substr(globalIdString.find_last_of("->") + 1);
257  }
258 
259 
260  std::string StateWatcher::getDefaultName() const
261  {
262  return "StateWatcher";
263  }
264 
265 
266  void StateWatcher::reportNetworkTraffic(const std::string&, const std::string&, Ice::Int, Ice::Int, const Ice::Current&)
267  {
268  }
269 
270  void StateWatcher::reportEvent(const ProfilerEvent& event, const Ice::Current&)
271  {
272  try
273  {
274  std::string stateIdentifier = event.parentName;
276  {
277  std::unique_lock lock(mapMutex);
278  auto it = stateMap.find(stateIdentifier);
279  if (it == stateMap.end())
280  {
281  ARMARX_VERBOSE << "Could not find state with id " << stateIdentifier;
282  return;
283  }
284  const StateListenerData& data = it->second;
285  for (auto& state : data.states)
286  {
287  if (state)
288  {
289  QMetaObject::invokeMethod(state.get(), "setActiveSubstate", Q_ARG(statechartmodel::StateInstancePtr, statechartmodel::StateInstancePtr()));
290  // auto subState = state->getActiveSubstate();
291  // if (subState)
292  // {
293  // QMetaObject::invokeMethod(subState.get(), "setActive", Q_ARG(bool, false));
294  // }
295  }
296  }
297  }
298  }
299  catch (...)
300  {
302  }
303  }
304 
305  void StateWatcher::reportStatechartTransition(const ProfilerStatechartTransition& event, const Ice::Current&)
306  {
307  try
308  {
309  std::unique_lock lock(mapMutex);
310 
311  {
312  ARMARX_DEBUG << "Got event reported for active state changed: " << event.parentStateIdentifier;
313  auto it = stateMap.find(event.parentStateIdentifier);
314  if (it == stateMap.end())
315  {
316  ARMARX_VERBOSE << "Could not find state with id " << event.parentStateIdentifier;
317  return;
318  }
319  const StateListenerData& data = it->second;
320  for (const statechartmodel::StatePtr& state : data.states)
321  {
322  auto activeSubstate = state->getActiveSubstate();
323  if (activeSubstate)
324  {
325  // QMetaObject::invokeMethod(activeSubstate.get(), "setActive", Q_ARG(bool, false));
326  }
327  std::string activeSubstateName = ExtractStateName(event.targetStateIdentifier);
328  if (!activeSubstateName.empty())
329  {
330  auto it = state->getSubstates().find(QString::fromStdString(activeSubstateName));
331  if (it != state->getSubstates().end())
332  {
333  statechartmodel::StateInstancePtr substate = *it;
334  if (substate)
335  {
336  ARMARX_DEBUG << "Invoking setActive for " << activeSubstateName;
337  QMetaObject::invokeMethod(state.get(), "setActiveSubstate", Q_ARG(statechartmodel::StateInstancePtr, substate));
338  // QMetaObject::invokeMethod(substate.get(), "setActive", Q_ARG(bool, true));
339  }
340  }
341  else
342  {
343  ARMARX_INFO << "could not find state " << activeSubstateName;
344  }
345  }
346  else
347  {
348  QMetaObject::invokeMethod(state.get(), "setActiveSubstate", Q_ARG(statechartmodel::StateInstancePtr, statechartmodel::StateInstancePtr()));
349  }
350  }
351  for (auto item : data.stateItems)
352  {
353  std::string activeSubstateName = ExtractStateName(event.targetStateIdentifier);
354  QMetaObject::invokeMethod(item, "setActiveSubstate", Q_ARG(QString, QString::fromStdString(activeSubstateName)));
355  // QMetaObject::invokeMethod(item->getParentStateItem()->setActiveSubstate(QString::fromStdString(activeSubstateName));
356  }
357 
358  }
359 
360  {
361  // ARMARX_IMPORTANT << "Got event reported for event: " << event->eventReceiverName;
362  auto it = stateMap.find(event.parentStateIdentifier);
363  if (it == stateMap.end())
364  {
365  ARMARX_VERBOSE << "Could not find state with id " << event.parentStateIdentifier;
366  return;
367  }
368  const StateListenerData& data = it->second;
369  for (const statechartmodel::StatePtr& state : data.states)
370  {
371  statechartmodel::StateCPtr cstate = state;
372 
373  std::string eventName = event.eventName;
374  std::string sourceStateName = ExtractStateName(event.sourceStateIdentifier);
375  std::string destinationStateName = ExtractStateName(event.targetStateIdentifier);
376 
377  if (state && !eventName.empty() && !destinationStateName.empty())
378  {
379  if (auto t = state->findTransition(QString::fromStdString(eventName), QString::fromStdString(sourceStateName), QString::fromStdString(destinationStateName)))
380  {
381  ARMARX_DEBUG << "Invoking transition highlight for " << eventName << " from " << sourceStateName << " to " << destinationStateName;
382  QMetaObject::invokeMethod(state.get(), "setTransitionActivated", Q_ARG(statechartmodel::TransitionCPtr, t));
383  }
384  else
385  {
386  auto ct = cstate->getStartTransition();
387  if (ct && eventName == "InitialTransition")
388  {
389  ARMARX_DEBUG << "Invoking inital transition highlight for " << state->getStateName();
390  QMetaObject::invokeMethod(state.get(), "setTransitionActivated", Q_ARG(statechartmodel::TransitionCPtr, ct));
391  }
392  else
393  {
394  ARMARX_VERBOSE << "Cannot find transition " << eventName << " for highlighting " << QString::fromStdString(sourceStateName) << " -> " << QString::fromStdString(destinationStateName);
395  }
396  }
397  }
398  }
399  for (auto item : data.stateItems)
400  {
401  QString eventName = QString::fromStdString(event.eventName);
402  QString sourceStateName = QString::fromStdString(ExtractStateName(event.sourceStateIdentifier));
403  QString destinationStateName = QString::fromStdString(ExtractStateName(event.targetStateIdentifier));
404  if (item && !eventName.isEmpty() && !destinationStateName.isEmpty())
405  {
406  for (auto t : item->getTransitionItems())
407  {
408  statechartmodel::StateCPtr stateclass = item->getStateInstance()->getStateClass();
409  if ((t->getTransition()->eventName == eventName && t->getTransition()->sourceState->getInstanceName() == sourceStateName)
410  || (stateclass && t->getTransition() == stateclass->getStartTransition() && eventName == "InitialTransition"))
411  {
412  QMetaObject::invokeMethod(t, "highlightAnimation", Q_ARG(int, 10000));
413  // t->highlightAnimation(10000);
414  }
415  }
416  }
417  }
418  }
419  }
420  catch (...)
421  {
422  ARMARX_DEBUG << "updating state " << event.parentStateIdentifier << " failed";
423  }
424 
425 
426 
427  }
428 
429  void StateWatcher::reportStatechartInputParameters(const ProfilerStatechartParameters& event, const Ice::Current&)
430  {
431  std::unique_lock lock(mapMutex);
432  // ARMARX_INFO << "input update for " << event.stateIdentifier << " content: " << StateUtilFunctions::getDictionaryString(event.parameterMap);
433  stateMap[event.stateIdentifier].parameters["inputParameters"] = event.parameterMap;
434  }
435 
436  void StateWatcher::reportStatechartLocalParameters(const ProfilerStatechartParameters& event, const Ice::Current&)
437  {
438  std::unique_lock lock(mapMutex);
439  // ARMARX_INFO << "local update for " << event.stateIdentifier << " content: " << StateUtilFunctions::getDictionaryString(event.parameterMap);
440  stateMap[event.stateIdentifier].parameters["localParameters"] = event.parameterMap;
441  }
442 
443  void StateWatcher::reportStatechartOutputParameters(const ProfilerStatechartParameters& event, const Ice::Current&)
444  {
445  std::unique_lock lock(mapMutex);
446  // ARMARX_INFO << "output update for " << event.stateIdentifier << " content: " << StateUtilFunctions::getDictionaryString(event.parameterMap);
447  stateMap[event.stateIdentifier].parameters["outputParameters"] = event.parameterMap;
448 
449  }
450 
451  void StateWatcher::reportProcessCpuUsage(const ProfilerProcessCpuUsage&, const Ice::Current&)
452  {
453  }
454 
455  void StateWatcher::reportProcessMemoryUsage(const ProfilerProcessMemoryUsage&, const Ice::Current&)
456  {
457  }
458 
459  void StateWatcher::reportEventList(const ProfilerEventList&, const Ice::Current&)
460  {
461  }
462 
463  void StateWatcher::reportStatechartTransitionList(const ProfilerStatechartTransitionList& data, const Ice::Current& c)
464  {
465  for (auto& elem : data)
466  {
468  }
469  }
470 
471  void StateWatcher::reportStatechartInputParametersList(const ProfilerStatechartParametersList& data, const Ice::Current& c)
472  {
473  for (auto& elem : data)
474  {
476  }
477  }
478 
479  void StateWatcher::reportStatechartLocalParametersList(const ProfilerStatechartParametersList& data, const Ice::Current& c)
480  {
481  for (auto& elem : data)
482  {
484  }
485  }
486 
487  void StateWatcher::reportStatechartOutputParametersList(const ProfilerStatechartParametersList& data, const Ice::Current& c)
488  {
489  for (auto& elem : data)
490  {
492  }
493  }
494 
495  void StateWatcher::reportProcessCpuUsageList(const ProfilerProcessCpuUsageList&, const Ice::Current&)
496  {
497  }
498 
499  void StateWatcher::reportProcessMemoryUsageList(const ProfilerProcessMemoryUsageList&, const Ice::Current&)
500  {
501  }
502 }
armarx::StateWatcher::ExtractStateName
static std::string ExtractStateName(const std::string globalIdString)
Definition: StateWatcher.cpp:250
armarx::Variant
The Variant class is described here: Variants.
Definition: Variant.h:224
ARMARX_VERBOSE
#define ARMARX_VERBOSE
Definition: Logging.h:180
armarx::StateWatcher::unsubscribeState
bool unsubscribeState(StateItem *state)
Definition: StateWatcher.cpp:147
armarx::StateWatcher::reportNetworkTraffic
void reportNetworkTraffic(const std::string &, const std::string &, Ice::Int, Ice::Int, const Ice::Current &) override
Definition: StateWatcher.cpp:266
armarx::StateWatcher::reportStatechartOutputParameters
void reportStatechartOutputParameters(const ProfilerStatechartParameters &, const Ice::Current &) override
Definition: StateWatcher.cpp:443
armarx::StateWatcher::subscribeToState
bool subscribeToState(StateIceBasePtr iceState, StateItem *state)
Definition: StateWatcher.cpp:164
armarx::StateWatcher::StateListenerData
Definition: StateWatcher.h:42
armarx::StateWatcher::SubscriptionMap
std::vector< std::pair< StateIceBasePtr, std::pair< statechartmodel::StatePtr, StateItem * > > > SubscriptionMap
Definition: StateWatcher.h:77
armarx::StateWatcher::mapMutex
std::mutex mapMutex
Definition: StateWatcher.h:74
armarx::StateWatcher::reportStatechartOutputParametersList
void reportStatechartOutputParametersList(const ProfilerStatechartParametersList &, const Ice::Current &) override
Definition: StateWatcher.cpp:487
VariantContainer.h
armarx::StateWatcher::reportStatechartTransitionList
void reportStatechartTransitionList(const ProfilerStatechartTransitionList &, const Ice::Current &) override
Definition: StateWatcher.cpp:463
armarx::StateWatcher::onDisconnectComponent
void onDisconnectComponent() override
Hook for subclass.
Definition: StateWatcher.cpp:59
armarx::StateWatcher::getStateParameter
VariantPtr getStateParameter(statechartmodel::StatePtr state, const std::string paramMapType) const
Definition: StateWatcher.cpp:181
armarx::StateWatcher::clear
void clear()
Definition: StateWatcher.cpp:243
c
constexpr T c
Definition: UnscentedKalmanFilterTest.cpp:43
armarx::StateWatcher::reportProcessMemoryUsageList
void reportProcessMemoryUsageList(const ProfilerProcessMemoryUsageList &, const Ice::Current &) override
Definition: StateWatcher.cpp:499
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:31
Term.h
armarx::StateWatcher::subscriptionQueue
SubscriptionMap subscriptionQueue
Definition: StateWatcher.h:78
armarx::statechartmodel::StateInstancePtr
std::shared_ptr< StateInstance > StateInstancePtr
Definition: StateInstance.h:138
armarx::StateWatcher::reportProcessMemoryUsage
void reportProcessMemoryUsage(const ProfilerProcessMemoryUsage &, const Ice::Current &) override
Definition: StateWatcher.cpp:455
armarx::StateWatcher::reportEvent
void reportEvent(const ProfilerEvent &, const Ice::Current &) override
Definition: StateWatcher.cpp:270
armarx::StateWatcher::reportProcessCpuUsage
void reportProcessCpuUsage(const ProfilerProcessCpuUsage &, const Ice::Current &) override
Definition: StateWatcher.cpp:451
IceInternal::Handle< Variant >
armarx::StateWatcher::reportStatechartInputParameters
void reportStatechartInputParameters(const ProfilerStatechartParameters &event, const Ice::Current &) override
Definition: StateWatcher.cpp:429
StringValueMap.h
armarx::VariantPtr
IceInternal::Handle< Variant > VariantPtr
Definition: Variant.h:42
armarx::StateWatcher::reportProcessCpuUsageList
void reportProcessCpuUsageList(const ProfilerProcessCpuUsageList &, const Ice::Current &) override
Definition: StateWatcher.cpp:495
armarx::StateWatcher::onInitComponent
void onInitComponent() override
Pure virtual hook for the subclass.
Definition: StateWatcher.cpp:45
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:177
Event.h
armarx::StateWatcher::stateMap
StateListenerDataMap stateMap
Definition: StateWatcher.h:73
armarx::StateWatcher::subscriptionFunction
void subscriptionFunction()
Definition: StateWatcher.cpp:72
armarx::StringValueMap::addElement
void addElement(const std::string &key, const VariantContainerBasePtr &variantContainer, const Ice::Current &c=Ice::emptyCurrent) override
Definition: StringValueMap.cpp:92
armarx::StateWatcher::reportEventList
void reportEventList(const ProfilerEventList &, const Ice::Current &) override
Definition: StateWatcher.cpp:459
armarx::StateWatcher::StateWatcher
StateWatcher()
Definition: StateWatcher.cpp:40
TransitionItem.h
armarx::ManagedIceObject::usingTopic
void usingTopic(const std::string &name, bool orderedPublishing=false)
Registers a proxy for subscription after initialization.
Definition: ManagedIceObject.cpp:248
armarx::StateWatcher::getDefaultName
std::string getDefaultName() const override
Retrieve default name of component.
Definition: StateWatcher.cpp:260
Profiler.h
ARMARX_INFO
#define ARMARX_INFO
Definition: Logging.h:174
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:471
StateWatcher.h
armarx::statechartmodel::TransitionCPtr
std::shared_ptr< const Transition > TransitionCPtr
Definition: Transition.h:94
armarx::VariantType::Int
const VariantTypeId Int
Definition: Variant.h:916
armarx::statechartmodel::StatePtr
std::shared_ptr< State > StatePtr
Definition: State.h:46
armarx::StateItem
Definition: StateItem.h:58
armarx::StateWatcher::reportStatechartTransition
void reportStatechartTransition(const ProfilerStatechartTransition &event, const Ice::Current &) override
Definition: StateWatcher.cpp:305
armarx::StateWatcher::getStateParameterMap
::armarx::StateParameterMap getStateParameterMap(statechartmodel::StatePtr state, const std::string paramMapType) const
Definition: StateWatcher.cpp:208
armarx::PeriodicTask
Definition: ArmarXManager.h:70
armarx::handleExceptions
void handleExceptions()
Definition: Exception.cpp:141
ARMARX_WARNING
#define ARMARX_WARNING
Definition: Logging.h:186
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:436
armarx::StringValueMap
The StringValueMap class is a subclass of VariantContainer and is comparable to a std::map<std::strin...
Definition: StringValueMap.h:49
armarx::StateWatcher::reportStatechartLocalParametersList
void reportStatechartLocalParametersList(const ProfilerStatechartParametersList &, const Ice::Current &) override
Definition: StateWatcher.cpp:479
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:28