PlanMachine9

A library for expressing a self-running state machine. States and Transitions in the machine are more than simple nodes and edges, though.

Visual representation of states and transitions - description below.

States and Transitions

Each State in the machine may have a precondition and/or postcondition. These are arbitrary code expressed via a lambda or Proc instance, and control whether or not the State may be entered or exited.

Each State also may have a prelude and/or postlude. These are arbitrary code chunks (also a lambda or Proc instance) that are run when entering and/or exiting a State.

Transitions may also have a precondition that controls whether or not the transition may occur, and may have an action that runs as the transition occurs.

Transitions are primarily triggered by an 'event' fired into the machine. Instead of a global namespace of events, each event may be fired along with a 'scope'. (Scopes typically specify the source of the event.) Transitions can be specified to occur when an event is fired only in a specific scope, or when the event is fired in any scope.

Transitions may also be specified without any triggering event. Such transitions occur as soon as they are legal. (In the most restrictive case, such a transition is only possible if the postcondition of the active state is met, the precondition of the transition is met, and the precondition of the target state is met.)

Because Transitions may execute code arbitrary code when executed, and thus affect some internal state of the machine or application, a Transitions may be specified to go to the same state as they originated in. In this case, the prelude of the State is not run upon transitioning.

Code Execution

Every precondition/postcondition/prelude/postlude/action block is executed using instance_eval in the scope of the plan instance itself. This gives those code blocks access to the current_state, plan_time (number of seconds the plan has been running), state_time (number of seconds the current state has been active), and env variables.

The env accessor returns an auto-vivifying Hash of hashes. The intended use is to provide a scope as the first key to the Hash, and the name of a global variable in that scope as the second key. This provides a convenient dumping ground for code to create and manage side inforamtion that helps simplify states in the machine.

Library

planmachine9.rb (download)

Example Usage (contrived)

elevator_plan.rb (download)
elevator.pxml9 (download)
(output)