Belle II Software  release-08-01-10
state_machine.py
1 
8 import basf2 as b2
9 from caf.state_machines import Machine, State
10 
11 # We set up a bunch of function callbacks to show the ordering of evaluation
12 # Notice that we always pass **kwargs so that they have access to anything that
13 # can be passed in.
14 
15 
16 def print_msg_before(**kwargs):
17  """
18  Callbacks on transitions have access to keyword arguments that you can
19  specify when calling a transition. But remember that all kwargs are passed
20  to ALL transition callbacks. Including both the before and after callbacks
21  """
22  b2.B2INFO(kwargs["msg_before"])
23 
24 
25 def print_msg_after(**kwargs):
26  """
27  Have to have a different kwarg name, otherwise the same argument from the
28  'before' callback will be used
29  """
30  b2.B2INFO(kwargs["msg_after"])
31 
32 
33 def enter_new_state(**kwargs):
34  """
35  Enter and exit callbacks have access to the prior and new state objects but NOT
36  the transition arguments.
37  """
38  b2.B2INFO("Entering state {} from state {}".format(kwargs["new_state"].name, kwargs["prior_state"].name))
39 
40 
41 def exit_old_state(**kwargs):
42  b2.B2INFO("Exiting state {} to state {}".format(kwargs["prior_state"].name, kwargs["new_state"].name))
43 
44 
45 def condition_true(**kwargs):
46  b2.B2INFO("Evaluating conditions")
47  return True
48 
49 
50 # Now build up a machine with some basic states and transitions between them
51 m1 = Machine()
52 m1.add_state(State("start", enter=enter_new_state, exit=exit_old_state)) # Can use a state object to add new ones
53 m1.add_state("running", enter=enter_new_state, exit=exit_old_state) # Don't have to use a state object though
54 m1.add_state("end", enter=enter_new_state, exit=exit_old_state)
55 
56 m1.add_transition(trigger="begin", source="start", dest="running",
57  conditions=condition_true, before=print_msg_before, after=print_msg_after)
58 m1.add_transition("finish", "running", "end",
59  conditions=condition_true, before=print_msg_before, after=print_msg_after)
60 
61 # have to set a start point
62 m1.initial_state = "start"
63 
64 # Note that because we didn't specify an initial state when creating the Machine we will get an orphaned default_initial
65 # state in the graph. Easily removable by hand or by adding an initial state in the Machine() initialisation.
66 m1.save_graph(filename="machine_graph.dot", graphname="Machine")
67 
68 # Run through the states passing in arguments to callbacks
69 b2.B2INFO("Currently in " + m1.state.name + " state.")
70 m1.begin(msg_before="About to run", msg_after="Now Running")
71 m1.finish(msg_before="Finishing", msg_after="Finished")
72 b2.B2INFO("Currently in " + m1.state.name + " state.")