-
Notifications
You must be signed in to change notification settings - Fork 1
Using a QuickCommand to simplify commands
In the previous tutorial, we saw how to make a UserTankDrive command to drive the robot. Although the command was effectively one line of "real code", we had to make a separate class and implement five methods, plus a constructor. Not only is this time-consuming, it makes the code seem more complicated than it actually is, and means it's harder for us to quickly try out new ideas. Enter QuickCommand
: a class that makes one-liners really one line, so you can focus on the interesting stuff.
We need to work on packaging the classes into a jar or something. For now just copy the class from this repo.
Let's look at our tank drive command from last time:
public class UserTankDrive extends Command {
public UserTankDrive() {
requires(Robot.drivetrain);
}
protected void initialize() {
// do nothing
}
protected void execute() {
Robot.drivetrain.drive.tankDrive(Robot.oi.leftJoystick, Robot.oi.rightJoystick);
}
protected boolean isFinished() {
return false;
}
protected void end() {
// do nothing
}
protected void interrupted() {
// do nothing
}
}
Really, this command is saying three things:
- We require
Robot.drivetrain
- We want to run
Robot.drivetrain.drive.tankDrive(Robot.oi.leftJoystick, Robot.oi.rightJoystick);
- We want to keep running it indefinitely
With a quickcommand, this can be expressed as:
QuickCommand.continuous(Robot.drivetrain, () -> Robot.drivetrain.drive.tankDrive(Robot.oi.leftJoystick, Robot.oi.rightJoystick));
This will return a command, which we can then pass to setDefaultCommand()
, or tie to a button. The first argument is the subsystem that the command requires. The second is a lambda expression, which is the code to run in execute()
.
This still looks kinda long and messy. If we run it from within the DriveSubsystem
class, we can make it considerably shorter:
QuickCommand.continuous(this, () -> drive.tankDrive(Robot.oi.leftJoystick, Robot.oi.rightJoystick));
While we can stick this code anywhere, it makes the most sense to put it in the subsystem that it belongs to. We'll make a method in DriveSubsystem
, userTankDriveCmd()
, that returns a command. The reason we make a method is so that we can pass parameters to the command. Although driving doesn't take parameters, other commands, such as PID setpoints, or extending/retracting an arm, do. The method looks like this:
public Command userTankDriveCmd() {
return QuickCommand.continuous(this, () -> drive.tankDrive(Robot.oi.leftJoystick, Robot.oi.rightJoystick));
}
Now we can set this as the default command:
public void initDefaultCommand() {
setDefaultCommand(userTankDriveCmd());
}
And that's it! Just a single-line method, instead of a whole class with six methods.
Rewrite the userTankDriveCmd
method so that it takes two Joystick
parameters, left
and right
, and uses those for driving.
- (TODO) more about the QuickCommand class
- (TODO) passing parameters
- (TODO) oneShot vs. continuous