-
Notifications
You must be signed in to change notification settings - Fork 6
Finite State Machines
since v0.2.4
Presage2 provides a simple API for defining and executing Finite State Machines. It can be found in the uk.ac.imperial.presage2.util.fsm
package. This document describes the basic usage of this API or you can just look at the javadoc.
The FSM is created through the FSMDescription builder class. This allows you to add states and transitions to your FSM. States and transitions are identified by a string or enum to describe their name. You may not add multiple states and transitions with the same name and all states given in a transition must be defined before you try to create it.
The FSMDescription class supports chaining of it's methods to allow a more compact definition of the state machine:
// example of a simple fsm
FSMDescription fsmDesc = FSM.description()
.addState("initial", StateType.START)
.addState("intermediate")
.addState("final", StateType.END)
.addTransition("initToInter", initCondition, "initial", "intermediate", initAction)
.addTransition("interToFinal", finalCondition, "intermediate", "final", finalAction);
// methods to add state to an FSMDescription
addState(String name, StateType type);
addState(String name);
addState(Enum<?> name, StateType type);
addState(Enum<?> name);
To add a state to the fsm you simply give a String
name and a StateType. The StateType can be START
, ACTIVE
or END
. These simply let the state machine know which state to start in, and when the state machine has finished. There may only be one start state, but as many end states as you want. If you do not specify the StateType it will default to ACTIVE
.
Alternatively you can use Enum
s to describe your state name. String
s and Enum
s can be used interchangeably in the same FSM as the latter is simply converted into a String
with it's name()
method.
addTransition(String name, TransitionCondition condition, String start, String end, Action action);
addTransition(Enum<?> name, TransitionCondition condition, Enum<?> start, Enum<?> end, Action action);
Like states transitions are named by a String
or Enum
, and link two previously defined states which are identified by their names. The transition also has a TransitionCondition which decides if the transition should be taken given an event on the fsm, and an Action which executes some code if the transition is taken.
In order to control when transitions can be taken the FSM uses TransitionConditions. These decide whether a transition can be taken given an event, an entity object (see later) and the current fsm state. Presage comes with some basic conditions and boolean operators:
- TransitionCondition.ALWAYS - Returns true always.
- EventTypeCondition - Returns true if the event is an instance of a given class.
- AndCondition - Returns the boolean AND of all conditions given to it.
- OrCondition - Returns the boolean OR of all conditions given to it.
- NotCondition - Returns the negation of the condition given to it.
If you pass null
as the transition condition when creating a transition the FSM will use TransitionCondition.ALWAYS by default.
Actions are what you execute the FSM for. They let you perform some task as the transition is being taken. In the case you don't want to do anything on a transition you can use Action.NOOP
for a blank action.
Once you have created your FSMDescription you can pass it to your FSM in order to execute it:
FSMDescription desc = FSM.description()...;
FSM fsm = new FSM(desc, entity);
The second argument to the FSM constructor is the entity for the FSM. This is a generic java Object
which you give the FSM. This object is then available to all TransitionConditions and Actions. Therefore you can use it to store additional state, metadata or objects you will need to work with.
Now you can apply events on the fsm with any java object:
fsm.applyEvent(event);