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
37namespace armarx
38{
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
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
215 ::armarx::StateParameterMap
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 {
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
constexpr T c
void usingTopic(const std::string &name, bool orderedPublishing=false)
Registers a proxy for subscription after initialization.
The periodic task executes one thread method repeatedly using the time period specified in the constr...
static std::string GetEventName(Profiler::EventType eventType)
getEventName maps enum values from armarx::Profiler::Profiler::EventType to strings
Definition Profiler.cpp:33
void onInitComponent() override
Pure virtual hook for the subclass.
void reportStatechartInputParameters(const ProfilerStatechartParameters &event, const Ice::Current &) override
std::vector< std::pair< StateIceBasePtr, std::pair< statechartmodel::StatePtr, StateItem * > > > SubscriptionMap
::armarx::StateParameterMap getStateParameterMap(statechartmodel::StatePtr state, const std::string paramMapType) const
VariantPtr getStateParameter(statechartmodel::StatePtr state, const std::string paramMapType) const
void onDisconnectComponent() override
Hook for subclass.
void reportStatechartOutputParameters(const ProfilerStatechartParameters &, const Ice::Current &) override
void reportStatechartLocalParameters(const ProfilerStatechartParameters &event, const Ice::Current &) override
void reportStatechartLocalParametersList(const ProfilerStatechartParametersList &, const Ice::Current &) override
SubscriptionMap subscriptionQueue
void reportStatechartTransitionList(const ProfilerStatechartTransitionList &, const Ice::Current &) override
void reportProcessCpuUsageList(const ProfilerProcessCpuUsageList &, const Ice::Current &) override
void reportNetworkTraffic(const std::string &, const std::string &, Ice::Int, Ice::Int, const Ice::Current &) override
bool unsubscribeState(StateItem *state)
void reportStatechartInputParametersList(const ProfilerStatechartParametersList &data, const Ice::Current &) override
void reportProcessCpuUsage(const ProfilerProcessCpuUsage &, const Ice::Current &) override
void onConnectComponent() override
Pure virtual hook for the subclass.
void reportEvent(const ProfilerEvent &, const Ice::Current &) override
static std::string ExtractStateName(const std::string globalIdString)
void reportProcessMemoryUsageList(const ProfilerProcessMemoryUsageList &, const Ice::Current &) override
void reportEventList(const ProfilerEventList &, const Ice::Current &) override
bool subscribeToState(StateIceBasePtr iceState, StateItem *state)
PeriodicTask< StateWatcher >::pointer_type subscriptionTask
StateListenerDataMap stateMap
void reportStatechartOutputParametersList(const ProfilerStatechartParametersList &, const Ice::Current &) override
void reportStatechartTransition(const ProfilerStatechartTransition &event, const Ice::Current &) override
std::string getDefaultName() const override
Retrieve default name of component.
void reportProcessMemoryUsage(const ProfilerProcessMemoryUsage &, const Ice::Current &) override
The StringValueMap class is a subclass of VariantContainer and is comparable to a std::map<std::strin...
The Variant class is described here: Variants.
Definition Variant.h:224
#define ARMARX_INFO
The normal logging level.
Definition Logging.h:181
#define ARMARX_DEBUG
The logging level for output that is only interesting while debugging.
Definition Logging.h:184
#define ARMARX_WARNING
The logging level for unexpected behaviour, but not a serious problem.
Definition Logging.h:193
#define ARMARX_VERBOSE
The logging level for verbose information.
Definition Logging.h:187
std::shared_ptr< State > StatePtr
Definition State.h:48
std::shared_ptr< StateInstance > StateInstancePtr
std::shared_ptr< const State > StateCPtr
Definition XmlWriter.h:45
std::shared_ptr< const Transition > TransitionCPtr
Definition Transition.h:91
This file offers overloads of toIce() and fromIce() functions for STL container types.
void handleExceptions()
IceInternal::Handle< Variant > VariantPtr
Definition Variant.h:41