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}Header
1#prama once 2 3#include <frc2/command/CommandHelper.h> 4#include <frc2/command/SequentialCommandGroup.h> 5 6class Example 7 : public frc2::CommandHelper<frc2::SequentialCommandGroup, Example> 8{ 9 public: 10 Example(void); 11};Source
1#include "commands/Example.h" 2 3Example::Example(void) 4{ 5 AddCommands 6 ( 7 //Drive Forward 8 DriveForward(), 9 10 //Drive Backwards 11 DriveReverse() 12 ); 13}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}Header
1#prama once 2 3#include <frc2/command/CommandHelper.h> 4#include <frc2/command/ParallelCommandGroup.h> 5 6class Example 7 : public frc2::CommandHelper<frc2::ParallelCommandGroup, Example> 8{ 9 public: 10 Example(void); 11};Source
1#include "commands/Example.h" 2 3Example::Example(void) 4{ 5 AddCommands 6 ( 7 //Drive Forward 8 DriveForward(), 9 10 //Arm to Home Position 11 Arm(Pos::Home) 12 ); 13}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}Header
1#prama once 2 3#include <frc2/command/CommandHelper.h> 4#include <frc2/command/ParallelRaceGroup.h> 5 6class Example 7 : public frc2::CommandHelper<frc2::ParallelRaceGroup, Example> 8{ 9 public: 10 Example(void); 11};Source
1#include "commands/Example.h" 2 3Example::Example(void) 4{ 5 AddCommands 6 ( 7 //Drive Forward 8 DriveForward(), 9 10 //Arm to Home Position 11 Arm(Pos::Home) 12 ); 13}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.
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.
As the main command group is the SequentialCommandGroup we then move on to the next command which is a ParallelCommandGroup.
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.
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());1frc2::ConditionalCommand(trueCommand, falseCommand, [&limit] {return isLimitHit();});
Wait Command
The WaitCommand() is useful for when a timed wait period is required.
1// Waits 10 seconds 2new WaitCommand(10);1// Waits 10 seconds 2frc2::WaitCommand(10.0_s);
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());1// Waits 10 seconds 2frc2::WaitUntilCommand(10.0_s); 3 4// Waits for limit switch to be true 5frc2.WaitUntilCommand([&Limit] {return 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);1// Add a 10 second timeout 2command.WithTimeout(10.0_s);
withInterrupt()
Adds a condition that will interrupt the command.
1new command.withInterrupt(isLimitHit());1command.WithInterrupt([&limit]{return isLimitHit();});
andThen()
Adds a method that is executed after the command ends.
1new command.andThen(() -> System.out.println("Command Finished"););1command.AndThen([] {std::cout<<"Command Finished";});
beforeStarting()
Adds a method that is executed before the command starts.
1new command.beforeStarting(() -> System.out.println("Command Starting"););1command.BeforeStarting([] {std::cout<<"Command Starting"});