rFSM Statecharts v1.0
=====================

Author: Markus Klotzbuecher
Date: 2013-01-24



Table of Contents
=================
1 Overview
2 Setup
3 Introduction
4 Specifying rFSM models
    4.1 States (=rfsm.state=)
        4.1.1 The doo function
        4.1.2 Configuring a State Machine
    4.2 Transitions (=rfsm.transition=)
    4.3 Connector (=rfsm.connector=)
5 Executing rFSM models
6 Common pitfalls
7 Tools and helper modules
    7.1 The event memory extension (=rfsm_emem= module) #EventMemory
    7.2 Await: trigger transition only after receiving multiple events
    7.3 Timeevents (=rfsm_timeevent= module)
    7.4 Configurable and colorized =dbg= info (=rfsmpp= module)
    7.5 =rfsm_checkevents= plugin
    7.6 Generate graphical representations (=rfsm2uml= and =fsm2dbg= modules)
    7.7 =rfsm-viz=: command line front end to rfsm2uml/rfsm2tree
    7.8 =rfsm-sim= simple rfsm simulator
    7.9 Lua fsm to json conversion (=rfsm2json= command line tool)
    7.10 =rfsm_rtt= Useful functions for using rFSM with OROCOS rtt
8 More examples, tips and tricks
    8.1 A more complete example
    8.2 How to compose state machines
    8.3 Using rfsm with Orocos RTT
9 API Summary
    9.1 State specification
    9.2 Operational functions
    9.3 Hooks
10 Contact
11 Download
12 Acknowledgement


1 Overview 
-----------

  rFSM is a small and powerful Statechart implementation. It is mainly
  designed for /Coordination/ of complex systems but is not limited to
  that. rFSM is written in pure Lua and is therefore highly portable
  and embeddable. As a Lua domain specific language rFSM inherits the
  extensibility of its host language.

  rFSM is dual licensed under LGPL/BSD.

  This README is also available in HTML and Text format in the doc/
  subdirectory.


2 Setup 
--------

  Make sure you have Lua 5.1 installed and the rFSM folder is in your
  =LUA_PATH=. For example:



  export LUA_PATH=";;;/home/mk/src/git/rfsm/?.lua"


  If your =LUA_PATH= is already set to something, then just add the
  rFSM path instead of overwriting it:



  export LUA_PATH="$LUA_PATH;/home/mk/src/git/rfsm/?.lua"



3 Introduction 
---------------

  rFSM is minimal Statechart flavor designed for /Coordinating/ of
  complex systems such as robots. It has the following features:

  - Hierarchical (composite) states
  - Completion events
  - Parametrizable and reusable states
  - Easy to build statemachines by composing existing states/state machines
  - Plugin mechanism permits extending the core engine. Available
    plugins include timeevents, event memory, sequential AND states
    and more.
  - Real-time safe operation possible using lua-tlsf/rtp[1]

  The following shows a simple hello_world example



    [file:example1.png]



  1:  return rfsm.state {
  2:     hello = rfsm.state { exit=function() print("hello") end },
  3:     world = rfsm.state { entry=function() print("world") end },
  4:  
  5:     rfsm.transition { src='initial', tgt='hello' },
  6:     rfsm.transition { src='hello', tgt='world', events={ 'e_done' } },
  7:     rfsm.transition { src='world', tgt='hello', events={ 'e_restart' } },
  8:  }


  The first line defines a new toplevel composite state and returns
  it. The root state of an rFSM state machine is always a state
  itself. This permits it to be composed as a substate in a different
  state machine. The =return= statement facilitates reading rfsm model
  files by tools or other state machines.

  The second and third line define two leaf states that are part of
  the toplevel composite state. =hello= defines an exit function and
  world an entry function which are called when the state is
  exited/entered, respectively.

  The next three lines define transition between these states. The
  first is from the initial connector to the =hello= state. This
  transition will be taken the first time the composite state is
  entered. The initial connector, as an exception, need not be defined
  and will be created automatically when referenced from a transition.

  The next transition is from =hello= to =world= and is triggered by
  the =e_done= event. This event is raised internally when a state
  completes, which is either the case when the states 'doo' function
  (see below) finishes or immediately, if there is no =doo=, as is the
  case here. The third transition is triggered by the =e_restart=
  event.

  Next we execute this statemachine in the rfsm-simulator:



  PMA-10-048 ~/prog/lua/rfsm(master) $ tools/rfsm-sim examples/hello_world.lua
  Lua 5.1.4  Copyright (C) 1994-2008 Lua.org, PUC-Rio
  rFSM simulator v0.1, type 'help()' to list available commands
  INFO: created undeclared connector root.initial
  > step()
  hello
  active: root.hello(done)
  queue:  e_done@root.hello


  We execute =step()= to advance the state machine once. As this is
  the first step, the fsm is entered via the 'initial' connector to
  the =hello= state. After that the state =hello= is active and =done=
  (because no =doo= function is defined). Consequently, an =e_done=
  completion event has been generated and placed in the queue. So the
  next step...



  > step()
  world
  active: root.world(done)
  queue:  e_done@root.world


  ... causes a transition to =world=. As the =world= state completion
  event does not trigger any transitions, running =step()= again does
  not have any effect:



  > step()
  active: root.world(done)
  queue:


  But we can manually send in the =e_restart= event and call =step()=,
  which takes us back to =hello=:



  > se("e_restart")
  > step()
  hello
  active: root.hello(done)
  queue:  e_done@root.hello



