State machine - AvionCargo-UL/SkyAvionics GitHub Wiki
State Machine 🏗️
Package Purpose 🎯
The purpose of the state machine package is to provide decision-making capabilities to the plane.
StateMachine ⚙️
The StateMachine
class is the core of the state machine pattern.
The machine contains all the states that can be used and also holds the current state.
In order to build the state machine, you need to provide all possible states and the initial state.
All possible states, called states
, are a dictionary that maps a state enum to a real state implementation.
To run the machine, you need to periodically call the execute
method.
How to Build the State Machine 🛠️
Define Used States 📝
states: dict[StateEnum, State] = {
StateEnum.IDLE: Idle(),
StateEnum.TAKEOFF: Takeoff(),
}
Define the State Machine 🧰
state_machine = StateMachine(states, StateEnum.TAKEOFF)
State 🏁
The State
class is the abstract class.
It defines 3 methods:
on_enter
-> Executes only once when the state is changed. Use this method to restore the state.execute
-> This is the loop of the state. You will need to do all the computation and state switching here.on_exit
-> Executes only once when the state is changed. You can clear resources if needed.
All states that derive from State
must implement these three methods. 🛠️
[!TIP]
Remember, concrete classes are just classes! You can define custom methods and constructors to pass anything into them.
How to Change State 🔄
In the execute
method, you can simply return the next state enum like so:
def execute(self) -> StateEnum:
print("Hello")
if true:
return StateEnum.MY_NEXT_STATE
[!NOTE] Return nothing if you don't need to switch the state.
How to Create a New State ➕
- Create a new class in the
state_machine/states/
folder:
class MyNewState(State):
def on_enter(self):
pass
def execute(self) -> StateEnum:
pass
def on_exit(self):
pass
- Append the class to the
StateEnum
:
class StateEnum(Enum):
IDLE = (auto(),)
...
MY_NEW_STATE = (auto(),)
- Register your state in the
application_context
where states are defined:
states: dict[StateEnum, State] = {
StateEnum.IDLE: Idle(),
...
StateEnum.MY_NEW_STATE : MyNewState(),
}