Unit 05 · lesson
Subsystems, Commands, and Triggers
Command-based programming gives FRC teams a way to organize robot behavior around responsibilities instead of dumping every action into one loop.
The basic vocabulary is straightforward once the ownership is clear.
Subsystem: who owns the hardware?
A subsystem represents one robot capability or mechanism.
Examples:
- drivetrain;
- intake;
- elevator;
- shooter;
- climber.
The subsystem owns hardware access and exposes meaningful operations.
Instead of code everywhere saying “set motor 7 to 0.62,” other code can request something closer to the robot’s language:
intake.runIn();
That is easier to reason about and easier to change later.
Command: what behavior should happen?
A command describes an action involving one or more subsystems.
Examples:
- run intake until a sensor detects a piece;
- move elevator to a scoring height;
- drive a fixed distance;
- aim and shoot;
- stop a mechanism safely.
Commands have lifecycles. They start, execute, finish, or get interrupted.
Trigger: when should behavior start?
Triggers connect events to commands.
A controller button is a common trigger, but triggers can also represent conditions.
Conceptually:
trigger condition becomes true
↓
scheduler starts command
↓
command uses subsystem
↓
subsystem controls hardware
Why requirements matter
Two commands should not fight for the same subsystem at the same time.
The command scheduler tracks subsystem requirements so one behavior can interrupt or block another according to the command structure.
That architecture prevents a class of “two pieces of code are both commanding the motor” bugs.
Worked example: intake command
Suppose the desired behavior is:
Hold a driver button to run the intake inward. Stop when the button is released.
A clean structure is:
Trigger: driver holds intake button
Command: run intake inward
Subsystem: intake
Hardware: intake motor controller
The command does not need to know how the driver controller is physically connected. The subsystem does not need to know which button was pressed.
Each layer has one reason to change.
Compare two designs
Design A
button binding → directly sets motor
autonomous code → directly sets same motor
sensor handler → directly stops same motor
Design B
button binding → schedules intake command
autonomous routine → schedules intake command
sensor condition → ends or changes command
intake subsystem → owns motor
Design A may work on day one. Design B is easier to reason about once the robot grows.
Sketch your command architecture
For one mechanism, define:
- subsystem name;
- hardware it owns;
- three public operations;
- two commands;
- the trigger or autonomous event that starts each command;
- one interruption condition.
Do not write full vendor-specific code unless you have an actual project available. The architectural sketch is the target.
Failure mode: abstraction with no meaning
Creating a class called IntakeSubsystem does not automatically produce good architecture.
If every other class still reaches inside and manipulates the motor directly, ownership is fake.
The rule is simple: the boundary should control access to the thing it claims to own.