4 Specifying rFSM models 
-------------------------

  rFSM state machines are constructed using three model elements:
  *states*, *connectors* and *transitions*.

  (all functions are part of the rfsm module, thus need to be called
  in Lua with the =rfsm= prefix, e.g. =rfsm.state{}=)

4.1 States (=rfsm.state=) 
==========================

   States are used to model discrete states of the system and can be
   either composite or leaf states. A composite state contains other
   states, while a leaf state does not. States can define =entry= and
   =exit= functions



  entry(fsm, state, 'entry')
  exit(fsm, state, 'exit')


   that are called when the state is entered or exited
   respectively. The arguments passed in are the toplevel statechart,
   the current state and the string 'entry' resp. 'exit'. Normally
   you don't need these arguments and should not change them
   either. (The rationale behind the second and third argument is to
   permit one function to handle entry and exit of multiple states
   and hence needs to identify these).


4.1.1 The doo function 
~~~~~~~~~~~~~~~~~~~~~~~

    Leaf states may additionally define a do function (it is called
    =doo= in rFSM to avoid clashes with the identically named Lua
    keyword).



  bool doo(fsm, state, 'doo')


    The doo function is used to perform actions /while/ a leaf state
    is active. To that end it can be used such that it is repeatedly
    called until either the function completes or an event triggers a
    transition to a different state.

    Implementationwise, this function is treated as a Lua
    coroutine. This enables the following two use-cases:

     1. =doo= is a regular function: =doo= is executed once and a
        completion event =e_done= is raised afterwards (if no =doo=
        function is defined this event is raised immediately after
        execution of the =entry= function).

     2. Long running =doo= with voluntary preemption: while possible,
        it is not recommended to define a =doo= function that runs for
        a longer time, because this would prevent incoming events to
        trigger transitions. Therefore, the =rfsm.yield()= call can be
        inserted at appropriate points into a long running =doo= to
        explicitly return control to the rfsm engine, that then
        checks for new events and potentially executes transitions.

    (Note: rfsm.yield is currently only an alias to =coroutine.yield=)

    The following example illustrates the second use case:



  doo = function(fsm)
           while true do
              if min_distance() < 0.1 then
                 rfsm.send_events(fsm, "e_close_obj")
              end
              rfsm.yield()
           end
        end


    This =doo= will check a certain condition repeatedly and raise the
    "e_close_obj" event if it is true. Each cycle the control is
    returned to the rFSM core by calling =rfsm.yield()=.

    =rfsm.yield(idle_flag)= accepts a Boolean argument (called the
    "idle flag") that influences how =doo= is called by the rFSM core:
    if =true= it will cause the rFSM core to go idle, provided there
    are no other events. If =false= (the default[2] if no arguments
    are given) and there are no other events, =doo= will be called in
    a tight loop. It depends on each application which =idle_flag= is
    appropriate. In general the idle_flag should always be true unless
    the intention is that the =doo= function is executed as fast as
    possible (potentially consuming a lot of CPU!).


