Enums
An enum is a type with a fixed set of named constants. Instead of using integers or strings to track robot state — where nothing stops you from using an invalid value — enums give you compiler-enforced, type-safe state management. They're the backbone of every clean FRC state machine.
By the end of this lesson, you will:
- Declare an enum with named constants and use it in a
switchstatement - Add fields and methods to an enum to associate data with each constant
- Build a robot state machine using an enum and a
switchto drive mechanism behavior - Recognize the WPILib vendor library enums:
NeutralModeValue,InvertedValue,NeutralModeValue - Explain why enums are safer than integer or String constants for state management
The Problem With Integer States
Before enums, programmers tracked state with integers: 0 = idle, 1 = intaking, 2 = scoring. This works — until someone passes 7, or -1, or confuses which subsystem uses which constants. The code compiles, the robot enables, and nothing behaves as expected.
Enum Basics
Enums with Fields and Methods
An enum is a full Java class — each constant can carry its own data and behavior. This is where enums become truly powerful for FRC: the motor output associated with each state travels with the state itself.
The Robot State Machine
The most important use of enums in FRC is the state machine: a private enum field tracks the current mechanism state, and each periodic call evaluates that state and applies transitions. Use the simulator below to step through a complete intake state machine.
Enums in WPILib and Vendor Libraries
You've been using vendor-library enums since Unit 5 without necessarily recognizing them as enums. They're the same pattern: a fixed set of named, compiler-verified options.
The clearest signal that a team has internalized enums is when I read their state machine code. A team that uses enums for arm positions and intake states can answer "what state is the arm in right now?" in one variable read — armState.name() prints the exact, human-readable state. A team using integers answers with "well, 2 means score, and 3 means stow, but we changed the order last week, so…" Enums make state self-documenting. When something breaks at competition, readable state is directly proportional to debugging speed.
- Use enums for all robot mechanism state variables. Replace integer and string state flags with named enum constants. The compiler guarantees only valid states exist.
private IntakeState state = IntakeState.IDLE;is correct.private int state = 0;is not. - Add fields to enums when state carries associated data. Motor outputs, setpoint angles, display names — these belong on the enum constant itself. The enum becomes the single source of truth for everything associated with that state.
- Switch statements on enums should have a
defaultcase. Even though all enum values should be covered by named cases, adefaultthat calls a safe fallback protects against future enum values added without updating the switch. - Use
name()for dashboard display.SmartDashboard.putString("State", currentState.name())gives you a readable state label for free — no manual string mapping required.
Knowledge Check
private int armState = 0; where 0=stow, 1=intake, 2=score. A teammate sets armState = 7 accidentally. What happens?SCORE_L2 is declared with a field: SCORE_L2(90.0). How do you read the angle value?motor.setNeutralMode(NeutralModeValue.Brake) safer than motor.setNeutralMode(1)?Complete State Machine with Enum
- Define an
IntakeStateenum with fields formotorOutputanddisplayName. Include at least four states:IDLE,INTAKING,GAME_PIECE_HELD, andEJECTING. - Modify your
IntakeSubsystemto use aprivate IntakeState currentStatefield. Inperiodic(), implement aswitchoncurrentStatethat applies the correct motor output from the enum's field. Add transitions: pressing A starts intaking, beam break triggers holding, pressing B starts ejecting, releasing B returns to idle. - Add a
getStateName()method that returnscurrentState.name(). Call it from SmartDashboard inperiodic(). Deploy and confirm the state label updates correctly as you trigger transitions. - Add an
ArmPositionenum to your arm subsystem with at least three positions and their target angles. Replace the hardcoded angle constants in your arm methods withArmPositionenum references. - Bonus (Unit 4 capstone): Look at your completed subsystem classes across all Unit 4 lessons. Write a one-page design review: Which OOP concepts from Unit 4 (classes/objects, constructors, static, encapsulation, inheritance, polymorphism, abstract/interfaces, enums) appear in your code? For each one, describe a specific line where it appears and why it's the right tool there.