On 05.04.2012 11:57, Santiago Romero wrote:
Looks like quite a detailed system. I'd be interested in seeing a
tutorial on how it is used.
Me too.
--
Santiago Romero
Ubuntu GNU/Linux
http://www.sromero.org
Hi
Well did you take a look at the examples [1]? Especially at the
mousefollower [2] example (look at the ### comments).
But I'm willing to write a tutorial so every one can use it. I'll try a
little introduction here:
A state machine has certain input it has to process. Depending on the
current state and the kind of input, the state machine can might perform
some actions whether it changes state or not. There are three types of
actions: entry, exit and transition action. The entry and exit actions
are bound to a state and are executed whenever that state is entered of
left (also when an external self transition is done).
So to use sympleHFSM you will have to define the input and the actions
it can perform. The input are just symbols that are passed to the
'event_handle' method of the state machine instance. This method will
handle the input and perform the corresponding actions. Therefore you
need to pass in an instance of the actions class you want to use at
creation time of the state machine instance (this way you can use
different 'backends', especially for testing). The second thing the
state machine instance needs to know is the structure. By structure I
mean the number of states that exists and their relationship between
them. This is the parent-child relationship and of course the
transitions between them.
So lets go through the mousefollower example [2]:
The mousefollower example has a pretty simple state machine: just three
states: idle, following and a parent state
Best way to visualize and plan a state machine is on paper, here is the
drawing for the example:
+--------------------------------------------------------------------+
| parent
|
init --->|
update/following_update |
| +------------------+
|
| | |
|
| +-----------------+ in_range/ +------------------+ |
|
| *-->| idle |---------------->| following |<-+
|
| | /idle_entry | | /following_entry |
|
| | | | |
|
| | | out_of_range/ | |
|
| | |<----------------| |
|
exit<---| +-----------------+ +------------------+
|
|
|
+--------------------------------------------------------------------+
Now I will describe the different sections of the example:
1. The input events are define. The mouse follower has a sensor that
give the event 'in_range' if the mouse is in range. Otherwise it
will generate an 'out_of_range' event. There is also the 'update'
event because it should behave differently depending in which state
it is. In idle state it will just do nothing (there is no action
registered for that) and in the following state it should just
follow the mouse position.
2. The actions the state machine can perform are defined. There are two
entry actions defined and an update action. The entry action for the
idle state named as 'idle_entry' and entry action for the following
state named 'following_entry'.
3. Points 1 and 2 just define the 'interfaces' of the state machine,
what its input is and what actions (sort of output) it will perform.
Now in point 3 the structure and the transitions are defined. First
the states are added. The spaces before 'idle' and 'following' state
identifier should indicate that they are both children of the
'parent' state. The only state that has no parent is the root state
(here called 'parent'). The initial flag is to determine which leaf
state the state machine should change in case a transition ends in a
state that is not a leaf. So in this case if a transition would end
at the 'parent' state then it would change to the idle state. For
each level there can only be one initial state. In those lines of
code also the entry actions are defined (explanation methodcaller
see [3]). In the next three lines the transitions are added. There
are three transitions (this are the arrows in the picture). Only the
self transitions in the 'following' state for the update event has
an action to call. Its the 'following_update' action. Now the
structure and the relationships are defined.
4. Here the actual actions for the entity are implemented. The
'following_update' action just does move the entity in direction of
the mouse. The other two actions are the entry actions for the two
sub-states, they just change the color of the entity.
5. Now here the state machine will be instantiated. The structure is
passed in and the well an instance of the actions pointing to that
instance of the entity (so the action can manipulate the entity). To
make the state machine work, input events need to be passed to the
state machine. This will happen in the update method of the entity.
There the proximity sensor will detect the mouse and then a
corresponding event (in_range or out_of_range) is generated and
passed to the state machine. This might change the state, depending
in which state it is and what event it gets. Then the update event
is also passed to the state machine, because it should show a
behavior (updating the position in direction of the mouse if in
state 'following').
I hope this made some things clear. There is much more to it. Take a
look at the symplehfsm_demo [4] for a more complex and full featured
example (run it in the console, preferably with the -O option: >>>python
-O symplehfsm_demo.py ).
I hope that helps.
~DR0ID
[1]
https://bitbucket.org/dr0id/symplehfsm/src/d9229897f4e6/trunk/symplehfsm/examples
[2]
https://bitbucket.org/dr0id/symplehfsm/src/d9229897f4e6/trunk/symplehfsm/examples/mousefollower/mousefollower.py
[3] its a convenient way to call dynamically a method by its name on an
object, see
http://docs.python.org/library/operator.html?highlight=methodcaller#operator.methodcaller
[4]
https://bitbucket.org/dr0id/symplehfsm/src/d9229897f4e6/trunk/symplehfsm/examples/TestHFSM/symplehfsm_demo.py