Unit 7: Advanced FRC Coding
You know how to build reliable state machines with enums and `switch` statements. Now, it's time to learn an advanced technique that makes our state machine code even cleaner, more readable, and less prone to errors.
Consider a robot arm that moves to predefined positions. With a basic `switch` statement, the state names are in the `enum`, but the data associated with them (the angles) is located somewhere else. This separation can lead to bugs if you add a new state but forget to update the `switch` statement.
The key insight is that in Java, an enum is a special kind of class. And just like any other class, it can have its own fields, constructor, and methods. We can store the data for a state directly inside the enum itself.
Let's refactor our `ArmState` enum to be "smart" by giving it a field for the target angle and a constructor to initialize it.
public enum ArmState {
// 1. Define the constants, passing arguments to the constructor
STOW(0.0),
INTAKE(95.0),
AMP_SCORE(110.0);
// 2. Add a field to hold the data for each state
public final double angle;
// 3. Create a constructor to initialize the field
private ArmState(double angle) {
this.angle = angle;
}
}
Now, our `ArmSubsystem` code becomes dramatically simpler and more robust. The `switch` statement is completely gone. To get the target angle, we just ask the state itself!
public class ArmSubsystem extends SubsystemBase {
private final PIDController m_pidController;
private ArmState m_targetState;
// ... constructor and other methods ...
public void setTargetState(ArmState state) {
this.m_targetState = state;
}
@Override
public void periodic() {
if (m_targetState != null) {
// Get the angle directly from the enum state! No switch needed.
double setpoint = m_targetState.angle;
m_pidController.setSetpoint(setpoint);
double pidOutput = m_pidController.calculate(getCurrentAngle());
m_motor.set(pidOutput);
}
}
}
This "smart enum" pattern is a core part of our coding standard because it follows a critical software principle: the Single Source of Truth. All information about the `INTAKE` state—its name and its target angle—is located in one single place. This reduces bugs, improves readability, and makes the code much easier to maintain.
Question: What is the main advantage of storing state-specific data (like a target angle) inside the enum itself?