Autonomous Basics

The basics of autonomous with WPILib.

Command Groups

Command groups are simple way to pair multiple commands together to create an autonomous routine.

Sequential Command Group

The most popular of the command groups, SequentialCommandGroup will run a list of commands in sequential order. Starting with the first command in the list then the second and so on.

Warning

The SequentialCommandGroup will not finish unless all the commands finish. Also if a command in the list does not finish the next command in line will not start.

 1import edu.wpi.first.wpilibj2.command.SequentialCommandGroup;
 2
 3public class Example extends SequentialCommandGroup
 4{
 5    public Example()
 6    {
 7        addCommands
 8        (
 9            //Drive Forward
10            new DriveForward(),
11
12            //Drive Reverse
13            new DriveReverse()
14        );
15    }
16}

In the above example using SequentialCommandGroup the command DriveForward() will be executed first and when complete the command DriveReverse() will be executed.

Caution

If DriveForward() does not end DriveReverse() will never start.

Parallel Command Group

The ParallelCommandGroup is just like the SequentialCommandGroup except that all the commands run at the same time. The command group will only finish when all commands are finished.

 1import edu.wpi.first.wpilibj2.command.ParallelCommandGroup;
 2
 3public class Example extends ParallelCommandGroup
 4{
 5    public Example()
 6    {
 7        addCommands
 8        (
 9            //Drive Forward
10            new DriveForward(),
11
12            //Move Arm to Home Position
13            new Arm(Pos.Home)
14        );
15    }
16}

In the above example using ParallelCommandGroup the commands DriveForward() and Arm(Pos.Home) will be executed at the same time.

Caution

Both DriveForward() and Arm(Pos.Home) MUST complete to move on. If they do not complete the routine will be stuck at the example() call.

Parallel Race Group

The ParallelRaceGroup is similar to the ParallelCommandGroup except that a race condition is created. All commands start at the same time but, when one command is finished it interrupts all other commands running and ends the command group.

 1import edu.wpi.first.wpilibj2.command.ParallelRaceGroup;
 2
 3public class Example extends ParallelRaceGroup
 4{
 5    public Example()
 6    {
 7        addCommands
 8        (
 9            //Drive Forward
10            new DriveForward(),
11
12            //Move Arm to Home Position
13            new Arm(Pos.Home)
14        );
15    }
16}

In the above example using ParallelRaceGroup the commands DriveForward() and Arm(Pos.Home) will be executed at the same time.

Note

If DriveForward() or Arm(Pos.Home) completes before the other then the other will be interrupted and stop running.

Java Only Benefits

For Java only, Static Factory Methods are possible, allowing a much simplar way to declare command groups.

sequence()

The sequence() static method allows for a sequential command group.

parallel()

The parallel() static method allows for a parallel command group.

race()

The race() static method allows for a parallel race group.

 1import edu.wpi.first.wpilibj2.command.SequentialCommandGroup;
 2
 3public class Example extends SequentialCommandGroup
 4{
 5    public Example()
 6    {
 7        addCommands
 8        (
 9            race(new DriveForward(), new ElevatorUP()),
10            parallel(new ShootObject(), new LineupGoal()),
11            sequence(new DriveReverse(), new StrafeRight())
12        );
13    }
14}

If we analyze this command group we can break down what is happening.

  1. We have race(new DriveForward(), new ElevatorUP()) this will create a ParallelRaceGroup that has the two commands DriveForward() and ElevatorUP() run at the same time in a race. When one finishes it will stop the other.

  2. As the main command group is the SequentialCommandGroup we then move on to the next command which is a ParallelCommandGroup.

  3. The ParallelCommandGroup of parallel(new ShootObject(), new LineupGoal()) tells us that ShootObject() and LineupGoal() happen at the same time. When both are complete it will pass to the next command group.

  4. The last command group here is the sequence(new DriveReverse(), new StrafeRight()) which is also a SequentialCommandGroup. This group is telling the robot to DriveReverse() and when that is done to StrafeRight().

Conditional Command

The ConditionalCommand will run one command or another based on condition that must be met.

1// Base parameters
2new ConditionalCommand(trueCommand, falseCommand, boolean condition);
3
4// Use case
5new ConditionalCommand(new DriveForward(), new DriveReverse(), isLimitHit());

Wait Command

The WaitCommand() is useful for when a timed wait period is required.

1// Waits 10 seconds
2new WaitCommand(10);

Wait Until Command

The WaitUntilCommand is an upgraded version of WaitCommand() as a boolean condition can be added.

1// Waits 10 seconds
2new WaitUntilCommand(10);
3
4// Waits for limit switch to be true
5new WaitUntilCommand(isLimitHit());

Command Decorators

Command decorators take the base command and add additonal functionalities to it.

withTimeout()

Adds a timeout to the command. When the timeout expires the command will be interrupted and end.

1// Add a 10 second timeout
2new command.withTimeout(10);

withInterrupt()

Adds a condition that will interrupt the command.

1new command.withInterrupt(isLimitHit());

andThen()

Adds a method that is executed after the command ends.

1new command.andThen(() -> System.out.println("Command Finished"););

beforeStarting()

Adds a method that is executed before the command starts.

1new command.beforeStarting(() -> System.out.println("Command Starting"););