In this section we'll cover the basic implementation of state machines and how states and transitions trigger specific tasks through function call backs and how those tasks are called on specific threads.
State machines control the flow of execution and are robust implementations that are easier to test and debug than conventional
if/then/else logic in straight procedural code. By mapping the states of the robot to a state machine and identifying valid transitions from one state to another, the developer creates a predictable and testable system with appropriate error handling. Figure 1 provides and example state machine. The blocks are the valid states and the curved lines are transitions between states. Transitions are undertaken when the underlying condition associated with the transition is verified.
State machines are implemented by the
EcStateMachine class. A state machine has a vector of state objects, each one representing a unique states of the state
machine. It also has five attributes. The attributes of a state machine are shown in the table below.
The XML represenation of the state machine is quite simple.
A state represents the current activity or state of the state machine. A state machine has an initial state (on startup) and then transitions to different states depending on enviornmental and internal events. A state has
A state supports three kinds of invoke blocks
These blocks allows the state to set up resources on entry, execute work each cycle, and then clean up any resources upon exit.
Here's a snippet of the XML definition for a state with its invoke blocks:
Transitions are how a state machine changes states, and are implemented by the
A transition has a conditions block used to check if the transition should occur, and an invokes block which specifies one or more functions to call when executing the transition.
Example XML code for the State IDLE to transition to state RUNNING:
<state id="IDLE"> <transition target="UNKNOWN"> <condition> <condNot> <condStringEQ elementId="CURRENT_STATE" elementPath="../runtime_state" condValue="RUNNING"/> </condNot> </condition> </transition> <transition target="TEACH"> <condition> <condInt32EQ elementId="ACTUAL_MODE" elementPath="/transfer_layers/rtde" condValue="1"/> </condition> </transition> <transition target="SERVO"> <condition> <condInt32EQ elementId="ACTUAL_MODE" elementPath="/transfer_layers/rtde" condValue="2"/> </condition> </transition> <transition target="SIMULATION"> <condition> <condInt32EQ elementId="ACTUAL_MODE" elementPath="/transfer_layers/rtde" condValue="3"/> </condition> </transition> </state>
The condition block defines a simple or compound predicate. When the predicate is true, the condition is met, and a state transition is triggered. Actin IPC provides a variety of
predicates and logical operators. Conditions can be compounded using
AND, NOT, OR with operators
==, >, >=, <, <=, ~= Basic types are supported including signed and unsigned integers, doubles, strings, boolean values as well as vectors of these same types.
The invokes block represents a group of invokes, which are called when the transition happens. The transition invokes are called after the current state's on-exit invokes and before the target state's on-entry invokes.
The sequence diagram in the figure below lays out the order of invokes for a state machine. Note that execution of the state machine is run to completion. This means that in a single cycle, the state machine can execute more than one state transition. The controller running the state machine will check for valid transitions, take the first transition, enter a new state, and then check immediately for valid transitions to other states. This continues until the state machine remains in a state with no valid transitions available.