MIRA
Toolbox StateMachine - Documentation


State machine class based on the SCXML (http://www.w3.org/TR/scxml/) specification.Can be used for designing programs that use a finite state automaton to realize some kind of flow control.

The following topics are covered in this documentation:

<scxml>

The root of a SCXML config file is required to be <scxml>.

Attributes

Nested Tags

Example

<scxml name="MyStateMachine" datamodel="python" binding="late">
</scxml>

<state>

Holds the representation of a state.

Definition: An atomic state is one that has no <state>, <parallel> or <final> children. Definition: A compound state is one that has <state>, <parallel> or <final> children (or a combination of these).

A compound state MAY specify either an "initial" attribute or an <initial> element, but not both. If neither the "initial" attribute nor an <initial> element is specified, the first child state in document order is chosen as the default initial state.

Attributes

Nested Tags

Parent Tags

Example

<scxml name="MyStateMachine" datamodel="python" binding="late">
<state id="A" initial="A2">
<state id="A1"/>
<state id="A2"/>
</state>
<state id="B" />
</scxml>

<initial>

This element represents the default initial state for a complex <state> element (i.e. one containing child <state> or <parallel> elements.

Nested Tags

Parent Tags

Example

<scxml name="MyStateMachine" datamodel="python" binding="late">
<state id="A">
<initial>
<transition target="A2"/>
</initial>
<state id="A1"/>
<state id="A2"/>
</state>
</scxml>

<final>

This element represents a final state of an <scxml> or compound <state> element.

Attributes

Nested Tags

Parent Tags

Example

<scxml name="MyStateMachine" datamodel="python" binding="late">
<state id="A">
<state id="A1">
<transition event="Done" target="Final"/>
</state>
<final id="Final"/>
</state>
</scxml>

<parallel>

The <parallel> element encapsulates a set of child states which are simultaneously active when the parent element is active.

Attributes

Nested Tags

Parent Tags

Example

<scxml name="MyStateMachine" datamodel="python" binding="late">
<parallel id="P">
<state id="A"/>
<state id="B" />
</parallel>
</scxml>

<history>

The <history> pseudo-state allows a state machine to remember its state configuration. A <transition> taking the <history> state as its target will return the state machine to this recorded configuration.

If the 'type' of a <history> element is "shallow", the immediately active children of its parent are recorded before taking any transition that exits the parent. If the 'type' of a <history> element is "deep", the active atomic descendants of the parent are recorded before taking any transition that exits the parent. After the parent state has been visited for the first time, we define the set of states that the processor has recorded to be the 'stored state configuration' We also define the states specified by the 'target' of the <history> element's <transition> child to be the 'default stored state configuration.' If a transition is executed that takes the <history> state as its target, the behavior depends on whether the parent state has been visited before. If it has, it behave as if the transition had taken the stored state configuration as its target. If it has not, it behave as if the transition had taken the default stored state configuration as its target.

Attributes

Nested Tags

Parent Tags

Example

<scxml name="MyStateMachine" datamodel="python" binding="late">
<state id="A">
<history id="Ahistory">
<transition target="A1"/>
</history>
<state id="A1">
<transition event="e12" target="A2" />
</state>
<state id="A2">
<transition event="e23" target="A3" />
</state>
<state id="A3">
<transition event="eAB" target="B" />
</state>
</state>
<state id="B">
<transition event="back" target="Ahistory" />
</state>
</scxml>

The following is a log output and shows that after firing the transition B->Ahistory the state machine goes back to A3

Fire transition MyStateMachine->A
Entering state A
Entering state A1
Send event e12
Leaving state A1
Fire transition A1->A2
Entering state A2
Send event e23
Leaving state A2
Fire transition A2->A3
Entering state A3
Send event eAB
Leaving state A3
Leaving state A
Fire transition A3->B
Entering state B
Send event back
Leaving state B
Fire transition B->Ahistory
Entering state A
Entering state A3

<transition>

Transitions between states are triggered by events and conditionalized via guard conditions. They may contain executable content, which is executed when the transition is taken.

See Events for more details on Events and how transitions are triggered by them.

Attributes

A conformant SCXML document MUST specify at least one of 'event', 'cond' or 'target'.

Nested Tags

The children of <transition> are executable content that is run after all the <onexit> handlers and before the all <onentry> handlers that are triggered by this transition.

Parent Tags

Example

<scxml name="MyStateMachine" datamodel="python" binding="late">
<state id="A">
<transition event="/Int" cond="_event.data.Value > 25" target="B" />-->
</state>
<state id="B">
<transition event"toA" target="A" />
</state>
</scxml>

<onentry>

A wrapper element containing executable content to be executed when the state is entered.

Nested Tags

The children of the <onentry> handler consist of executable content

Parent Tags

Example

<scxml name="MyStateMachine" datamodel="python" binding="late">
<state id="A">
<onentry>print 'On entry of A'</onentry>
</state>
</scxml>

<onexit>

A wrapper element containing executable content to be executed when the state is exited.

Nested Tags

The children of the <onexit> handler consist of executable content

Parent Tags

Example

<scxml name="MyStateMachine" datamodel="python" binding="late">
<state id="A">
<onexit>print 'On exit of A'</onexit>
</state>
</scxml>

<datamodel>

<datamodel> is a wrapper element which encapsulates any number of <data> elements, each of which defines a single data object.

Nested Tags

Parent Tags

Example

<scxml name="MyStateMachine" datamodel="python" binding="late">
<state id="A">
<datamodel>
<data id="pi" expr="3.141"/>
</datamodel>
</state>
</scxml>

<data>

The <data> element is used to declare and populate portions of the datamodel.

Attributes

Nested Tags

The children of the <data> element represent an in-line specification of the value of the data object.

In a conformant SCXML document, if the expr attribute is present, the element MUST NOT have any children. Thus 'expr' and children are mutually exclusive in the <data> element.

Parent Tags

Example

<scxml name="MyStateMachine" datamodel="python" binding="late">
<state id="A">
<datamodel>
<data id="pi" expr="3.141"/>
<data id="x">'Hello World'</data>
</datamodel>
</state>
</scxml>

Data binding and scoping

There is a single globally visible data model for the entire state machine. Specifically, the state machine allows any data element to be accessed from any state. Thus the data model has no concept of scoping. However, authors control when the initial values are assigned to the data elements by means of the 'binding' attribute on the <scxml> element. When 'binding' is assigned the value "early" (the default), all data elements are created and their initial values are assigned at document initialization time. When 'binding' is assigned the value "late", the state machine creates the data elements at document initialization time, but assigns the value specified by 'expr' to a given data element only when the state that contains it is entered for the first time, before any <onentry> markup. Ordering dependencies between <data> elements are not permitted. In the case of early binding, all <data> elements are evaluated at initialization time but do so in any order. Suppose, for example, that the declaration of element "a" precedes the declaration of element "b" in a document. It is not safe to assume that "a" will be instantiated and have a value when the declaration of "b" is executed. Therefore the "expr" in "b" cannot safely reference the value of "a" (and vice-versa). When late binding is selected, the data model elements are created at initialization time but do so in any order. Similarly, the value specified by 'expr' are assigned to data elements only when the state containing them is first entered, but do so in any order.

Events

Events are one of the basic concepts in SCXML since they drive most transitions. The internal structure of events is platform-specific as long as the following external interface is observed:

Events can be raised during the execution of an SCXML document under author control by use of the <raise> and <send> elements. However, certain events are mandatory and generated automatically by the interpreter.

Definition: A transition matches an event if at least one of its event descriptors matches the event's name. Definition: An event descriptor matches an event name if its string of tokens is an exact match or a prefix of the set of tokens in the event's name. In all cases, the token matching is case sensitive.

For example, a transition with an 'event' attribute of "error foo" will match event names "error", "error.send", "error.send.failed", etc. (or "foo", "foo.bar" etc.) but would not match events named "errors.my.custom", "errorhandler.mistake","errOr.send" or "foobar".

An event designator consisting solely of "*" can be used as a wildcard matching any sequence of tokens, and thus any event. Note that this is different from a transition lacking the 'event' attribute altogether. Such an eventless transition does not match any event, but will be taken whenever its 'cond' attribute evaluates to 'True'. The state machine will check for such eventless transitions when it first enters a state, before it looks for transitions driven by internal or external events.

Events can also be generated by channel data changes in the Framework. Therefor the user must add a leading '/' to an events name. The state machine will automaitcally subscribe to that channel and fires an event with the channels name whenever data in the channel changes. The content of the channel when the event was send is available via the '_event' variable.

As events trigger state changes and transitions they should only be raised when they signal a change (e.g. falling or rising edge). Never use channels that update with a high frequency or channels that contain always the same data. These can lead to an internal overflow of the event queue so that events will be lost or processed with a high time delay.
<scxml>
<state id="A">
<transition event="/MyPoseChannel" cond="_event.data.Value.X > 25" target="B" />-->
</state>
<state id="B" />
</scxml>

The above example subscribes automatically to channel /MyPoseChannel and fires an event named '/MyPoseChannel' whenever data in that channel changes. In this case the structure of the _event variable would be as follows:

_event = { name : "/MyPoseChannel",
data : { Timestamp : 12335647567856,
FrameID : "MyFrame",
SequenceID : 0
Value : { X : 1.5,
Y : 0.0
Phi : 180.0
}
}
}

Errors

Once the SCXML processor has begun executing a well-formed SCXML document, it signals any errors that occur by raising SCXML events whose names begin with 'error.'. One error event is defined in this specification: 'error.platform'. It category consists of application errors and errors internal to the execution of the document, such as those arising from expression evaluation. The event name is extended by adding a suffix classifying the error and the data element may contain additional information about the nature of the error. Note in particular, that these events are ignored if no transition is found that matches them. Note however that authors can arrange for otherwise unhandled errors to cause the interpreter to exit by creating a transition with "event" attribute of 'error' and a target of any top-level final state (i.e. one that is a child of <scxml>). If such a transition T is placed in a state S, it will cause the state machine to terminate on any error that is raised in S or one of its substates and is not handled by another transition that is placed in a substate of S or in S and preceding T in document order.

List of Errors and Events

The following events are generated automatically by the SCXML implementation under the listed conditions.

Executable content

Executable content allows the state machine to do things. It provides the hooks that allow to modify the data model and interact with external entities. Executable content consists of actions that are performed as part of taking transitions. In particular, executable content occurs inside <onentry> and <onexit> elements as well as inside <transition>. When the state machine takes a transition, it executes the <onexit> executable content in the states it is leaving, followed by the content in the <transition>, followed by the <onentry> content in the states it is entering.

The SCXML standard specifies that implementations are allowed to define their own content. So we will interpret text children of executable elements as Python script code by default.

<scxml name="MyStateMachine" datamodel="python" binding="late">
<state id="A">
<onentry>print 'On entering state A'</onentry>
</state>
</scxml>

<script>

The <script> element adds scripting capability to the state machine. It is equivalent to use no tags at all for executable content but provides an additional feature of sourcing scripts from file via the <id>src</id> attribute.

Attributes

Parent Tags

Example

<scxml name="MyStateMachine" datamodel="python" binding="late">
<state id="A">
<onentry>
<script>print 'On entering state A'<script>
<script src="MyScript.py" />
</onentry>
</state>
</scxml>

<raise>

The <raise> element raises an event in the current SCXML session. Note that the event will not be processed until the current block of executable content has completed and all events that are already in the internal event queue have been processed.

Attributes

Parent Tags

Example

<scxml name="MyStateMachine" datamodel="python" binding="late">
<state id="A">
<onentry>
<raise event="MyEvent" />
</onentry>
</state>
</scxml>

<send>

The <send> element raises an event in the current SCXML session. Note that the event will not be processed until the current block of executable content has completed and all events that are already in the internal event queue have been processed.

Attributes

Nested Tags

Parameters
p1The element is evaluated when the parent <send> element is evaluated and the resulting data is contained in the event. Occurs 0 or more times.

<content>MyContent</content> The element is evaluated when the parent <send> element is evaluated and the resulting data is contained in the event. Occurs 0 or 1 times.

A conformant document MUST NOT specify with <content>.

Parent Tags

Example

<scxml name="MyStateMachine" datamodel="python" binding="late">
<state id="A">
<onentry>
<send id="TimeoutEventID" event="Timeout" delay="30s">
<content>Sorry</content>
</send>
</onentry>
</state>
</scxml>

<cancel>

The <cancel> element is used to cancel a delayed <send> event. The best attempt is made to cancel the delayed event. Note, however, that it can not be guaranteed to succeed, for example if the event has already been delivered by the time the <cancel> tag executes.

Attributes

Parent Tags

Example

<scxml name="MyStateMachine" datamodel="python" binding="late">
<state id="A">
<onentry>
<send id="TimeoutEventID" event="Timeout" delay="30s">
<content>Sorry</content>
</send>
</onentry>
<transition event="Success" target="B"/>
<transition event="Timeout" target="Error"/>
<onexit>
<cancel sendid="TimeoutEventID"/>
</onexit>
</state>
<state id="B"/>
<state id="Error"/>
</scxml>

The Python datamodel

Currently only the Python datamodel is supported. All executable content as well as all data in the data model is interpreted as Python code.

Note that indentations are significant in Python.

A good practice is to import all needed Python modules in the <script> childs of <scxml> node.

<scxml name="MyStateMachine" datamodel="python" binding="late">
<script>
import math
import sys
</script>
</scxml>

Instead of using the data model nodes which is the prefered way of creating variables you can create and assign variables in all the executable content.

<scxml name="MyStateMachine" datamodel="python" binding="late">
<script>
pi = 3.141
s = "Hello World"
</script>
</scxml>

To use the framework functionality (e.g. Units, Channel access, RPC calls) from within the statemachine you must import the module mirapy:

<scxml name="MyStateMachine" datamodel="python" binding="late">
<script>
import mirapy
</script>
</scxml>

Build in functionality

The basic datamodel contains a variable '_sm' that should NOT be overwritten. This variable holds a reference to the statemachine instance and allows to manipulate the statemachine from within the datamodel.

It supports the method 'sendEvent(Event)' that can be used to send events from the data model instead of using the <send> or <raise> nodes.

<scxml name="MyStateMachine" datamodel="python" binding="late">
<script>
from statemachinepy import Event
</script>
<state id="A">
<onentry>
<script>_sm.sendEvent(Event("ToB"))</script>
</onentry>
<transition event="ToB" target="B"/>
</state>
<state id="B"/>
</scxml>

Also the data model supports the predicate 'In(id)' that evaluates to true if the state with name 'id' is contained in the current state configuration (the state is active).

One can also obtain the current state configuration as a set via the 'getConfiguration()' method:

<scxml name="MyStateMachine" datamodel="python" binding="late">
<state id="A">
<onentry>
<script>print list(_sm.getConfiguration())</script>
</onentry>
<transition event="ToB" target="B"/>
</state>
<state id="B"/>
</scxml>

SCXML Editor

As your state machine grows, a GUI-based editor may come in handy. You can find a (very limited) number of different scxml editors out there, however, the scxmlgui (http://code.google.com/p/scxmlgui/) is most suitable.

An adapted version of that editor has been created to fulfill our needs. The following changes have been made to improve the interaction with our scxml implementation:

Overview

The SCXML Editor allows you to create new SCXML documents, to open and edit pre-existing files with a graphical user interface and to export the graphs as image files. More information is available at https://github.com/fmorbini/scxmlgui/blob/wiki/Guide.md .

Creating a new file

Open the SCXML Editor by starting the jar file "fsm-editor.jar" in a terminal :

java -jar fsm-editor.jar

You can then press CTRL-N or click on File->New.

Opening a file

When the editor is already running, you can open a file by clicking on File->Open file. However, to avoid layout display issues it is recommended to use this method only when no other file was open before. You can also start the editor directly with a pre-existing file from the terminal :

java -jar fsm-editor -i <name of your scxml file> -l

The "-l" option is vital to keep a correct layout.

Editing nodes and edges

To create a new node, simply right click on the area where you want to put your node and choose Add node. To edit a node, you can either double-click on it or right click and choose Edit node. The different characteristics of the node can then be modified in the new window which has appeared. To create a new transition, click in the center of the starting node, hold and drag the mouse until the center of the destination node. The edge edition is similar to the node edition : either double-click on an edge or right click on it and choose Edit Transition. You can then modify the properties of the edge.

Each action can be undone by pressing CTRL-Z or redone with CTRL-Y.

To delete an object, select it with a left click and press the Delete key.

Saving a file

To save your file, press CTRL-S or click on File->Save. You can also save the document in a new file with CTRL-SHIFT-S or in File->Save as. There, you have the possibility to export the document to another type (scxml, png, jpg, html, svg, bmp, ...).

SCXML Listener

In addition to the basic edition functionalities, the editor offers an SCXML Listener. To use it, open the scxml file you want to listen to and click on Tools->SCXML execution listener. You will have to choose a port to connect to and you can start the connection with the button Start. The program will then begin to wait for the connection to this port (using TCP) of another program which is supposed to implement the corresponding state machine. When the connection is established, each time a new node or a new transition is encountered in the execution of the state machine, it is added to the listener and highlighted on the graph. One can thus follow the evolution of the execution of the state machine. When the program executing the state machine breaks the connection, it should send to the listener the phrase "disconnecting", which will then stop the connection on the listener side as well.

SCXMLListener.png

To learn more about the client side of the TCP connection which is supposed to run the state machine, read the documentation on FlowControl.