State Machines Lesson

State Machines: The Brains of a Mechanism

A state machine is a design pattern that is critical to how we build software for complex mechanisms. It allows you to describe a sequence of actions in a clear, organized, and predictable way, which is key to writing reliable and easy-to-debug robot code.

What is a State Machine?

A state machine is a model of behavior defined by two simple things: a finite number of conditions a system can be in (states), and the events that cause a move from one state to another (transitions). A system can only be in one state at a time.

The Traffic Light Analogy

A traffic light is a perfect real-world state machine.

  • States: `GREEN`, `YELLOW`, `RED`.
  • Transitions: The expiration of a timer causes a transition from `GREEN` to `YELLOW`, and so on.

It can't be both green and red at the same time. This predictability is what we want for our robot's mechanisms.

An FRC Example: An Intake Mechanism

Let's design a state machine for a simple intake that picks up game pieces. Before writing code, we should always diagram the states and transitions on a whiteboard.

The States

  • `IDLE`: The intake is off, waiting for instructions.
  • `INTAKING`: The rollers are spinning to pull a game piece in.
  • `HOLDING`: The rollers are off, and a game piece is secured.
  • `EJECTING`: The rollers are spinning in reverse to spit the game piece out.

The Transitions

  • `IDLE` → `INTAKING`: The driver presses the 'A' button.
  • `INTAKING` → `HOLDING`: A beam break sensor is tripped.
  • `HOLDING` → `EJECTING`: The driver presses the 'B' button.
  • `EJECTING` → `IDLE`: A 0.5-second timer finishes.

Implementing a State Machine in Code

The cleanest way to implement a state machine in Java is with an `enum` to define the states and a `switch` statement inside a subsystem's `periodic()` method to handle the logic.

// 1. Define the States with an enum
public enum IntakeState {
    IDLE,
    INTAKING,
    HOLDING,
    EJECTING
}

// 2. Implement the logic in the subsystem
public class IntakeSubsystem extends SubsystemBase {
    private IntakeState m_currentState = IntakeState.IDLE; // Start in IDLE
    // ... motor and sensor objects ...

    @Override
    public void periodic() {
        // This switch statement runs 50 times per second
        switch (m_currentState) {
            case IDLE:
                // Stop the motor
                // Transition: if driver presses 'A', change state to INTAKING
                break;
            case INTAKING:
                // Run the motor forward
                // Transition: if sensor is tripped, change state to HOLDING
                break;
            case HOLDING:
                // Stop the motor
                // Transition: if driver presses 'B', change state to EJECTING
                break;
            case EJECTING:
                // Run the motor in reverse
                // Transition: if timer is done, change state to IDLE
                break;
        }
        SmartDashboard.putString("Intake State", m_currentState.toString());
    }
}
    

Test Your Knowledge

Question: What are the two fundamental components that define a state machine?