The Conductor Analogy: Imagine an orchestra.
- The Robot is the Concert Hall.
- The Subsystems (Episode 3) are the musicians (Violin, Drums).
- The Commands (This Episode) are the sheet music telling them what to play.
- The RobotContainer is the Conductor, deciding when the music starts.
๐ฏ Learning Objectives
๐๏ธ Chapter 1: The Big Picture
Why "Command-Based"?
In the "Olden Days" (like... 2015), we wrote code in big loops. It was messy. If you wanted the arm to move while the robot drove, you had to write complex if statements.
Command-Based solves this by letting us write small, isolated pieces of code ("Commands") and the WPILib Scheduler handles running them all at once. It's multi-tasking for free!
The Three Pillars
- Subsystems: The physical parts (Drivebase, Arm, Intake). They represent hardware.
- Commands: The actions (DriveForward, RaiseArm, EatPizza). They represent verbs.
- RobotContainer: The glue. It connects the hardware to the actions using controllers.
๐ฆ Chapter 2: The RobotContainer
RobotContainer.java is where 90% of your configuration happens. It's not a Subsystem. It's a setup class.
public class RobotContainer {
// 1. Define Subsystems (The Hardware)
private final DriveSubsystem m_drive = new DriveSubsystem();
private final ArmSubsystem m_arm = new ArmSubsystem();
// 2. Define Controllers (The Input)
private final CommandXboxController m_driver = new CommandXboxController(0);
public RobotContainer() {
// 3. Configure bindings
configureBindings();
// 4. Set Default Commands (What to do when no buttons are pressed)
m_drive.setDefaultCommand(
// Run command that constantly reads joystick
new RunCommand(
() -> m_drive.arcadeDrive(-m_driver.getLeftY(), -m_driver.getRightX()),
m_drive
)
);
}
private void configureBindings() {
// "When A is pressed, print Hello"
m_driver.a().onTrue(new InstantCommand(() -> System.out.println("Hello!")));
}
}Common Mistake: Do NOT put game logic in Robot.java. Robot.java should mostly be empty in Command-Based programming. Treat RobotContainer as your main entry point!
๐ Chapter 3: Anatomy of a Command
A Command is a class that implements the Command interface. It has four main methods that run in a specific order.
Code Example: DriveDistanceCommand
public class DriveDistanceCommand extends Command {
private final DriveSubsystem m_drive;
private final double m_distance;
// Constructor: Require the subsystem!
public DriveDistanceCommand(DriveSubsystem drive, double distance) {
m_drive = drive;
m_distance = distance;
addRequirements(m_drive); // Crucial! Tells scheduler "I need the drivebase"
}
@Override
public void initialize() {
m_drive.resetEncoders();
}
@Override
public void execute() {
m_drive.tankDrive(0.5, 0.5); // Drive forward at 50%
}
@Override
public boolean isFinished() {
// Stop if we passed the distance
return m_drive.getAverageDistance() >= m_distance;
}
@Override
public void end(boolean interrupted) {
m_drive.stop(); // Safety first!
}
}๐ฎ Chapter 4: Triggers & Bindings
This is how we make the robot interactive. In modern WPILib (2024+), we use Trigger objects.
Types of Bindings
onTrue(): Runs the command once when the button is pressed. (Good for: "Shoot", "Toggle").whileTrue(): Runs the command repeatedly while holding the button. Ends when released. (Good for: "Spin Intake").onFalse(): Runs when the button is released.toggleOnTrue(): Press to start, press again to stop.
// In RobotContainer.configureBindings()
// While holding 'X', spin intake. When released, it stops (because command ends).
m_driver.x().whileTrue(new StartIntakeCommand(m_intake));
// When 'A' is pressed, schedule the "Score" command. It runs until it finishes itself.
m_driver.a().onTrue(new ScoreAmpCommand(m_arm, m_shooter));
// Triggers can be anything! Not just buttons!
// "If battery voltage drops below 10V, rumble controller"
new Trigger(() -> RobotController.getBatteryVoltage() < 10)
.onTrue(new InstantCommand(() -> m_driver.getHID().setRumble(RumbleType.kBothRumble, 1)));๐ง Checkpoint
You now understand the skeleton of a robot program!
- RobotContainer holds the pieces.
- Commands are the instructions.
- Triggers start the instructions.
But... what are they controlling? In Episode 3, we will build the Muscles (Subsystems) to make this skeleton move!
๐ Need Help? We've Got Your Back!
- Email: feds.programming@gmail.com
Keep coding, keep learning, and remember: every expert was once a beginner who refused to give up! ๐
P.S. - If your robot starts talking back, that's either very advanced AI or you need more sleep. Probably more sleep. ๐ค๐ค
This documentation is part of the Zero to Hero programming series. For the complete learning experience, watch the accompanying video and practice with real robot code. Remember: the only way to get good at programming is to write lots of bad code first! ๐
Special Thanks: To all the students who asked "Why doesn't this work?" and inspired us to create better documentation. Your questions make us better teachers, and your curiosity drives innovation. You're the real MVPs! ๐
Remember: Every expert was once a beginner who refused to give up. Keep coding, keep learning, and most importantly - keep having fun! ๐