|
Programming complex behavior or event-dependent processes in ArmarX is done with Statecharts. For more details refer to Statechart. More...
Data Structures | |
class | DynamicRemoteState |
DynamicRemoteStates can be used to connect to remote statecharts dynamically at runtime. More... | |
class | FinalStateBase< EventType, StateType > |
class | ParameterMapping |
This class maps parameters from several source dictionaries to one input dictionary. The mapping depends on an instance of ParameterMappingIceBase, in which the mapping is specified. More... | |
class | RemoteState |
This Statetype is used to create a state instance that represents a state that is located in another application. It is added in a parent state by calling State::addRemoteState(statename, proxyname). If a RemoteState is entered for the first time, it creates automatically a new instance at the remotely located RemoteStateOfferer that contains the real state. The RemoteState receives upon creation of the new real-state instance an unique id of this state for further communication. This id is automatically used in the onBreak- and onExit-functions, to communicate with the correct state. Except the state creation-call (which should return immediately) all remote procedure calls are async calls. More... | |
class | RemoteStateOfferer< ContextType > |
Class that holds states, which offer functionality for other states over Ice. More... | |
class | RemoteStateWrapper |
class | State |
class | StateBase |
class | StatechartContext |
This class contains a statechart and provides the interfaces to distributed components. More... | |
class | StateController |
class | StateTemplate |
class | StateUtility |
Modules | |
XMLStateComponent | |
Typedefs | |
using | CounterState = CounterStateTemplate< EvCounterNotFulfilled, EvCounterFulfilled > |
CounterState is a typedef for the CounterStateTemplate, that uses the events EvCounterNotFulfilled and EvCounterFulfilled. More... | |
using | FailureState = FinalState< Failure > |
using | SuccessState = FinalState< Success > |
Programming complex behavior or event-dependent processes in ArmarX is done with Statecharts. For more details refer to Statechart.
\page Statechart ArmarX Statecharts \brief Programming complex behavior or event-dependent processes in ArmarX is done with Statecharts. \tableofcontents Statecharts are a variant of Finite-StateMachines to model complex behavior. The main usecase of statecharts in ArmarX is to program new robot behaviors, but they can also be used for any other purpose that is state-dependent and/or require event-dependent processing. To ease the process of programming robot behaviors ArmarX offers a graphical tool for creating these behaviors: The \ref armarx::StatechartEditorController. With this editor it is possible to easily design hierarchical compositions of statecharts with a defined data flow. For a detailed tutorial of the statechart editor refer to \ref ArmarXCore-Tutorials-sce "Statechart editor basic tutorial". A detailed explanation of ArmarX Statecharts can be found in the publication:<br/> M. Wächter, S. Ottenhaus, M. Kröhnert, N. Vahrenkamp and T. Asfour (2016), *The ArmarX Statechart Concept: Graphical Programming of Robot Behaviour*, Front. Robot. AI 3:33. <a href="http://journal.frontiersin.org/article/10.3389/frobt.2016.00033/full">[DOI]</a> \section StatechartConcept Statechart concept in ArmarX Complex robot behaviors are usually compositions of smaller operations, each of which modifying the states of the robot and the environment. Based on this principle, robot operations in ArmarX are arranged as hierarchical, distributed, and orthogonal statecharts based on Harel's approach 1987. Statecharts are widely used in robotics to control the behavior on a high level. The well-known RDE ROS employs statecharts that are similar to the ones in ArmarX in terms of data flow. However, the two approaches differ in the way transitions are triggered. In many aspects the statecharts of ArmarX are similar to rFSM from Orocos. Nevertheless, the statecharts in Orocos focus on the coordination of components, while our approach concentrates on the disclosure of the internal state. The key principles of the ArmarX statecharts are: **modularity**, **reusability**, **runtime reconfigurability**, **decentralization** and **state-disclosure**. - *Modularity* is an inherent characteristic of our statecharts due to the definition of states as individual objects with specified input and output. - *Reusability* is ensured since states are composites, i.e. every state can be used as a substate in any other state. Furthermore, states offer a generic interface for communication. - *Runtime reconfigurability* means that a statechart can be defined in configuration files that allows changing its structure at runtime completely. - *Decentralization* means that a statechart does not need to entirely reside in one process, but can be distributed over several components. This allows load balancing and increases robustness. A crashed distributed state component would not crash the whole statechart, but would just create an event for higher layers, indicating that this specific component has failed. - *State-disclosure* means that the current state and all its parameters can be inspected and logged at runtime. \section Structure Structure of a statechart A statechart in ArmarX is a normal state itself. It contains - the statename, unique in its hierarchy level - an id, that is unique in its process - *onEnter()*, *onBreak()* and *onExit()*-functions (synchronous) and *run()* (asynchronous), that provide the functionality of the state (*optional*) - **Substates** (instances of states) (*optional*) - **Transitions** (table of conditional links between states) (*optional*) - **Input parameters**, which are set by the system or parentstates before the state is entered (*read-only* set of parameters that this state requires) (*optional*) - **Local parameters**, which can be read and written by the user to pass self-calulated data down to substates (*optional*) - **Output parameters**, which should contain the result of the state and are to be set by the statechart-designer (set of result parameters, that this state offers)(*optional*) So a statechart in ArmarX consists of a toplevel state, that is the statechart itself. This state has a set of substates, which can have substates as well and so on.<br/> Since a statechart is a state itself, it can be used by other state as well. The other state just needs to know what input and output parameters the statechart expects/offers and has to provide the inputparameters. \section DesigningAStatechart Creation of statecharts ArmarX provides means for designing statecharts textually and \ref armarx::StatechartEditorGuiPlugin "graphically" with the possibility to include user-defined code for custom operations. \subsection ProgrammingStateharts Textually programming a statechart This type of designing a statechart is the deprecated way. It is still possible, but it is takes much longer and more complex to understand. The implementation is based on inheritance from base classes, i.e. a state needs to be derived from StateTemplate <myStateType>, where myStateType is the new State-class itself.<br/> To add functionality to a new, derived state, one has to implement the functions StateBase::defineState(), StateBase::defineParameters(), StateBase::defineSubstates(), StateBase::onEnter(), StateBase::onExit(), StateBase::onBreak(), StateBase::run(). But it is not required to implement all these functions, just these that are needed for the purpose of the state. So, a basic statechart looks like this: \include StatechartExample.dox \image html ArmarX-Statechart-SimpleExample.png "Visualization of the statechart example" More and complete examples can be found in ${ArmarXCore_DIR}/../source/ArmarXCore/applications/StateChartExamples. Examples: - InstallConditionExample - RemoteAccessableStateExample - StatechartPerformanceTest - StateParameterExample - TimeoutExample For more information on the functions see the infile-documentation. \section Eventprocessing Events are the triggers for transitions. Events are triggered on fulfillment of conditions, which the same state installed before. And since states should be modular and reuseable they dont know anything about other states on the same hierarchy level or higher. Therefore events are sent to the statechart and then processed by the state, where the transition is located. Events are <b>not</b> processed by the state, that the transition is affecting.<br/> Events always have a specific receiver state, for which the event was meant, so that it is easier to identify if an unexpected was received and which state it should originally reach.<br/> If there is a state S with two substates A and B and a transition from A to B like this: \verbatim S / \ A-->B
An event that triggers the transition from A to B must have the eventReceiver set to A and be send to state S. State S then calls the onExit()-function of state A, applies the parameter-mapping, then calls onEnter() of state B. But usually the statechart-implementing-user does not need to know all these eventprocessing details. The installed events (e.g. with installCondition, sendEvent) are automatically sent to the correct state.
The specification of the dataflow between states is an important part in the design of the ArmarX statecharts. It is possible to specify which parameters are transferred when an active state is changed. Every state has an input-, local- and an output-parametermap. These maps are string->Variant maps, that means a string is associated with a variable type, that can contain an int, a float, a string etc.
The input-parametermap is filled before the onEnter()-function is called. This happens automatically during the transition.
The transition-class has a member where the user can specify how the source-parameters should be mapped onto the input-parametermap of the next state (see ParameterMapping) or via the transition dialog in the Statechart Editor. As sources for the input parameters the following sources are available:
ArmarX Statecharts offer the possibility to provide different parameter sets for different robots or different setups. These profiles are defined in a hierarchical way, which means that values of lower priority profiles (lowest is Root) are overwritten by values of a profile with a higher priority.
A profile encapsulates default parameter values for a well-defined use case configuration of a statechart while maintaining the same functionality for all statecharts of the hierarchy. For example, a statechart that is used on a simulated robot might need different default parameter values than the same statechart that is deployed on a real robot. This notion helps with preventing duplicates of functionally equal statecharts while still allowing individual configurations for different use cases. The profiles are ordered in a hierarchy to enable inheritance of parameter values.
Additionally, the profiles offer to specify configuration values for the whole statechart group like proxy names, e.g. the KinematicUnit. These differ usually from robot to robot, e.g. Armar3KinematicUnit, and need to be specified for each robot seperately. These configuration values can be specified in the Statechart Editor within in the statechart group properties.
Usually there is a hierarchy for each type of a robot, e.g. for Armar3 we use the following profile hierarchy:
Any profile here can be specified to be used, even intermediate profiles. If Armar3Real is selected in the statechart configuration and for one parameter there is no value given for Armar3Real, the hierarchy is traversed until a parameter is found. If no profile is specified, the Root profile is used.
It is possible to call external components inside the statecharts. Since statecharts on their own are not particularly useful for robotics, they need to communicate with the other components, i.e. the robot components. To this end, each state has a pointer to its StatechartContext, which contains Ice proxies to other components. In case of an XML state created with the StatechartEditor these contexts can be generated from the GUI automatically.
State usually react on events and trigger transitions into other states based on these events. These events can be fired if an condition is fulfilled. To specify such a condition and connect it to an event you need to use the installCondition function inside your onEnter or onRun function and construct a condition as described here.
In a normal application the maincomponent derives from component. To offer functionality over Ice for other components/statecharts the main component needs to be derived from the class RemoteStateOfferer.
Additionally the pure virtual function RemoteStateOfferer::onInitRemoteStateOfferer() needs to be implemented in this class. In onInitRemoteStateOfferer() the states, that should be accessable remotely, are to be added with State::addState<StateType>(statename).
Online statecharts can be controlled from the StatechartViewer.
using CounterState = CounterStateTemplate<EvCounterNotFulfilled, EvCounterFulfilled> |
#include <ArmarXCore/statechart/standardstates/CounterState.h>
CounterState is a typedef for the CounterStateTemplate, that uses the events EvCounterNotFulfilled and EvCounterFulfilled.
Definition at line 97 of file CounterState.h.
#include <ArmarXCore/statechart/standardstates/FinalState.h>
State that automatically signals "Failure" to the parent state. See class FinalStateBase for more information.
Definition at line 184 of file FinalState.h.
#include <ArmarXCore/statechart/standardstates/FinalState.h>
State that automatically signals "Success" to the parent state. See class FinalStateBase for more information.
Definition at line 173 of file FinalState.h.