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 ➕

  1. 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
  1. Append the class to the StateEnum:
class StateEnum(Enum):
    IDLE = (auto(),)
    ...
    MY_NEW_STATE = (auto(),)
  1. Register your state in the application_context where states are defined:
states: dict[StateEnum, State] = {
   StateEnum.IDLE: Idle(),
   ...
   StateEnum.MY_NEW_STATE : MyNewState(),
}