State.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 "State.h"
25
26#include <mutex>
27
28#include <IceUtil/UUID.h>
29
30#include <SimoxUtility/algorithm/string/string_tools.h>
31
35
36#include "DynamicRemoteState.h" //needed for substate copying
37#include "RemoteState.h" //needed for substate copying
38#include "StateBaseImpl.h"
39#include "StateUtilFunctions.h"
40
41namespace armarx
42{
43 // TODO: This should probably be somewhere in SimoxUtility?
44 std::string
45 joinStrings(std::vector<std::string> const& input, std::string const& seperator)
46 {
47 return simox::alg::join(input, seperator);
48 }
49
51 {
55 };
56
57 State::State() : simpl(new Impl)
58 {
59 }
60
61 State::State(const State& source) :
62 IceUtil::Shared(),
63 Ice::Object(source),
64 StateIceBase(source),
65 Logging(source),
66 StateBase(source),
67 StateController(source),
68 StateUtility(source),
69 simpl(new Impl)
70 {
71 }
72
73 State&
74 State::operator=(const State& source)
75 {
76 assert(0);
78 StateBase::impl->context = source.impl->context;
79 return *this;
80 }
81
83 {
84 }
85
86 bool
88 {
89 __checkPhase(ePreDefined, __PRETTY_FUNCTION__);
90
91 return StateBase::init(context, manager);
92 }
93
94 unsigned int
96 {
97 return StateBase::impl->localUniqueId;
98 }
99
100 std::string
102 {
103 return globalStateIdentifier;
104 }
105
108 {
109 return StateBasePtr::dynamicCast(initState);
110 }
111
112 bool
114 {
115 return unbreakable;
116 }
117
118 StateParameterMap&
120 {
121 return outputParameters;
122 }
123
125 State::operator[](std::string const& stateName)
126 {
127 for (size_t i = 0; i < subStateList.size(); ++i)
128 {
129 if (stateName == StateBasePtr::dynamicCast(subStateList[i])->stateName ||
130 stateName == StateBasePtr::dynamicCast(subStateList[i])->globalStateIdentifier)
131 {
132 return StatePtr::dynamicCast(subStateList[i]);
133 }
134 }
135
136 return nullptr;
137 }
138
141 {
142
143 if (findSubstateByName(pNewState->getStateName()))
144 {
146 "There exists already a substate with name '" + stateName +
147 "' in this hierarchy level. In one hierarchy level (aka one substatelist) the "
148 "names must be unique.");
149 }
150
151 pNewState->__setParentState(this);
152 subStateList.push_back(pNewState);
153 pNewState->init(StateBase::impl->context, StateBase::impl->manager);
154 return pNewState;
155 }
156
158 State::addRemoteState(std::string stateName, std::string proxyName, std::string instanceName)
159 {
160 __checkPhase(eSubstatesDefinitions, __PRETTY_FUNCTION__);
161
162 if (instanceName.empty())
163 {
164 instanceName = stateName;
165 }
166
167 if (findSubstateByName(instanceName))
168 {
169 throw LocalException("There exists already a substate with name '" + instanceName +
170 "' in this hierarchy level. In one hierarchy level aka one "
171 "substatelist the names must be unique.");
172 }
173
174 RemoteStatePtr pNewState = new RemoteState();
175 pNewState->setStateName(instanceName);
176 pNewState->setStateClassName(stateName);
177 pNewState->__setParentState(this);
178 pNewState->setProxyName(proxyName);
179
180 subStateList.push_back(pNewState);
182
183 pNewState->StateBase::init(StateBase::impl->context, StateBase::impl->manager);
184
185 if (!ManagedIceObjectPtr::dynamicCast(pNewState))
186 {
188 "could not cast RemoteStatePtr to ManagedIceObjectPtr");
189 }
190
191 if (!context)
192 {
194 "statechart context ptr is NULL -> could not add state as component");
195 }
196 else
197 {
198
199 context->getArmarXManager()->addObject(ManagedIceObjectPtr::dynamicCast(pNewState),
200 false);
201
202 // ARMARX_DEBUG << "Waiting for RemoteState '" << pNewState->getName() << "'";
203
204 // pNewState->getObjectScheduler()->waitForObjectStateMinimum(eManagedIceObjectStarted, 500);
205
206 // ARMARX_DEBUG << "RemoteState '" << pNewState->getName() << "' started.";
207 }
208
209 return pNewState;
210 }
211
213 State::addDynamicRemoteState(std::string instanceName)
214 {
215 __checkPhase(eSubstatesDefinitions, __PRETTY_FUNCTION__);
216
217 if (findSubstateByName(instanceName))
218 {
219 throw LocalException("There exists already a substate with name '" + stateName +
220 "' in this hierarchy level. In one hierarchy level aka one "
221 "substatelist the names must be unique.");
222 }
223
224 RemoteStatePtr pNewState = new DynamicRemoteState();
225
226 pNewState->__setParentState(this);
227 pNewState->setStateName(instanceName);
228 subStateList.push_back(pNewState);
230
231 pNewState->StateBase::init(StateBase::impl->context, StateBase::impl->manager);
232
233 ARMARX_CHECK_EXPRESSION(ManagedIceObjectPtr::dynamicCast(pNewState));
235
236 context->getArmarXManager()->addObject(ManagedIceObjectPtr::dynamicCast(pNewState),
237 false,
238 pNewState->getName() + IceUtil::generateUUID());
239
240 ARMARX_DEBUG << "Waiting for RemoteState " << pNewState->getName();
241
242 pNewState->getObjectScheduler()->waitForObjectStateMinimum(eManagedIceObjectStarted);
243
244 ARMARX_DEBUG << "RemoteState " << pNewState->getName() << "started.";
245
246 return pNewState;
247 }
248
249 TransitionIceBase&
251 StateIceBasePtr sourceState,
252 StateIceBasePtr destinationState,
253 ParameterMappingIceBasePtr mappingToNextStatesInput,
254 ParameterMappingIceBasePtr mappingToParentStatesLocal,
255 ParameterMappingIceBasePtr mappingToParentStatesOutput)
256 {
257 __checkPhase(eSubstatesDefinitions, __PRETTY_FUNCTION__);
258 TransitionIceBase t;
259
260 assert(sourceState._ptr);
261 assert(destinationState._ptr);
262 t.sourceState = sourceState;
263 t.evt = createEvent(event->eventName, event->properties);
264 t.destinationState = destinationState;
265
266 if (mappingToNextStatesInput)
267 {
268 t.mappingToNextStatesInput = PMPtr::dynamicCast(mappingToNextStatesInput)->clone();
269 }
270
271 if (mappingToParentStatesLocal)
272 {
273 t.mappingToParentStatesLocal = PMPtr::dynamicCast(mappingToParentStatesLocal)->clone();
274 }
275
276 if (mappingToParentStatesOutput)
277 {
278 t.mappingToParentStatesOutput =
279 PMPtr::dynamicCast(mappingToParentStatesOutput)->clone();
280 }
281
284 "There already exists a transition on event '" + t.evt->eventName + "' from '" +
285 sourceState->stateName + "' to '" + destinationState->stateName + "'");
286
287 transitions.push_back(t);
288 return *transitions.rbegin();
289 }
290
291 void
292 State::inheritInputFromSubstate(std::string stateName)
293 {
294 __checkPhase(eParametersDefinitions, __PRETTY_FUNCTION__);
295 StateBase::impl->inputInheritance.push_back(stateName);
296 }
297
298 bool
299 State::addToInput(const std::string& key,
300 VariantTypeId type,
301 bool optional,
302 VariantPtr defaultValue)
303 {
304 __checkPhase(eParametersDefinitions, __PRETTY_FUNCTION__);
305 return addParameter(inputParameters, key, type, optional);
306 }
307
308 bool
309 State::addToInput(const std::string& key,
310 const ContainerType& type,
311 bool optional,
312 VariantContainerBasePtr defaultValue)
313 {
314 __checkPhase(eParametersDefinitions, __PRETTY_FUNCTION__);
315 return addParameterContainer(inputParameters, key, type, optional, defaultValue);
316 }
317
318 bool
319 State::addToOutput(const std::string& key, VariantTypeId type, bool optional)
320 {
321 __checkPhase(eParametersDefinitions, __PRETTY_FUNCTION__);
322 return addParameter(outputParameters, key, type, optional);
323 }
324
325 bool
326 State::addToOutput(const std::string& key, const ContainerType& type, bool optional)
327 {
328 __checkPhase(eParametersDefinitions, __PRETTY_FUNCTION__);
329
330 return addParameterContainer(outputParameters, key, type, optional);
331 }
332
333 bool
334 State::addToLocal(const std::string& key,
335 const ContainerType& type,
336 VariantContainerBasePtr defaultValue)
337 {
338 __checkPhase(eParametersDefinitions, __PRETTY_FUNCTION__);
339 std::unique_lock lock(simpl->localParameterMutex);
340
341 return addParameterContainer(localParameters, key, type, true, defaultValue);
342 }
343
344 bool
345 State::addToLocal(const std::string& key, VariantTypeId type, VariantPtr defaultValue)
346 {
347 __checkPhase(eParametersDefinitions, __PRETTY_FUNCTION__);
348 std::unique_lock lock(simpl->localParameterMutex);
349
350 return addParameter(localParameters, key, type, true, defaultValue);
351 }
352
355 {
356 __checkPhase(eSubstatesDefinitions, __PRETTY_FUNCTION__);
357
358 if (initialStateMapping)
359 {
360 this->initialStateMapping = initialStateMapping->clone();
361 }
362
363 if (!StateIceBasePtr::dynamicCast(initState))
364 {
365 throw LocalException("Couldnt cast initstate");
366 }
367
368 this->initState = initState;
369
370 return initState;
371 }
372
373 void
375 {
376 __checkPhase(eStatechartDefinitions, __PRETTY_FUNCTION__);
377 unbreakable = setUnbreakable;
378 }
379
380 void
381 State::setUseRunFunction(bool useRunFuntion)
382 {
383 StateBase::impl->__useRunFunction = useRunFuntion;
384 }
385
386 void
388 {
389 __checkPhase(eEntering, __PRETTY_FUNCTION__);
390 StateBase::impl->cancelEnteringSubstates = true;
391 }
392
393 void
394 State::setStateName(const std::string& newName)
395 {
396 stateName = newName;
397 }
398
399 void
400 State::setStateClassNameFromTypeName(const std::string& typeName)
401 {
402 std::string className = simox::alg::replace_all(typeName, ":", "_");
403 setStateClassName(className);
404 }
405
406 StateParameterMap
408 {
409 StateParameterMap result;
410 std::unique_lock lock(simpl->inputParameterMutex);
411 StateUtilFunctions::copyDictionary(inputParameters, result);
412 return result;
413 }
414
416 State::getInput(const std::string& key) const
417 {
418 __checkPhaseMin(eDefined, __PRETTY_FUNCTION__);
419 std::unique_lock lock(simpl->inputParameterMutex);
420
421
422 VariantPtr var;
423 getParameter(inputParameters, key, var);
424 return var->clone();
425 }
426
427 StateParameterMap&
429 {
430 return localParameters;
431 }
432
433 void
434 State::setInput(const std::string& key, const Variant& value)
435 {
436 __checkPhaseMin(eDefined, __PRETTY_FUNCTION__);
437 std::unique_lock lock(simpl->inputParameterMutex);
438
440 {
441 throw LocalException("Input parameter '" + key + "' in state '" + stateName +
442 "'' is already set and cannot be changed.");
443 }
444
445 setParameter(inputParameters, key, value);
446 }
447
448 void
449 State::setInput(std::string const& key, const VariantContainerBase& valueList)
450 {
451 __checkPhaseMin(eDefined, __PRETTY_FUNCTION__);
452 std::unique_lock lock(simpl->inputParameterMutex);
453
455 {
456 throw LocalException("Input parameter '" + key + "' in state '" + stateName +
457 "'' is already set and cannot be changed.");
458 }
459
460 setParameterContainer(inputParameters, key, valueList);
461 }
462
463 void
464 State::setLocal(std::string const& key, const Variant& value)
465 {
466 __checkPhaseMin(eDefined, __PRETTY_FUNCTION__);
467 std::unique_lock lock(simpl->localParameterMutex);
468
469 setParameter(getLocalParameters(), key, value);
470 }
471
472 void
473 State::setLocal(std::string const& key, const VariantContainerBase& valueList)
474 {
475 __checkPhaseMin(eDefined, __PRETTY_FUNCTION__);
476 std::unique_lock lock(simpl->localParameterMutex);
477
478 setParameterContainer(getLocalParameters(), key, valueList);
479 }
480
481 void
482 State::setOutput(std::string const& key, const Variant& value)
483 {
484 __checkPhaseMin(eDefined, __PRETTY_FUNCTION__);
485 std::unique_lock lock(simpl->outputParameterMutex);
486
487 setParameter(getOutputParameters(), key, value);
488 }
489
490 void
491 State::setOutput(std::string const& key, const VariantContainerBase& valueList)
492 {
493 __checkPhaseMin(eDefined, __PRETTY_FUNCTION__);
494 std::unique_lock lock(simpl->outputParameterMutex);
495
497 }
498
501 {
502 StateBasePtr result = new State(*this);
503 //result->deepCopy(shared_from_this,false);
504 return result;
505 }
506
509 {
510 StateBasePtr result = new State();
511 //result->deepCopy(shared_from_this,false);
512 return result;
513 }
514
515 // SingleTypeVariantListPtr
516 // State::getInputList(std::string key){
517 // __checkPhaseMin(eDefined, __PRETTY_FUNCTION__);
518 // std::unique_lock lock(inputParameterMutex);
519 // SingleTypeVariantListPtr varList;
520 // getParameter(inputParameters, key, varList);
521 // return varList;
522 // }
523
524 VariantContainerBasePtr
525 State::getLocalContainer(std::string const& key)
526 {
527 __checkPhaseMin(eDefined, __PRETTY_FUNCTION__);
528 std::unique_lock lock(simpl->localParameterMutex);
529
530 VariantContainerBasePtr varList;
531 getParameterContainer(localParameters, key, varList);
532 return VariantContainerBasePtr::dynamicCast(varList);
533 }
534
535 bool
536 State::isInputParameterSet(const std::string& key) const
537 {
538 return isParameterSet(inputParameters, key);
539 }
540
541 bool
542 State::isLocalParameterSet(const std::string& key) const
543 {
544 return isParameterSet(localParameters, key);
545 }
546
547 bool
548 State::isOutputParameterSet(const std::string& key) const
549 {
550 return isParameterSet(outputParameters, key);
551 }
552
553 template <>
555 State::addState<State>(std::string const& stateName)
556 {
557 __checkPhase(eSubstatesDefinitions, __PRETTY_FUNCTION__);
558
559 if (findSubstateByName(stateName))
560 {
562 "There already exists a substate with name '" + stateName +
563 "' in this hierarchy level. In one hierarchy level (aka one substatelist) the "
564 "names must be unique.");
565 }
566
567 if (stateName.empty())
568 {
569 throw exceptions::local::eStatechartLogicError("The statename must not be empty");
570 }
571
572 StatePtr pNewState = new State();
573 pNewState->stateName = stateName;
574 pNewState->__setParentState(this);
575 subStateList.push_back(pNewState);
577 pNewState->init(context, StateBase::impl->manager);
578
579 return pNewState;
580 }
581
582
583} // namespace armarx
Base Class for all Logging classes.
Definition Logging.h:240
ArmarXManagerPtr getArmarXManager() const
Returns the ArmarX manager used to add and remove components.
This class is the implementation of the Slice Definition of a state.
Definition StateBase.h:60
void getParameterContainer(const StateParameterMap &paramMap, const std::string &key, VariantContainerBasePtr &valueContainer) const
StateBase & operator=(const StateBase &source)
Definition StateBase.cpp:97
StateBasePtr findSubstateByName(const std::string &substateName)
Utility function to find a substate of this state by the name.
bool isParameterSet(const StateParameterMap &paramMap, const std::string &key) const
void setParameter(StateParameterMap &paramMap, const std::string &key, const Variant &variant)
void __checkPhase(StatePhase allowedType, const char *functionName) const
Helper function for checking if a function was called in valid position of the statechart.
void __checkPhaseMin(StatePhase allowedType, const char *functionName) const
bool addParameterContainer(StateParameterMap &paramMap, const std::string &key, const ContainerType &containerType, bool optional, VariantContainerBasePtr defaultValue=VariantContainerBasePtr()) const
void setStateClassName(std::string className)
setStateClassName() sets the string, that contains a stringrepresentation of this class....
void setParameterContainer(StateParameterMap &paramMap, const std::string &key, const VariantContainerBasePtr &valueContainer)
bool addParameter(StateParameterMap &paramMap, const std::string &key, VariantTypeId type, bool optional, VariantPtr defaultValue=VariantPtr()) const
bool init(StatechartContextInterface *context, StatechartManager *manager)
Function to initialize this state. Must be called in the highest level of the hierarchy - and only th...
std::unique_ptr< Impl > impl
Definition StateBase.h:289
StatePhase getStatePhase() const
void getParameter(const StateParameterMap &paramMap, const std::string &key, VariantPtr &value) const
ContextType * getContext() const
Definition StateBase.h:71
The StateController class processes events and controls the statechart flow.
bool __checkExistenceOfTransition(const TransitionIceBase &transition)
This class provides utility functions for statechart-implementing-users to communicate with other dis...
Definition StateUtil.h:47
EventPtr createEvent()
Utility function to create a new Event.
Definition StateUtil.h:63
Class that offers the main functionality needed to create a statechart.
Definition State.h:54
void setStateName(const std::string &newName)
Definition State.cpp:394
StateParameterMap getInputParameters() override
Returns a new copy of the inputparameters-dictionary, so that the caller cannot modify them (const wo...
Definition State.cpp:407
~State() override
Definition State.cpp:82
StateParameterMap & getLocalParameters()
Getter for the local parameter map.
Definition State.cpp:428
bool isUnbreakable() const
Definition State.cpp:113
void setOutput(std::string const &key, const Variant &value)
setOuput() sets an output parameter of this state.
Definition State.cpp:482
StateBasePtr addState(StateBasePtr pNewState)
Definition State.cpp:140
bool isOutputParameterSet(const std::string &key) const
Definition State.cpp:548
StateBasePtr clone() const override
Generates a new copy of this state with the same statename, substates, transitions,...
Definition State.cpp:500
bool addToInput(const std::string &key, const ContainerType &type, bool optional, VariantContainerBasePtr defaultValue=VariantContainerBasePtr())
Adds a key,type-pair to the input parameters.
Definition State.cpp:309
std::enable_if_t< std::is_base_of_v< VariantDataClass, T >, IceInternal::Handle< T > > getInput(const std::string &key) const
getInput can be used to access a specific input parameter.
Definition State.h:620
StateBasePtr setInitState(StateBasePtr initState, ParameterMappingPtr initialStateMapping=ParameterMappingPtr())
Sets the initial substate of this state.
Definition State.cpp:354
bool isLocalParameterSet(const std::string &key) const
Definition State.cpp:542
TransitionIceBase & addTransition(EventPtr event, StateIceBasePtr sourceState, StateIceBasePtr destinationState, ParameterMappingIceBasePtr mappingToNextStatesInput=nullptr, ParameterMappingIceBasePtr mappingToParentStatesLocal=nullptr, ParameterMappingIceBasePtr mappingToParentStatesOutput=nullptr)
Definition State.cpp:250
void setUseRunFunction(bool useRunFuntion)
setUseRunFunction can be used to configurate whether the thread with the async.
Definition State.cpp:381
State & operator=(const State &source)
Definition State.cpp:74
VariantContainerBasePtr getLocalContainer(std::string const &key)
Definition State.cpp:525
std::string getGlobalIdString() const
Getter for the global state identifier string.
Definition State.cpp:101
StateBasePtr createEmptyCopy() const override
Generates a new copy of this state with the same overidden functions. stateName, substates,...
Definition State.cpp:508
bool addToOutput(const std::string &key, VariantTypeId type, bool optional)
Adds a key,type-pair to the output parameters.
Definition State.cpp:319
void setStateClassNameFromTypeName(const std::string &typeName)
Definition State.cpp:400
virtual RemoteStatePtr addDynamicRemoteState(std::string instanceName)
Function to add a new dynamic remote substate to this state.
Definition State.cpp:213
void setUnbreakable(bool setUnbreakable=true)
With this function the state can be made unbreakable.
Definition State.cpp:374
StatePtr operator[](std::string const &stateName)
Function to jump directly into a state. Should only be called for statemachine-debugging.
Definition State.cpp:125
virtual RemoteStatePtr addRemoteState(std::string stateName, std::string proxyName, std::string instanceName="")
Function to add a new remote substate to this state.
Definition State.cpp:158
bool init(StatechartContextInterface *context, StatechartManager *manager)
Function to initialize this state. Must be called in the highest level of the hierarchy - and only th...
Definition State.cpp:87
void cancelSubstates()
Use this function in the onEnter() function, if you want to avoid that the substates (i....
Definition State.cpp:387
bool addToLocal(const std::string &key, VariantTypeId type, VariantPtr defaultValue=VariantPtr())
Adds a key,type-pair to the local parameters.
Definition State.cpp:345
bool isInputParameterSet(const std::string &key) const
Checks whether a given input parameter is set or not.
Definition State.cpp:536
void inheritInputFromSubstate(std::string stateName)
Definition State.cpp:292
void setLocal(std::string const &key, const Variant &value)
setLocal() sets a local parameter.
Definition State.cpp:464
void setInput(std::string const &key, const Variant &value)
setInput() sets an input parameter.
Definition State.cpp:434
unsigned int getId() const
Returns an id to this state, that is guaranteed to be unique in this process.
Definition State.cpp:95
StateBasePtr getInitState() const
Getter for the initial state. The initial state is automatically entered, when this state is entered.
Definition State.cpp:107
StateParameterMap & getOutputParameters() override
getter function to get the map of output parameters
Definition State.cpp:119
This class contains a statechart and provides the interfaces to distributed components.
The Variant class is described here: Variants.
Definition Variant.h:224
#define ARMARX_CHECK_EXPRESSION(expression)
This macro evaluates the expression and if it turns out to be false it will throw an ExpressionExcept...
#define ARMARX_DEBUG
The logging level for output that is only interesting while debugging.
Definition Logging.h:184
void copyDictionary(const StringVariantContainerBaseMap &source, StringVariantContainerBaseMap &destination)
Clears the destination map and copies the parameters of the source in it.
This file offers overloads of toIce() and fromIce() functions for STL container types.
IceInternal::Handle< RemoteState > RemoteStatePtr
Definition RemoteState.h:47
std::string joinStrings(std::vector< std::string > const &input, std::string const &seperator)
Definition State.cpp:45
IceInternal::Handle< State > StatePtr
Definition State.h:44
IceInternal::Handle< Variant > VariantPtr
Definition Variant.h:41
Ice::Int VariantTypeId
Definition Variant.h:43
IceInternal::Handle< Event > EventPtr
Typedef of EventPtr as IceInternal::Handle<Event> for convenience.
Definition Event.h:40
IceInternal::Handle< StateBase > StateBasePtr
Definition StateBase.h:49
IceInternal::Handle< ParameterMapping > ParameterMappingPtr
std::mutex localParameterMutex
Definition State.cpp:53
std::mutex outputParameterMutex
Definition State.cpp:54
std::mutex inputParameterMutex
Definition State.cpp:52