4.1.2 Configuring a State Machine 
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

    The root composite state honors some extra fields to refine the
    global FSM behavior.

    *Configuring error, warning, informational and debug output.* The
    =err=, =warn=, =info= and =dbg= fields can be used to fine tune
    how these messages are output. The value of these fields can be
    either true or false or set to a function that accepts a variable
    list of arguments. The default is to write errors and warnings to
    stderr and info to stdout. Debug messages are turned off by
    default. Nicer and configurable pretty printing of debug output is
    provided by the =rfsmpp= module (described below).

    *The* =getevents= *hook.* The =getevents= hook is called by the
    rFSM core whenever it needs to check for new events. This function
    is the central mechanism to integrate rFSM into existing
    systems. The expected behavior is to return a Lua table of events
    (array part only). These events are then used to check for enabled
    transitions.

4.2 Transitions (=rfsm.transition=) 
====================================

   Transitions define how a state machine changes state upon receiving
   events:

   Example:



  rfsm.transition {
      src='stateX', tgt='stateY', events = {"e1", "e2"},
      guard=function()
                if getVal() > 0.3 then
                    return false
                end
                return true
            end,
      effect=function () do_this() end
  }


   The above defines a transition between stateX and stateY which is
   triggered by the events =e1= _and_ =e2=. The =guard= condition
   (optional) will prevent the transition from being executed if it
   returns false. The =effect= function (optional) will be executed
   during the transitioning of the function. If no events are
   specified, this is interpreted as *any* events will trigger the
   transition.

   Three ways of specifying the =src= and =target= states are
   supported: /local/, /relative/ or /absolute/. In the above example
   =stateX= and =stateY= are referenced locally and must therefore be
   defined within the same composite state as the transition.

   Relative references specify states that are more deeply nested
   (relative to the position of the transition). Such references
   starts with a leading dot. For example:



  return rfsm.state{
     operational=rfsm.state{
        motors_on = rfsm.state{
           moving = rfsm.state{},
           stopped = rfsm.state{},
           rfsm.trans{src='initial', tgt='stopped'},
        },
        rfsm.trans{src='initial', tgt='motors_on'},
     },
     off=rfsm.state{},
     rfsm.trans{src='initial', tgt=".operational.motors_on.moving" }
     rfsm.trans{src=".operational.motors_on.stopped", tgt='off', events={'e_off'} }
  }


   The first transition is defined between the (locally referenced)
   =initial= connector to the relatively referenced =moving=
   state. This permits to /refine/ the default behavior of the
   operational state, namely entering =motors_on.stopped= (due to the
   initial connectors), to instead enter the =motors_on.moving= state.

   The second transition defines a transition from the relatively
   referenced =operational.motors_on.stopped= to =off=. Here the
   intention is to constrain the states from which one can reach the
   =off= state: turning the device off is only permitted if it is not
   moving.

   At last absolute references begin with "root." Using absolute
   syntax is strongly discouraged for anything other than testing,
   as it breaks compositionality: if a state machine is used within
   a larger statemachine the absolute reference is broken.

   Furthermore, transitions support so called *priority
   numbers*. Priority numbers serve to resolve conflicts within one
   hierarchical level. In case two transitions are enabled by a set of
   events, the transition with the higher priority number will be
   executed. Priority numbers are defined with the =pn= keyword on
   transitions, as shown below. Transitions without priority numbers
   are assumed to have priority 0.



  rfsm.trans{ src='following', tgt='hitting', pn=10, events={ 't6' } },


   If possible, statecharts should be designed not to depend on
   priority numbers and introduce these rather as an optimization.

