Complex Movements with Command Groups Lesson

Complex Movements with Command Groups

Individual commands are powerful, but the real magic happens when you compose them into complex sequences. Command Groups allow you to build sophisticated autonomous routines and driver actions from simple, reusable building blocks.

The Power of Composition

The core idea is to build small, compose big. We create simple, testable commands for individual actions (drive, turn, run intake) and then use command groups to choreograph them into complex routines. WPILib provides a `Commands` utility class with factory methods to make this easy.

1. Sequential Command Groups

A sequential group runs a list of commands one after another. The next command in the sequence will not start until the previous one has completely finished. This is the backbone of most autonomous routines.

// In RobotContainer.java
public Command getSimpleAuto() {
    // This command will drive forward 36 inches, and only when that is done,
    // it will run the intake for 2 seconds.
    return Commands.sequence(
        new DriveDistanceCommand(m_drivetrain, 36.0),
        new RunIntakeForTimeCommand(m_intake, 2.0)
    );
}
    

2. Parallel Command Groups

A parallel group runs multiple commands at the same time. The group finishes when the last of the parallel commands has finished. This is perfect for actions that can and should happen concurrently to save time.

// In RobotContainer.java
public Command getScoringCommand() {
    // This command will raise the arm to the scoring position AND
    // spin up the shooter wheels to the target RPM at the same time.
    return Commands.parallel(
        new MoveArmToPositionCommand(m_arm, 110.0),
        new SpinUpShooterCommand(m_shooter, 4000)
    );
}
    

Other Useful Command Groups

WPILib provides even more specialized groups for advanced control.

  • `Commands.parallelRace(...)`: Runs commands in parallel, but the entire group ends as soon as the first command finishes. Great for actions with multiple end conditions (e.g., "run intake until a note is detected OR 2 seconds have passed").
  • `Commands.parallelDeadline(...)`: Runs commands in parallel, but one command is designated the "deadline." The group ends when the deadline command finishes. Useful for actions like "drive forward for 36 inches, and while you're doing that, run the intake."

Test Your Knowledge

Question: You need to create a command that drives toward a game piece while simultaneously running the intake. Which type of command group is the most appropriate for this?