Skip to main content

Commands

In a traditional timed robot program, code for different mechanisms can become tangled and difficult to read. WPILib's command-based framework separates the robot's hardware into subsystems and its actions into commands.

A command describes an action, such as running the intake or moving an elevator to a target height. Commands can be connected to controller buttons or combined into autonomous routines.

Basic Structure

The following command uses the IntakeSubsystem from the previous page. Create IntakeCommand.java inside the commands folder:

IntakeCommand.java
package frc.robot.commands;

import edu.wpi.first.wpilibj2.command.Command;
import frc.robot.subsystems.IntakeSubsystem;

public class IntakeCommand extends Command {
private final IntakeSubsystem intake;

public IntakeCommand(IntakeSubsystem intake) {
this.intake = intake;
addRequirements(intake);
}

@Override
public void initialize() {}

@Override
public void execute() {
intake.intake();
}

@Override
public void end(boolean interrupted) {
intake.stop();
}

@Override
public boolean isFinished() {
return false;
}
}

The constructor receives the existing IntakeSubsystem from RobotContainer and stores it in the intake field. addRequirements(intake) tells the command scheduler that this command uses the intake. While it is running, the scheduler will prevent another command that requires the same subsystem from running at the same time.

initialize()

This method runs once when the command is first scheduled. Use it to prepare the command, reset values, or start an action that only needs to happen once.

execute()

This method runs repeatedly while the command is scheduled, normally once every 20 ms. Here, it calls the subsystem's intake() method to keep the intake motor running.

@Override
public void execute() {
intake.intake();
}

end()

This method runs once when the command finishes or is cancelled. Use it to stop motors and leave the subsystem in a safe state.

The interrupted parameter is false when the command finishes normally and true when it is cancelled or replaced by another command.

@Override
public void end(boolean interrupted) {
intake.stop();
}

isFinished()

This method is checked repeatedly after execute(). It returns true when the command should end. Returning false means the command continues running until it is cancelled or interrupted.

// Returns true when the command should end.
@Override
public boolean isFinished() {
return false;
}

Because this intake command always returns false, it must be cancelled. A common approach is to run it only while the driver holds a button. Add a binding in RobotContainer.java:

RobotContainer.java
m_driverController.a().whileTrue(new IntakeCommand(intake));

Pressing the A button schedules the command. Releasing the button cancels it, which causes end() to run and stop the intake motor.

The order looks like this:

Command scheduled


initialize() runs once


execute() ◄──┐ runs repeatedly
│ │
▼ │
isFinished() ───┘ false: keep running

true

end() runs once