4.3 Connector (=rfsm.connector=) 
=================================

   Connectors permit to define so called compound transitions by
   chaining multiple transition segments together. Connectors are
   similar to the UML junction element. Compound transitions are
   statically evaluated, meaning that the compound transition is only
   executed if each subtransition is enabled (events match and guards
   are true).

   Also see the examples =connector_simple.lua= and
   =connector_split.lua=.

   Connectors are useful for defining interfaces (entry and exit
   points) that hide internals of a composite state. The following
   example defines a error handling state:


  return rfsm.state{
    software_err = rfsm.state{},
    hardware_err = rfsm.state{},
  
    initial = rfsm.conn{},
    recovered = rfsm.conn{},
    failed = rfsm.conn{},
  
    rfsm.trans{src='initial', tgt='software_err', events={'e_sw_err'}},
    rfsm.trans{src='initial', tgt='hardware_err', events={'e_hw_err'}},
  
    rfsm.trans{src='software_err', tgt='recovered', events={'e_recovered'}},
    rfsm.trans{src='hardware_err', tgt='recovered', events={'e_recovered'}},
    rfsm.trans{src='software_err', tgt='failed', events={'e_failed'}},
    rfsm.trans{src='hardware_err', tgt='failed', events={'e_failed'}},
  }


   Transitions 1 and 2 dispatch to different error handling states
   based on the events received. Transitions 3, 4, 5 and 6 connect the
   states to different exit connectors based on the events they
   generate.

   /Note/: defining cycles is possible, but dangerous, unsupported and
   discouraged. It may make the yogurt in your fridge grow fine grey
   beards.


