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