41#include <boost/regex.hpp>
55 impl->visitCounter = 0;
56 impl->context =
nullptr;
57 impl->manager =
nullptr;
59 setTag(std::string(
"Statechart"));
61 initialStateMapping =
nullptr;
67 (*
impl->stateInstancesPtr)[
impl->localUniqueId] =
this;
77 impl->statePhase = source.impl->statePhase;
78 impl->__useRunFunction =
true;
79 impl->__parentState =
nullptr;
80 impl->visitCounter = 0;
81 impl->context =
nullptr;
82 impl->manager =
nullptr;
84 setTag(std::string(
"Statechart"));
85 initialStateMapping =
nullptr;
93 (*
impl->stateInstancesPtr)[
impl->localUniqueId] =
this;
107 for (
unsigned int i = 0; i < subStateList.size(); i++)
109 RemoteStatePtr remoteStatePtr = RemoteStatePtr::dynamicCast(subStateList.at(i));
111 if (remoteStatePtr &&
113 ->getArmarXManager())
119 remoteStatePtr->getArmarXManager()->removeObjectNonBlocking(
120 remoteStatePtr->getName());
131 impl->stateInstancesPtr->erase(
impl->localUniqueId);
144 hint =
"This function must be called in defineSubstates().";
148 hint =
"This function must be called in defineParameters().";
153 hint =
"This function must be called in defineState().";
158 hint =
"This function must be called in onEnter().";
166 std::stringstream typeStr;
168 throw LocalException(
169 "It is not allowed to call the function " + std::string(functionName) +
170 " here! (Current Phase/Allowed Phase): " + typeStr.str() +
") " + hint);
176 const char* functionName)
const
178 if (!std::any_of(allowedTypes.begin(),
180 [&](
StatePhase value) { return value == getStatePhase(); }))
184 for (
auto& allowedType : allowedTypes)
193 hint +=
"defineSubstates()";
197 hint +=
"defineParameters()";
202 hint +=
"defineState()";
218 hint =
"\nThis function must be called in " + hint;
221 std::stringstream typeStr;
223 throw LocalException(
"It is not allowed to call the function " +
224 std::string(functionName) +
225 " here! (Current Phase: " + typeStr.str() +
") " + hint);
234 std::stringstream typeStr;
236 throw LocalException(
237 "It is not allowed to call the function " + std::string(functionName) +
238 " here! (Current Phase/min. Allowed Phase): " + typeStr.str() +
") ");
254 impl->__parentState = parentState;
261 if (
impl->__parentState)
263 if (!
impl->__parentState->globalStateIdentifier.empty())
265 globalStateIdentifier =
266 impl->__parentState->getGlobalHierarchyString() +
"->" + stateName;
270 globalStateIdentifier =
276 globalStateIdentifier = stateName;
285 for (
unsigned int i = 0; i < subStateList.size(); i++)
287 StateBasePtr::dynamicCast(subStateList.at(i))->__updateGlobalStateIdRecursive();
295 initialized = enable;
296 impl->initCondition.notify_all();
302 if (subStateList.size() > 0)
313 boost::recursive_mutex::scoped_lock lock(
impl->__processEventMutex);
315 if (activeSubstate._ptr)
328 if (!sourceState.initialized)
339 if (sourceState.initialStateMapping)
341 initialStateMapping = PMPtr::dynamicCast(sourceState.initialStateMapping)->clone();
344 impl->__useRunFunction = sourceState.
impl->__useRunFunction;
346 impl->statePhase = sourceState.
impl->statePhase;
347 impl->__parentState =
nullptr;
348 activeSubstate =
nullptr;
350 impl->manager = sourceState.
impl->manager;
351 impl->cancelEnteringSubstates = sourceState.
impl->cancelEnteringSubstates;
353 impl->triggeredEndstateEvent = sourceState.
impl->triggeredEndstateEvent;
355 if (sourceState.subStateList.size() > 0)
357 for (
unsigned int i = 0; i < sourceState.subStateList.size(); i++)
360 StateBasePtr::dynamicCast(sourceState.subStateList.at(i))->clone();
361 subStateList.at(i) = curSubstate;
363 if (!curSubstate._ptr)
365 throw LocalException(
366 "StatePtrePtr::dynamicCast failed in deepCopy() in file " +
367 std::string(__FILE__));
370 curSubstate->impl->__parentState =
this;
372 if (sourceState.initState._ptr == sourceState.subStateList.at(i)._ptr)
374 initState = curSubstate;
377 if (sourceState.activeSubstate._ptr == sourceState.subStateList.at(i)._ptr)
379 activeSubstate = curSubstate;
384 for (
unsigned int j = 0; j < sourceState.transitions.size(); j++)
386 if (sourceState.transitions[j].mappingToNextStatesInput)
388 transitions[j].mappingToNextStatesInput =
390 sourceState.transitions[j].mappingToNextStatesInput)
394 if (sourceState.transitions[j].mappingToParentStatesLocal)
396 transitions[j].mappingToParentStatesLocal =
398 sourceState.transitions[j].mappingToParentStatesLocal)
402 if (sourceState.transitions[j].mappingToParentStatesOutput)
404 transitions[j].mappingToParentStatesOutput =
406 sourceState.transitions[j].mappingToParentStatesOutput)
410 if (sourceState.transitions[j].sourceState._ptr ==
411 sourceState.subStateList.at(i)._ptr)
413 transitions[j].sourceState = curSubstate;
416 if (sourceState.transitions[j].destinationState._ptr ==
417 sourceState.subStateList.at(i)._ptr)
419 transitions[j].destinationState = curSubstate;
426 activeSubstate =
nullptr;
445 ARMARX_WARNING <<
"The StatechartContext should not be null" << std::endl;
450 ARMARX_WARNING <<
"The StatechartManager should not be null" << std::endl;
453 this->
impl->manager = manager;
454 this->
impl->context = context;
459 setTag(
"State: " + stateName);
471 if (subStateList.size() > 0)
489 stateName +
"' was not set!");
493 activeSubstate =
nullptr;
501 if (!
impl->context && checkNULL)
506 return impl->context;
523 impl->__useRunFunction =
535 this->
impl->context = context;
541 return outputParameters;
553 return impl->localUniqueId;
559 return stateClassName;
565 StateIceBase* curParent =
impl->__parentState;
570 result = curParent->stateName +
"->" + result;
571 curParent = StateBasePtr::dynamicCast(curParent)->impl->__parentState;
582 return globalStateIdentifier;
593 if (!
impl->initCondition.timed_wait(lock,
594 boost::posix_time::milliseconds(timeoutMS)))
601 impl->initCondition.wait(lock);
616 const std::string& key,
624 VariantContainerBasePtr variantContainer =
626 VariantContainerBasePtr defaultContainer;
630 const auto&
data = *defaultValue;
635 paramMap, key, *variantContainer->getContainerType(), optional, defaultContainer);
640 const std::string& key,
641 const ContainerType& containerType,
643 VariantContainerBasePtr defaultValue)
const
647 throw LocalException(
"The key-string of a parameter must not be empty.");
650 const boost::regex e(
"^([a-zA-Z0-9_\\.]+)$");
652 if (!boost::regex_match(key, e))
654 throw LocalException(
"Invalid character in new key '" + key +
655 "'. Only a-zA-Z0-9_ are allowed.");
669 if (containerType.subType)
684 param->value->setContainerType(containerType.clone());
688 param->defaultValue = defaultValue->cloneContainer();
691 param->optionalParam = optional;
694 if (paramMap.find(key) != paramMap.end())
699 paramMap[key] = param;
705 const std::string& key,
708 StateParameterMap::iterator it = paramMap.find( key);
710 if (it == paramMap.end())
717 if ((it->second->value->getContainerType()->typeId !=
720 "Cannot assign the parameter '" + key +
"' with type '" +
722 it->second->value->getContainerType()->typeId +
")!");
725 it->second->set =
true;
730 const std::string& key,
731 const VariantContainerBasePtr& valueContainer)
738 const std::string& key,
739 const VariantContainerBase& valueContainer)
741 StateParameterMap::iterator it = paramMap.find( key);
743 if (it == paramMap.end())
748 if (valueContainer.getSize() > 0 &&
750 .find(::armarx::InvalidVariantData::ice_staticId()) == std::string::npos)
753 valueContainer.getContainerType()))
755 "Cannot assign the parameter container '" + key +
"' with type '" +
757 "' to another type of container (" +
761 auto type = it->second->value->getContainerType();
762 it->second->value = valueContainer.cloneContainer();
763 it->second->value->setContainerType(type);
764 it->second->set =
true;
769 const std::string& key,
770 VariantContainerBasePtr& valueContainer)
const
772 StateParameterMap::const_iterator it = paramMap.find(key);
774 if (it == paramMap.end())
779 if (!it->second->set)
781 throw LocalException(
"Requested parameter '" + key +
"' was not set in state " +
785 valueContainer = it->second->value;
791 StateParameterMap::const_iterator it = paramMap.find(key);
793 if (it == paramMap.end())
795 throw LocalException(
"Requested parameter '" + key +
"' not found in state " +
799 return it->second->set;
804 const std::string& key)
const
806 std::string parameters;
808 for (StateParameterMap::const_iterator it = paramMap.begin(); it != paramMap.end();
809 it++, parameters +=
",\n")
817 stateName, key,
"Available parameters:\n" + parameters);
823 for (
size_t i = 0; i <
impl->inputInheritance.size(); i++)
829 StateParameterMap substateInput = state->getInputParameters();
831 for (StateParameterMap::iterator it = substateInput.begin();
832 it != substateInput.end();
835 StateParameterIceBasePtr param = it->second;
837 impl->inputInheritance.at(i) +
"." + it->first,
838 *param->value->getContainerType(),
839 param->optionalParam);
848 for (StateParameterMap::iterator i = inputParameters.begin(); i != inputParameters.end();
851 StateParameterIceBasePtr p = i->second;
855 p->value = p->defaultValue->cloneContainer();
864 for (
unsigned int i = 0; i < subStateList.size(); i++)
866 if (StateBasePtr::dynamicCast(subStateList.at(i))->stateName == substateName)
868 return StateBasePtr::dynamicCast(subStateList.at(i));
877 const std::string& key,
880 StateParameterMap::const_iterator it = paramMap.find( key);
882 if (it == paramMap.end())
887 if (!it->second->set)
889 throw LocalException(
"Requested parameter '" + key +
"' was not set in state " +
896 throw InvalidTypeException(
"Parameter '" + key +
"' is not a single variant!");
906 stateClassName = className;
912 for (
auto s : subStateList)
915 state->refetchSubstates();
922 return impl->triggeredEndstateEvent;
929 return impl->statePhase;
936 impl->statePhase = newPhase;
939 StringVariantContainerBaseMap
943 StringVariantContainerBaseMap inputSetValues =
945 result.insert(inputSetValues.begin(), inputSetValues.end());
949 std::vector<StateBasePtr>
954 throw LocalException(
"The toplevelState must not be NULL");
957 std::vector<StateBasePtr> activeStates;
959 boost::recursive_mutex::scoped_lock lock(toplevelState->impl->__processEventMutex);
961 while (activeState->activeSubstate)
963 activeState = StateBasePtr::dynamicCast(activeState->activeSubstate);
966 activeStates.push_back(activeState);
973 impl->cancelEnteringSubstates =
false;
977 eventsDelayed =
false;
978 greedyInputDictionary =
false;
980 inputParameters.clear();
981 localParameters.clear();
982 outputParameters.clear();
983 subStateList.clear();
985 initialStateMapping =
nullptr;
987 activeSubstate =
nullptr;
988 impl->__parentState =
nullptr;
989 impl->triggeredEndstateEvent =
nullptr;
void setTag(const LogTag &tag)
The SingleVariant class is required to store single Variant instances in VariantContainer subclasses.
This class is the implementation of the Slice Definition of a state.
void getParameterContainer(const StateParameterMap ¶mMap, const std::string &key, VariantContainerBasePtr &valueContainer) const
virtual void defineState()
Virtual function, in which this state can be configured.
StateBase & operator=(const StateBase &source)
virtual void run()
Virtual function, that can be reimplemented to calculate complex operations.
virtual bool isInitialized() const
Returns the status of this state. Only if a state is initialized, it can be used.
StateBasePtr findSubstateByName(const std::string &substateName)
Utility function to find a substate of this state by the name.
void __updateGlobalStateId()
bool isParameterSet(const StateParameterMap ¶mMap, const std::string &key) const
void setParameter(StateParameterMap ¶mMap, const std::string &key, const Variant &variant)
virtual bool __hasActiveSubstate()
Virtual function to indicate wheter a state has an active substate or not. To be overridden by Remote...
static std::vector< StateBasePtr > GetActiveStateLeafs(StateBasePtr toplevelState)
void __setParentState(StateBase *parentState)
virtual bool waitForInitialization(int timeoutMS=-1) const
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
virtual void onBreak()
Virtual function, in which the behaviour of state is defined, when it is abnormally exited....
void setContext(StatechartContextInterface *context)
void inheritInputParameters()
void setStatePhase(StatePhase newPhase)
bool addParameterContainer(StateParameterMap ¶mMap, const std::string &key, const ContainerType &containerType, bool optional, VariantContainerBasePtr defaultValue=VariantContainerBasePtr()) const
EventPtr getTriggeredEndstateEvent() const
This function returns the event that was triggered by entering an endstate.
void setStateClassName(std::string className)
setStateClassName() sets the string, that contains a stringrepresentation of this class....
virtual StateParameterMap & getOutputParameters()
const std::string & getStateClassName() const
virtual void __updateGlobalStateIdRecursive()
virtual void defineParameters()
Virtual function, in which input/local/output parameters can be specified.
void __copyDefaultValuesToInput()
virtual void defineSubstates()
Virtual function, in which substates, transition and mappings can be added.
void setParameterContainer(StateParameterMap ¶mMap, const std::string &key, const VariantContainerBasePtr &valueContainer)
virtual void deepCopy(const StateBase &sourceState, bool reset=true)
Function to copy the states with all it substates and transitions.
virtual void onEnter()
Virtual function, in which the behaviour of state is defined, when it is entered. Can be overridden,...
bool addParameter(StateParameterMap ¶mMap, const std::string &key, VariantTypeId type, bool optional, VariantPtr defaultValue=VariantPtr()) const
std::string getLocalHierarchyString() const
Function to get a string that contains als parent states and this state. (e.g. "Robot->Functional->Id...
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
StatePhase
enum that specifies the phase in which the state is currently in used to control the usage of state-f...
StatechartContextInterface * getContext(bool checkNULL=true) const
StatePhase getStatePhase() const
std::string getGlobalHierarchyString() const
virtual bool __hasSubstates()
Virtual function to indicate wheter a state has substates or not. To be overridden by RemoteState to ...
StringVariantContainerBaseMap __getSetInputAndLocalParameters() const
Combines both maps to one map and returns a new map of only the set parameters.
void __throwUnknownParameter(const StateParameterMap ¶mMap, const std::string &key) const
Ice::Int getLocalUniqueId() const
void reset()
Function to reset the state: clear name, clear substatesList, clear transition etc.
void getParameter(const StateParameterMap ¶mMap, const std::string &key, VariantPtr &value) const
virtual void refetchSubstates()
This functions updates the substates.
ContextType * getContext() const
std::string getStateName() const
getStateName
void setInitialized(bool enable)
virtual void onExit()
Virtual function, in which the behaviour of state is defined, when it is exited. Can be overridden,...
static StateParameterPtr create()
static std::string allTypesToString(const ContainerTypePtr &type)
static bool compare(const ContainerTypePtr &type1, const ContainerTypePtr &secondType)
The Variant class is described here: Variants.
VariantTypeId getType(const Ice::Current &c=Ice::emptyCurrent) const override
Return the Variant's internal type.
static int hashTypeName(const std::string &typeName)
Compute and return a hash value for a given type name.
static std::string typeToString(VariantTypeId typeId)
Return the name of the registered type typeId.
void setType(VariantTypeId typeId, const Ice::Current &c=Ice::emptyCurrent) override
Sets the Variant's type to typeId.
#define ARMARX_WARNING
The logging level for unexpected behaviour, but not a serious problem.
Mutex::scoped_lock ScopedLock
boost::unique_lock< HiddenTimedMutex > ScopedLock
void copyDictionary(const StringVariantContainerBaseMap &source, StringVariantContainerBaseMap &destination)
Clears the destination map and copies the parameters of the source in it.
StringVariantContainerBaseMap getSetValues(const StateParameterMap ¶mMap)
This file offers overloads of toIce() and fromIce() functions for STL container types.
IceInternal::Handle< RemoteState > RemoteStatePtr
IceInternal::Handle< StateParameter > StateParameterPtr
IceInternal::Handle< SingleVariant > SingleVariantPtr
IceInternal::Handle< Variant > VariantPtr
IceInternal::Handle< Event > EventPtr
Typedef of EventPtr as IceInternal::Handle<Event> for convenience.
IceInternal::Handle< StateBase > StateBasePtr
static int __LocalIdCounter
Unique Identifier counter for this process for identifing states.
std::map< int, StateBase * > StateInstanceMap
std::shared_ptr< StateInstanceMap > StateInstanceMapPtr
static StateInstanceMapPtr StateInstances
Static map that contains all the states that are alive in this process.
static HiddenTimedMutex * __StateInstancesMutex