5 Executing rFSM models 
------------------------

  Before running a statemachine must be initalized. This serves to
  validate the fsm model and transform the fsm to be suitable for
  execution. Initalization is done using the =rfsm.init(fsm)=
  function, that takes a (string) rfsm description as input and
  returns an initalized fsm. To load an rfsm from a file and initialize
  it, the =rfsm.load(filename)= function can be used:



  fsm = rfsm.init(rfsm.load("fsm.lua"))


  If the return value from =rfsm.init= is not =false=, initalization
  succeeded and the returned fsm can be run.

  The function =rfsm.step(fsm, n)= will attempt to step the given fsm
  for a maximum of =n= times. A /step/ can be either the execution of
  a transition _or_ a single execution of the =doo= program. =step=
  will return either when the state machine is /idle/ _or_ the given
  number of steps has been reached. The boolean return value indicates
  whether the fsm is idle (=true=) or the maximum amount of requested
  steps was reached (=false=).

  For each step the rfsm engine will invoke the =getevents= hook to
  retrieve new events and then reason about what to do (which
  transitions to execute or =doo='s to run). After that these events
  are discarded. If this seems inconvenient, checkout the [event memory]
  extension.

  When omitted, the number of steps argument =n= to =rfsm.step=
  defaults to *1*.

  =rfsm.run(fsm)= calls =step= as long as the given fsm is not
  idle. Not idle means: there are either events in the queue or there
  is an active =doo= function that is _not_ idle.

  To directly send events to the fsm the function
  =rfsm.send_events(fsm, e1, e2, ...)= can be used. The first argument
  is the fsm to which all subsequent event arguments are sent to.



  [event memory]: sec-7-1

6 Common pitfalls 
------------------

  1. Name clashes between state/connector names with reserved Lua
     keywords.

     This can be worked around by using the following syntax:



  ['end'] = rfsm.state{...}


  2. Executing functions accidentially

     It is a common mistake to execute externally defined functions
     instead of adding references to them:



  stateX = rfsm.state{ entry = my_func() }


     The (likely) mistake above is to execute my_func and assigning
     the result to entry instead of assigning my_func:



  stateX = rfsm.state{ entry = my_func }


     Of course the first example would be perfectly valid if
     my_func() returned a function as a result!

  3. Why doesn't my statemachine react if I send a completion event
     =e_done= from the outside?

     Short answer: because it is a syntactic shortcut for the
     completion event *of the source state* of the transition which it
     is defined on. During initalization it is transformed to
     =e_done@fqn= (e.g. =e_root@root.stateA.stateB=) If you send in
     the expanded completion event it will work.

     Explanation: a completion event only makes sense in the context
     of a state which completed. Making the state which has completed
     explicit in the event avoids accidentially triggering a
     transition labeled with a higher priority completion event that
     has nothing to do with the current one.

     The same holds true for =rfsm_timeevent= based timeevents.

  4. My FSM is using up 100% CPU, what's wrong?

     Most likely you have defined a long running =doo= function that
     does not call =rfsm.yield= with a =true= argument (the idle
     flag). Therefore the rFSM engine calls the =doo= function in a
     tight loop.

  5. My FSM is doing nothing, my guard are not executed, ... ,
     although I'm running =step= or =run= periodically!

     rFSM will only attempt to transition if it has at least one event
     in the queue! If you only want to transition based on guards,
     raise a dummy event (e.g. "e_any").


7 Tools and helper modules 
---------------------------

7.1 The event memory extension (=rfsm_emem= module) #EventMemory 
=================================================================

   This extension adds /memory/ of events that occurred to an rFSM
   statechart. This is done maintaining a table =emem= for every
   state. The keys in this table are event names and the values the
   number of times that event occurred while the respective state was
   active. The =emem= table is cleared when a state is exited by
   setting all values to 0.

   This extension is useful for defining transitions that are taken
   only after certain events have occurred, but that do not necessarily
   occur within one step. Because the rFSM engine drops events after
   each steps this information would otherwise be lost.

   To enable event memory, all you need to do is load the =rfsm_emem=
   module. Checkout the =examples/emem_test.lua= for more details.


7.2 Await: trigger transition only after receiving multiple events 
===================================================================

   In a nutshell, this plugin permits to trigger transitions only
   after multiple events have been received. These events can be
   received in different steps.

   This is basically a specialized version of the emem plugin. This
   one should be preferred if no counting is required, since it is
   computationally much less expensive.

   Behavior: When loaded, the plugin scans for events with the syntax
   await(event1, event2)". This statement is transformed as follows:

    - a guard condition is generated and added to possibly existing
      guard conditions. It will only enable the transition if the both
      events have been received while the source state is active.

    - a second hook is installed in the exit function of the source
      state to reset the event counting. So when the source state is
      exited (either via or not via the await transition) and
      reentered again, the counting start from the beginning. It would
      be trivial to provide a variant of await that resets the counts
      only if the await transition is taken, however it is not clear
      right now if that would be useful at all.

   For more information checkout the =await.lua= example.

7.3 Timeevents (=rfsm_timeevent= module) 
=========================================

   This module extends the rFSM engine with time events. Time events
   are automatically raised /after/ the specified time after entering
   a state has elapsed. To enable time events, it suffices to load the
   =rfsm_timeevent= module. Currently only relative (opposed to
   absolute) timeevents are supported. These can be specified on
   transitions using the =e_done(duration)= syntax, as show in the
   following example:



  rfsm.trans{ src='A', tgt='B', events={ 'e_after(0.1)' } },


   The timeevent will be raised 100ms after state =A= was entered.

   The only requirement of a rfsm_timeevents is that a =gettime=
   function is configured using the
   =rfsm_timeevent.set_gettime_hook(f)= function. This function is
   expected to return the current time in two return values: seconds,
   nanoseconds.

   An example can be found in =examples/timeevent.lua=

   *Warning:* these timeevents only work while the rfsm engine is
    running and can not magically wake up an idle fsm. Therefore this
    type of timeevents typically only makes sense for fsm that are
    "stepped" at a fixed frequency or that never go idle.


7.4 Configurable and colorized =dbg= info (=rfsmpp= module) 
============================================================

   The =rfsmpp.gen_dbgcolor= function generates a configurable and
   colorful =dbg= hook.

   Usage:



  rfsmpp.gen_dbgcolor(name, dbgids, defshow)


     - =name= is the (optional) string name to print prefixing the
       debug output
     - =dbgids= is a table that enables or disables certain dbg ids by
       setting them to true or false. Known debug ids are:
       =STATE_ENTER=, =STATE_EXIT=, =EFFECT=, =DOO=, =EXEC_PATH=,
       =ERROR=, =HIBERNATING=, =RAISED=, =TIMEEVENT=
     - =defshow= (bool) defines whether debug id's not mentioned in the dbgids
       table are shown or not.


   Example:



  fsm = rfsm.init(...)
  fsm.dbg=rfsmpp.gen_dbgcolor("fsm1",
                              { STATE_ENTER=true, STATE_EXIT=true}, false)


   Will show only =STATE_ENTER= and =STATE_EXIT= debug messages.

7.5 =rfsm_checkevents= plugin 
==============================

   This debugging helper plugin will at load-time construct a list of
   all events used in the FSM. If at runtime an event is received
   which is not known in the known list, a warning message will be
   printed.

   To use, just require the module before creating your
   fsm. Important: load it /after/ other plugins that transform events
   (such as timeevents), so that it picks up the transformed events.


7.6 Generate graphical representations (=rfsm2uml= and =fsm2dbg= modules) 
==========================================================================

     Modules to transform rFSM models to graphical
     descriptions. =rfsm2uml= generates classical statechart figures and
     =rfsm2tree= generates a tree representation (useful to see check
     priorities).

     Usage:

     - =rfsm2uml.rfsm2uml(root_fsm, format, outfile, caption)=
     - =rfsm2tree.rfsm2tree(root_fsm, format, outfile)=

     Examples:



  require("rfsm2uml")
  fsm = rfsm.init(rfsm.load("fsm.lua"))
  rfsm2uml.rfsm2uml(fsm, 'png', "fsm.png", "Figure caption")


     or



  require("rfsm2tree")
  fsm = rfsm.init(rfsm.load("fsm.lua"))
  rfsm2tree.rfsm2tree(fsm, 'png', "fsm-tree.png")


     The =rfsm-viz= command line uses these modules to generate
     pictures.


7.7 =rfsm-viz=: command line front end to rfsm2uml/rfsm2tree 
=============================================================

     to generate all possible formats run:



  $ tools/rfsm-viz all examples/composite_nested.lua


     generates various representations (in =examples/=)


7.8 =rfsm-sim= simple rfsm simulator 
=====================================

     small command line simulator for running a fsm
     interactively.



  $ tools/rfsm-sim all examples/ball_tracker_scope.lua


     It requires an image viewer which automatically updates once the
     file displayed changes. For example =evince= works nicely.


7.9 Lua fsm to json conversion (=rfsm2json= command line tool) 
===============================================================

   Based on =rfsm2json.lua= module and requires lua-json.


7.10 =rfsm_rtt= Useful functions for using rFSM with OROCOS rtt 
================================================================

   See the Orocos [LuaCookbook] for more details.



   [LuaCookbook]: http://www.orocos.org/wiki/orocos/toolchain/LuaCookbook

8 More examples, tips and tricks 
---------------------------------

8.1 A more complete example 
============================

   The graphical model:



      [file:example2.png]

   ... and the corresponding textual representation:



  -- any rFSM is always contained in a state
  return rfsm.state {
     dbg = true, -- enable debugging
  
     on = rfsm.state {
        entry = function () print("disabling brakes") end,
        exit = function () print("enabling brakes") end,
  
        moving = rfsm.state {
           entry=function () print("starting to move") end,
           exit=function () print("stopping") end,
        },
  
        waiting = rfsm.state {},
  
        -- define some transitions
        rfsm.trans{ src='initial', tgt='waiting' },
        rfsm.trans{ src='waiting', tgt='moving', events={ 'e_start' } },
        rfsm.trans{ src='moving', tgt='waiting', events={ 'e_stop' } },
     },
  
     error = rfsm.state {
        doo = function (fsm)
                   print ("Error detected - trying to fix")
                   rfsm.yield()
                   math.randomseed( os.time() )
                   rfsm.yield()
                   if math.random(0,100) < 40 then
                      print("unable to fix, raising e_fatal_error")
                      rfsm.send_events(fsm, "e_fatal_error")
                   else
                      print("repair succeeded!")
                      rfsm.send_events(fsm, "e_error_fixed")
                   end
                end,
     },
  
     fatal_error = rfsm.state {},
  
     rfsm.trans{ src='initial', tgt='on',
                 effect=function() print("initializing system") end },
     rfsm.trans{ src='on', tgt='error', events={ 'e_error' } },
     rfsm.trans{ src='error', tgt='on', events={ 'e_error_fixed' } },
     rfsm.trans{ src='error', tgt='fatal_error', events={ 'e_fatal_error' } },
     rfsm.trans{ src='fatal_error', tgt='initial', events={ 'e_reset' } },
  }



8.2 How to compose state machines 
==================================

   This is easy! Let's assume the state machine is is a file
   "subfsm.lua" and uses the strongly recommended =return
   rfsm.state ...= syntax, it can be included as follows:



  return rfsm.state {
  
     name_of_state = rfsm.load("subfsm.lua"),
  
     otherstateX = rfsm.state{},
     ...
  }


   Make sure not to forget the ',' after the =rfsm.load()= statement!


8.3 Using rfsm with Orocos RTT 
===============================
   The [LuaCookbook] page describes how to do this.



   [LuaCookbook]: http://www.orocos.org/wiki/orocos/toolchain/LuaCookbook

9 API Summary 
--------------

9.1 State specification 
========================

   Functions to define rFSM:

     *Function*       *Short alias*   *Description*        
    ----------------+---------------+---------------------
     =state{}=        =state{}=       create a state       
     =connector{}=    =conn{}=        create a connector   
     =transition{}=   =trans{}=       create a transition  



9.2 Operational functions 
==========================

     *Function*                     *Description*                                         
    ------------------------------+------------------------------------------------------
     =fsm rfsm.init(fsmmodel)=      create an initialized rfsm instance from model        
     =idle rfsm.step(fsm, n)=       attempt to transition FSM n times. Default: once      
     =rfsm.run(fsm)=                run FSM until it goes idle                            
     =rfsm.send_events(fsm, ...)=   send one or more events to internal rfsm event queue  


9.3 Hooks 
==========

   The following hook functions can be defined for a toplevel
   composite state and allow to refine various behavior of the state
   machine.

     *Function*            *Description*                                                                       
    ---------------------+------------------------------------------------------------------------------------
     =dbg=                 called to output debug information. Set to false to disable. Default: false.        
     =info=                called to output informational messages. Set to false to disable. Default: stdout.  
     =warn=                called to output warnings. Set to false to disable. Default stderr.                 
     =err=                 called to output errors. Set to false to disable. Default stderr.                   
     =table getevents()=   function which returns a table of new events which have occurred.                   


   Lower level functions (not for normal use):

   Use these to manage step hooks. Setting =pre_step_hook= and
   =post_step_hook= directly is not permitted anymore:

     *Function*                               *Description*                                                      
    ----------------------------------------+-------------------------------------------------------------------
     =pre_step_hook_add(fsm, hook, where)=    install function hook to be called _before_ each rfsm step of fsm  
     =post_step_hook_add(fsm, hook, where)=   install function hook to be called _after_ each rfsm step of fsm   

   =idle_hook(fsm)=: if defined, called *instead* of returning from
   step/run functions. Used only for debugging purposes.

10 Contact 
-----------

  Please direct questions, bugs or improvements to the [orocos-users]
  mailing list.


  [orocos-users]: http://lists.mech.kuleuven.be/mailman/listinfo/orocos-users

11 Download 
------------

  The code can be found in [this] git repository.

  A cheatsheet summarizing the DSL is available [here].


  [this]: https://github.com/kmarkus/rFSM
  [here]: https://github.com/kmarkus/rfsm-cheatsheet/raw/master/cheatsheet.pdf

12 Acknowledgement 
-------------------

  - Funding

    The research leading to these results has received funding from
    the European Community's Seventh Framework Programme
    (FP7/2007-2013) under grant agreement no. FP7-ICT-231940-BRICS
    (Best Practice in Robotics)

  - Scientific background

    This work borrows many ideas from the Statecharts by David Harel
    and some from UML 2.1 State Machines. The following publications
    are the most relevant

    David Harel and Amnon Naamad. 1996. The STATEMATE semantics of
    statecharts. ACM Trans. Softw. Eng. Methodol. 5, 4 (October 1996),
    293-333. DOI=10.1145/235321.235322
    [http://doi.acm.org/10.1145/235321.235322]

    The OMG UML Specification:
    [http://www.omg.org/spec/UML/2.3/Superstructure/PDF/]


[1] See [this] Real-time Linux Workshop paper, [lua-tlsf] and the
 [minimal Lua real-time POSIX bindings]


[2] The reason for this choice of default is that it fails more
  obviously (100% CPU load) than the opposite (doo function not
  executed properly).

  [this]: https://lwn.net/images/conf/rtlws-2011/paper.05.html
  [lua-tlsf]: https://github.com/kmarkus/lua-tlsf
  [minimal Lua real-time POSIX bindings]: https://github.com/kmarkus/rtp

