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:
- 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.
- 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'.
- 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.
- 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.
- 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
|