StateUtil.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 ArmarXCore::Statechart
19 * @author Mirko Waechter( mirko.waechter at kit dot edu)
20 * @date 2012
21 * @copyright http://www.gnu.org/licenses/gpl-2.0.txt
22 * GNU General Public License
23 */
24 #include "StateUtil.h"
25 #include "StatechartContext.h"
26 #include "StateParameter.h"
27 #include "StatechartManager.h"
29 #include "StateBaseImpl.h"
31 
33 #include <sstream>
34 
35 
36 namespace armarx
37 {
38  void StateUtility::sendEvent(const EventPtr event, StateBasePtr eventProcessor)
39  {
40  // __checkPhaseMin(eEntering, __PRETTY_FUNCTION__);
41 
42  if (!eventProcessor._ptr)
43  {
44  eventProcessor = impl->__parentState;
45  }
46 
47  // if sendEvent was called and this state is not active anymore, omit event
48  if (
49  (eventProcessor.get() == impl->__parentState && (getStatePhase() < eEntering || getStatePhase() >= eBreaking))
50  || (impl->__parentState && impl->__parentState->activeSubstate.get() != this))
51  {
52  ARMARX_VERBOSE << "The state " << stateName << " is not active anymore - event '" << event->eventName << "' omitted" << std::endl;
53 
54  if (impl->__parentState->activeSubstate)
55  {
56  ARMARX_VERBOSE << "Active state is now: " << StateBasePtr::dynamicCast(impl->__parentState->activeSubstate)->stateName;
57  }
58 
59  return;
60  }
61 
62  // if(!checkEventIsHandled(event))
63  // {
64  // throw exceptions::local::eStatechartLogicError("The event " + event->eventName + " is not handled by the parent state. Please insert a transition for this event in the parent state of state '" + getGlobalHierarchyString() + "'");
65  // }
66  StateControllerPtr eventController = StateControllerPtr::dynamicCast(eventProcessor); // cast here to make sure cast works
67 
68  if (eventController._ptr)
69  {
70  if (impl->manager)
71  {
72  impl->manager->addEvent(event, eventController);
73  }
74 
75  // ScopedRecursiveLock lock(__eventBufferMutex);
76  // ARMARX_VERBOSE << "NEW event inserted";
77  // __eventBuffer.push_back(pair<StateControllerPtr, EventPtr>(eventController, event));
78  }
79 
80  // if(__stateMutex.try_lock()){// if locked, this function was called from onEnter()
81  // __stateMutex.unlock();
82  // if(functionPhase != eRunning)
83  // __processEvents();
84  // }
85 
86  }
87 
88  // std::string StateUtility::getScope() const
89  // {
90  // std::stringstream str;
91  // str << context->getName() << "_" << stateName << "_" << localUniqueId;
92  // return str.str();
93  // }
94 
95 
96 
97  ConditionIdentifier StateUtility::installCondition(const Term& condition, const EventPtr evt, const std::string& desc)
98  {
99  __checkPhase({eEntering, eEntered}, __PRETTY_FUNCTION__);
100  StatechartContext* context = getContext<StatechartContext>();
101  if (!context)
102  {
104  }
105 
106  if (!impl->__parentState)
107  {
109  }
110 
111  // if (!checkEventIsHandled(evt))
112  // {
113  // throw exceptions::local::eStatechartLogicError("The event " + evt->eventName + " is not handled by the parent state. Please insert a transition for this event in the parent state of state '" + getGlobalHierarchyString() + "'");
114  // }
115 
116  StateBasePtr eventProcessor = impl->__parentState;
117  ConditionHandlerInterfacePrx conditionHandlerPrx = context->conditionHandlerPrx;
118 
119  std::string uniqueEventIdentifier = context->eventDistributor->registerEvent(evt, eventProcessor, impl->visitCounter);
120 
121  EventPtr sentEvent = new Event(*evt);
122  sentEvent->eventName = uniqueEventIdentifier;
123 
124  ARMARX_DEBUG << "registered event: " << sentEvent->eventName << ", EventRecv:" << sentEvent->eventReceiverName << flush;
125  installedConditions.push_back(condition.getImpl());
126  ConditionIdentifier condId = conditionHandlerPrx->installConditionWithDescription(context->eventDistributor->getListener(), condition.getImpl(), sentEvent, desc, true, false, {});
127  __installedConditionIdentifiers.push_back(condId);
128  return condId;
129  }
130 
131  void StateUtility::removeCondition(ConditionIdentifier conditionId)
132  {
133  auto context = getContext<StatechartContext>();
134  if (!context)
135  {
137  }
138 
139  // remove from eventmap?
140  ARMARX_DEBUG << "removing condition with Id: " << conditionId.uniqueId << flush;
141  context->conditionHandlerPrx->begin_removeCondition(conditionId);
142  }
143 
145  {
146  __checkPhase(eEntering, __PRETTY_FUNCTION__);
147 
148  StatechartContext* context = getContext<StatechartContext>();
149  ARMARX_INFO << "Installing Timeout Event (Timeout: " << timeoutDurationMs << "ms)" << flush;
150 
151  if (!context)
152  {
153  throw exceptions::local::eNullPointerException("context pointer is NULL");
154  }
155 
156  if (!context->eventDistributor->getProxy())
157  {
158  throw exceptions::local::eNullPointerException("eventWrapper->myproxy was not set");
159  }
160 
161  if (!impl->__parentState)
162  {
163  throw exceptions::local::eNullPointerException("parent pointer is NULL");
164  }
165 
166 
167  std::stringstream timerName;
168  timerName << "Timer_" << context->getName() << "_" << stateName << "_" << impl->localUniqueId << "_" << evt->eventName << "_" << timeoutDurationMs << "ms";
169 
170  ActionEventIdentifier result;
171  result.actionId = ChannelRefPtr::dynamicCast(context->systemObserverPrx->startTimer(timerName.str()));
172  __installedTimerChannelRefs.push_back(result.actionId);
173  Literal expression(ChannelRefPtr::dynamicCast(result.actionId)->getDataFieldIdentifier("elapsedMs"), "larger", Literal::createParameterList(timeoutDurationMs));
174  result.conditionId = installCondition(expression, evt, "Timeout condition");
175  return result;
176  }
177 
179  {
180  StatechartContext* context = getContext<StatechartContext>();
181  if (!context)
182  {
184  }
185 
186  context->systemObserverPrx->begin_removeTimer(id.actionId);
187  removeCondition(id.conditionId);
188  }
189 
190 
191 
192  StateUtility::ActionEventIdentifier StateUtility::setCounterEvent(int counterThreshold, const EventPtr& evt, int initialValue)
193  {
194  __checkPhaseMin(eEntering, __PRETTY_FUNCTION__);
195  StatechartContext* context = getContext<StatechartContext>();
196  ARMARX_INFO << "Installing Counter Event (Counter Threshold: " << counterThreshold << ", InitialValue: " << initialValue << ")" << flush;
197 
198  if (!context)
199  {
200  throw exceptions::local::eNullPointerException("context pointer is NULL");
201  }
202 
203  if (!context->eventDistributor->getListener())
204  {
205  throw exceptions::local::eNullPointerException("eventWrapper->myproxy was not set");
206  }
207 
208  if (!impl->__parentState)
209  {
210  throw exceptions::local::eNullPointerException("parentState pointer is NULL");
211  }
212 
213 
214  std::stringstream counterName;
215  counterName << "Counter_" << stateName << "_" << impl->localUniqueId << "_" << evt->eventName;
216 
217  ActionEventIdentifier result;
218 
219  result.actionId = ChannelRefPtr::dynamicCast(context->systemObserverPrx->startCounter(initialValue, counterName.str()));
220  __installedCounterChannelRefs.push_back(result.actionId);
221  Literal expression(ChannelRefPtr::dynamicCast(result.actionId)->getDataFieldIdentifier("value"), "equals", Literal::createParameterList(counterThreshold));
222  result.conditionId = installCondition(expression, evt, "Counter condition");
223  return result;
224  }
225 
227  {
228  StatechartContext* context = getContext<StatechartContext>();
229  if (!context)
230  {
232  }
233 
234  context->systemObserverPrx->begin_removeCounter(id.actionId);
235  removeCondition(id.conditionId);
236  }
237 
238  bool
239  StateUtility::checkEventIsHandled(const EventPtr& event) const
240  {
241  __checkPhaseMin(eDefined, __PRETTY_FUNCTION__);
242 
243  if (!impl->__parentState)
244  {
245  throw exceptions::local::eNullPointerException("parentState pointer is NULL");
246  }
247 
248  for (unsigned int i = 0; i < impl->__parentState->transitions.size(); ++i)
249  {
250  TransitionIceBase& t = impl->__parentState->transitions.at(i);
251 
252  if (t.evt->eventName == event->eventName)
253  {
254  return true;
255  }
256  }
257 
258  return false;
259  }
260 
261  EventPtr StateUtility::createEvent(const std::string& eventName, const StringVariantContainerBaseMap& properties)
262  {
263  EventPtr evt = new Event(this->stateName, eventName);
264  evt->properties = properties;
265  return evt;
266  }
267 
268  void StateUtility::_removeInstalledConditions()
269  {
270  StatechartContext* context = dynamic_cast<StatechartContext*>(getContext(false));
271  if (!context)
272  {
273  ARMARX_INFO << "Statechart Context is NULL - cannot clear installed conditions";
274  return;
275  }
276  for (auto c : __installedConditionIdentifiers)
277  {
279  }
280 
281  __installedConditionIdentifiers.clear();
282 
283  for (auto c : __installedTimerChannelRefs)
284  {
285  context->systemObserverPrx->removeTimer(c);
286  }
287 
288  __installedTimerChannelRefs.clear();
289 
290  for (auto c : __installedCounterChannelRefs)
291  {
292  context->systemObserverPrx->begin_removeCounter(c);
293  }
294 
295  __installedCounterChannelRefs.clear();
296  }
297 
298 
299 }
300 
armarx::StateBase::eEntered
@ eEntered
Definition: StateBase.h:273
armarx::StateUtility::removeCondition
void removeCondition(ConditionIdentifier conditionId)
Utility function to remove an installed condition on the distributed conditionhandler.
Definition: StateUtil.cpp:131
armarx::StateBase::getContext
ContextType * getContext() const
Definition: StateBase.h:74
armarx::StateBase::eEntering
@ eEntering
Definition: StateBase.h:272
ARMARX_VERBOSE
#define ARMARX_VERBOSE
Definition: Logging.h:180
StateBaseImpl.h
armarx::StateBase::__checkPhaseMin
void __checkPhaseMin(StatePhase allowedType, const char *functionName) const
Definition: StateBase.cpp:225
armarx::StatechartContext::systemObserverPrx
SystemObserverInterfacePrx systemObserverPrx
Definition: StatechartContext.h:187
armarx::Literal::createParameterList
static VarList createParameterList()
Static helper method to create an empty parameterlist.
Definition: Term.cpp:129
c
constexpr T c
Definition: UnscentedKalmanFilterTest.cpp:43
armarx::exceptions::local::eNullPointerException
Definition: Exception.h:42
armarx::Term
Definition: Term.h:111
armarx::StateUtility::setCounterEvent
ActionEventIdentifier setCounterEvent(int counterThreshold, const EventPtr &evt, int initialValue=0)
Definition: StateUtil.cpp:192
StateParameter.h
armarx::StateBase::eDefined
@ eDefined
Definition: StateBase.h:271
StatechartContext.h
armarx::StateUtility::ActionEventIdentifier::actionId
ChannelRefBasePtr actionId
Definition: StateUtil.h:57
IceInternal::Handle< Event >
StatechartEventDistributor.h
armarx::StateUtility::ActionEventIdentifier
Struct for the return value of setCounter/TimerEvent.
Definition: StateUtil.h:55
armarx::Event
An Event is used to communicate between e.g. condition handlers and statecharts.
Definition: Event.h:52
armarx::StateUtility::setTimeoutEvent
ActionEventIdentifier setTimeoutEvent(int timeoutDurationMs, const EventPtr &evt)
Utility function to start a timer on the systemObserver and register an event on the conditionHandler...
Definition: StateUtil.cpp:144
armarx::StatechartContext::eventDistributor
StatechartEventDistributorPtr eventDistributor
The EventListenerInterface instance, that receives events from observers and redirects them to the co...
Definition: StatechartContext.h:184
armarx::StatechartContext
This class contains a statechart and provides the interfaces to distributed components.
Definition: StatechartContext.h:89
armarx::flush
const LogSender::manipulator flush
Definition: LogSender.h:251
ARMARX_DEBUG
#define ARMARX_DEBUG
Definition: Logging.h:177
armarx::StateUtility::installCondition
ConditionIdentifier installCondition(const Term &condition, const EventPtr evt, const std::string &desc="")
Utility function to install a condition on the distributed conditionhandler.
Definition: StateUtil.cpp:97
armarx::StateUtility::ActionEventIdentifier::conditionId
ConditionIdentifier conditionId
Definition: StateUtil.h:58
armarx::StateUtility::removeCounterEvent
void removeCounterEvent(const ActionEventIdentifier &id)
Definition: StateUtil.cpp:226
armarx::StateUtility::sendEvent
void sendEvent(const EventPtr event, StateBasePtr eventProcessor=nullptr)
Function to send an event to a specific state from an onEnter()-function. Must not be called anywhere...
Definition: StateUtil.cpp:38
StatechartManager.h
ARMARX_INFO
#define ARMARX_INFO
Definition: Logging.h:174
armarx::StateUtility::createEvent
EventPtr createEvent()
Utility function to create a new Event.
Definition: StateUtil.h:64
armarx::ManagedIceObject::getName
std::string getName() const
Retrieve name of object.
Definition: ManagedIceObject.cpp:107
armarx::Literal
Definition: Term.h:208
StateUtil.h
armarx::StateBase::getStatePhase
StatePhase getStatePhase() const
Definition: StateBase.cpp:844
armarx::StateBase::eBreaking
@ eBreaking
Definition: StateBase.h:274
armarx::StateBase::__checkPhase
void __checkPhase(StatePhase allowedType, const char *functionName) const
Helper function for checking if a function was called in valid position of the statechart.
Definition: StateBase.cpp:134
armarx::StateBase::impl
std::unique_ptr< Impl > impl
Definition: StateBase.h:258
armarx::StateUtility::removeTimeoutEvent
void removeTimeoutEvent(const ActionEventIdentifier &id)
Definition: StateUtil.cpp:178
armarx
This file offers overloads of toIce() and fromIce() functions for STL container types.
Definition: ArmarXTimeserver.cpp:28
Exception.h
ChannelRef.h
armarx::Term::getImpl
TermImplPtr getImpl() const
Retrieve term implementation object as used in the ArmarX Framework in order to build distributed exp...
Definition: Term.cpp:103