Improve command decorator names (#1945)

This commit is contained in:
Oblarg
2019-10-19 11:13:33 -04:00
committed by Peter Johnson
parent a38f183a98
commit 53816155ba
18 changed files with 47 additions and 46 deletions

View File

@@ -43,7 +43,7 @@ ParallelRaceGroup Command::WithTimeout(units::second_t duration) && {
return ParallelRaceGroup(std::move(temp));
}
ParallelRaceGroup Command::InterruptOn(std::function<bool()> condition) && {
ParallelRaceGroup Command::WithInterrupt(std::function<bool()> condition) && {
std::vector<std::unique_ptr<Command>> temp;
temp.emplace_back(std::make_unique<WaitUntilCommand>(std::move(condition)));
temp.emplace_back(std::move(*this).TransferOwnership());
@@ -58,7 +58,7 @@ SequentialCommandGroup Command::BeforeStarting(std::function<void()> toRun) && {
return SequentialCommandGroup(std::move(temp));
}
SequentialCommandGroup Command::WhenFinished(std::function<void()> toRun) && {
SequentialCommandGroup Command::AndThen(std::function<void()> toRun) && {
std::vector<std::unique_ptr<Command>> temp;
temp.emplace_back(std::move(*this).TransferOwnership());
temp.emplace_back(std::make_unique<InstantCommand>(

View File

@@ -122,7 +122,7 @@ class Command : public frc::ErrorBase {
* @param condition the interrupt condition
* @return the command with the interrupt condition added
*/
ParallelRaceGroup InterruptOn(std::function<bool()> condition) &&;
ParallelRaceGroup WithInterrupt(std::function<bool()> condition) &&;
/**
* Decorates this command with a runnable to run before this command starts.
@@ -138,7 +138,7 @@ class Command : public frc::ErrorBase {
* @param toRun the Runnable to run
* @return the decorated command
*/
SequentialCommandGroup WhenFinished(std::function<void()> toRun) &&;
SequentialCommandGroup AndThen(std::function<void()> toRun) &&;
/**
* Decorates this command to run perpetually, ignoring its ordinary end

View File

@@ -19,7 +19,7 @@ namespace frc2 {
* A command that starts a notifier to run the given runnable periodically in a
* separate thread. Has no end condition as-is; either subclass it or use {@link
* Command#withTimeout(double)} or
* {@link Command#interruptOn(BooleanSupplier)} to give it one.
* {@link Command#withInterrupt(BooleanSupplier)} to give it one.
*
* <p>WARNING: Do not use this class unless you are confident in your ability to
* make the executed code thread-safe. If you do not know what "thread-safe"

View File

@@ -14,7 +14,7 @@ namespace frc2 {
/**
* A command that runs a Runnable continuously. Has no end condition as-is;
* either subclass it or use Command.WithTimeout() or
* Command.InterruptOn() to give it one. If you only wish
* Command.WithInterrupt() to give it one. If you only wish
* to execute a Runnable once, use InstantCommand.
*/
class RunCommand : public CommandHelper<CommandBase, RunCommand> {

View File

@@ -15,8 +15,8 @@ namespace frc2 {
* A command that runs a given runnable when it is initalized, and another
* runnable when it ends. Useful for running and then stopping a motor, or
* extending and then retracting a solenoid. Has no end condition as-is; either
* subclass it or use Command.WithTimeout() or Command.InterruptOn() to give it
* one.
* subclass it or use Command.WithTimeout() or Command.WithInterrupt() to give
* it one.
*/
class StartEndCommand : public CommandHelper<CommandBase, StartEndCommand> {
public:

View File

@@ -31,13 +31,13 @@ TEST_F(CommandDecoratorTest, WithTimeoutTest) {
EXPECT_FALSE(scheduler.IsScheduled(&command));
}
TEST_F(CommandDecoratorTest, InterruptOnTest) {
TEST_F(CommandDecoratorTest, WithInterruptTest) {
CommandScheduler scheduler = GetScheduler();
bool finished = false;
auto command =
RunCommand([] {}, {}).InterruptOn([&finished] { return finished; });
RunCommand([] {}, {}).WithInterrupt([&finished] { return finished; });
scheduler.Schedule(&command);
@@ -68,13 +68,13 @@ TEST_F(CommandDecoratorTest, BeforeStartingTest) {
EXPECT_FALSE(scheduler.IsScheduled(&command));
}
TEST_F(CommandDecoratorTest, WhenFinishedTest) {
TEST_F(CommandDecoratorTest, AndThenTest) {
CommandScheduler scheduler = GetScheduler();
bool finished = false;
auto command =
InstantCommand([] {}, {}).WhenFinished([&finished] { finished = true; });
InstantCommand([] {}, {}).AndThen([&finished] { finished = true; });
scheduler.Schedule(&command);

View File

@@ -63,7 +63,7 @@ class RobotContainer {
// speed)
.WithTimeout(ac::kAutoTimeoutSeconds)
// When the command ends, turn off the shooter and the feeder
.WhenFinished([this] {
.AndThen([this] {
m_shooter.Disable();
m_shooter.StopFeeder();
});

View File

@@ -19,7 +19,7 @@ ComplexAuto::ComplexAuto(DriveSubsystem* drive, HatchSubsystem* hatch) {
frc2::StartEndCommand([drive] { drive->ArcadeDrive(kAutoDriveSpeed, 0); },
[drive] { drive->ArcadeDrive(0, 0); }, {drive})
.BeforeStarting([drive] { drive->ResetEncoders(); })
.InterruptOn([drive] {
.WithInterrupt([drive] {
return drive->GetAverageEncoderDistance() >=
kAutoDriveDistanceInches;
}),
@@ -30,7 +30,7 @@ ComplexAuto::ComplexAuto(DriveSubsystem* drive, HatchSubsystem* hatch) {
[drive] { drive->ArcadeDrive(-kAutoDriveSpeed, 0); },
[drive] { drive->ArcadeDrive(0, 0); }, {drive})
.BeforeStarting([drive] { drive->ResetEncoders(); })
.InterruptOn([drive] {
.WithInterrupt([drive] {
return drive->GetAverageEncoderDistance() <=
kAutoBackupDistanceInches;
}));

View File

@@ -52,7 +52,7 @@ class RobotContainer {
[this] { m_drive.ArcadeDrive(ac::kAutoDriveSpeed, 0); },
[this] { m_drive.ArcadeDrive(0, 0); }, {&m_drive})
.BeforeStarting([this] { m_drive.ResetEncoders(); })
.InterruptOn([this] {
.WithInterrupt([this] {
return m_drive.GetAverageEncoderDistance() >=
ac::kAutoDriveDistanceInches;
});

View File

@@ -99,26 +99,10 @@ public interface Command {
* @param condition the interrupt condition
* @return the command with the interrupt condition added
*/
default Command interruptOn(BooleanSupplier condition) {
default Command withInterrupt(BooleanSupplier condition) {
return new ParallelRaceGroup(this, new WaitUntilCommand(condition));
}
/**
* Decorates this command with a runnable to run after the command finishes.
*
* <p>Note: This decorator works by composing this command within a CommandGroup. The command
* cannot be used independently after being decorated, or be re-decorated with a different
* decorator, unless it is manually cleared from the list of grouped commands with
* {@link CommandGroupBase#clearGroupedCommand(Command)}. The decorated command can, however, be
* further decorated without issue.
*
* @param toRun the Runnable to run
* @return the decorated command
*/
default Command whenFinished(Runnable toRun) {
return new SequentialCommandGroup(this, new InstantCommand(toRun));
}
/**
* Decorates this command with a runnable to run before this command starts.
*
@@ -135,6 +119,22 @@ public interface Command {
return new SequentialCommandGroup(new InstantCommand(toRun), this);
}
/**
* Decorates this command with a runnable to run after the command finishes.
*
* <p>Note: This decorator works by composing this command within a CommandGroup. The command
* cannot be used independently after being decorated, or be re-decorated with a different
* decorator, unless it is manually cleared from the list of grouped commands with
* {@link CommandGroupBase#clearGroupedCommand(Command)}. The decorated command can, however, be
* further decorated without issue.
*
* @param toRun the Runnable to run
* @return the decorated command
*/
default Command andThen(Runnable toRun) {
return new SequentialCommandGroup(this, new InstantCommand(toRun));
}
/**
* Decorates this command with a set of commands to run after it in sequence. Often more
* convenient/less-verbose than constructing a new {@link SequentialCommandGroup} explicitly.

View File

@@ -14,7 +14,7 @@ import edu.wpi.first.wpilibj.Notifier;
/**
* A command that starts a notifier to run the given runnable periodically in a separate thread.
* Has no end condition as-is; either subclass it or use {@link Command#withTimeout(double)} or
* {@link Command#interruptOn(BooleanSupplier)} to give it one.
* {@link Command#withInterrupt(BooleanSupplier)} to give it one.
*
* <p>WARNING: Do not use this class unless you are confident in your ability to make the executed
* code thread-safe. If you do not know what "thread-safe" means, that is a good sign that

View File

@@ -14,7 +14,7 @@ import static edu.wpi.first.wpilibj.util.ErrorMessages.requireNonNullParam;
/**
* A command that runs a Runnable continuously. Has no end condition as-is;
* either subclass it or use {@link Command#withTimeout(double)} or
* {@link Command#interruptOn(BooleanSupplier)} to give it one. If you only wish
* {@link Command#withInterrupt(BooleanSupplier)} to give it one. If you only wish
* to execute a Runnable once, use {@link InstantCommand}.
*/
public class RunCommand extends CommandBase {

View File

@@ -15,7 +15,7 @@ import static edu.wpi.first.wpilibj.util.ErrorMessages.requireNonNullParam;
* A command that runs a given runnable when it is initalized, and another runnable when it ends.
* Useful for running and then stopping a motor, or extending and then retracting a solenoid.
* Has no end condition as-is; either subclass it or use {@link Command#withTimeout(double)} or
* {@link Command#interruptOn(BooleanSupplier)} to give it one.
* {@link Command#withInterrupt(BooleanSupplier)} to give it one.
*/
public class StartEndCommand extends CommandBase {
protected final Runnable m_onInit;

View File

@@ -36,12 +36,12 @@ class CommandDecoratorTest extends CommandTestBase {
}
@Test
void interruptOnTest() {
void withInterruptTest() {
CommandScheduler scheduler = new CommandScheduler();
ConditionHolder condition = new ConditionHolder();
Command command = new WaitCommand(10).interruptOn(condition::getCondition);
Command command = new WaitCommand(10).withInterrupt(condition::getCondition);
scheduler.schedule(command);
scheduler.run();
@@ -66,7 +66,7 @@ class CommandDecoratorTest extends CommandTestBase {
}
@Test
void whenFinishedTest() {
void andThenLambdaTest() {
CommandScheduler scheduler = new CommandScheduler();
ConditionHolder condition = new ConditionHolder();
@@ -74,7 +74,7 @@ class CommandDecoratorTest extends CommandTestBase {
Command command = new InstantCommand();
scheduler.schedule(command.whenFinished(() -> condition.setCondition(true)));
scheduler.schedule(command.andThen(() -> condition.setCondition(true)));
assertFalse(condition.getCondition());

View File

@@ -47,7 +47,7 @@ class CommandGroupErrorTest extends CommandTestBase {
void redecoratedCommandErrorTest() {
Command command = new InstantCommand();
assertDoesNotThrow(() -> command.withTimeout(10).interruptOn(() -> false));
assertDoesNotThrow(() -> command.withTimeout(10).withInterrupt(() -> false));
assertThrows(IllegalArgumentException.class, () -> command.withTimeout(10));
CommandGroupBase.clearGroupedCommand(command);
assertDoesNotThrow(() -> command.withTimeout(10));

View File

@@ -50,7 +50,7 @@ public class RobotContainer {
// speed)
.withTimeout(kAutoTimeoutSeconds)
// When the command ends, turn off the shooter and the feeder
.whenFinished(() -> {
.andThen(() -> {
m_shooter.disable();
m_shooter.stopFeeder();
});

View File

@@ -52,7 +52,8 @@ public class RobotContainer {
// Reset the encoders before starting
.beforeStarting(m_robotDrive::resetEncoders)
// End the command when the robot's driven distance exceeds the desired value
.interruptOn(() -> m_robotDrive.getAverageEncoderDistance() >= kAutoDriveDistanceInches);
.withInterrupt(() -> m_robotDrive.getAverageEncoderDistance()
>= kAutoDriveDistanceInches);
// A complex auto routine that drives forward, drops a hatch, and then drives backward.
private final Command m_complexAuto = new ComplexAutoCommand(m_robotDrive, m_hatchSubsystem);
@@ -78,7 +79,7 @@ public class RobotContainer {
new RunCommand(() -> m_robotDrive.arcadeDrive(
m_driverController.getY(GenericHID.Hand.kLeft),
m_driverController.getX(GenericHID.Hand.kRight)),
m_robotDrive)
m_robotDrive)
);
// Add commands to the autonomous command chooser

View File

@@ -40,7 +40,7 @@ public class ComplexAutoCommand extends SequentialCommandGroup {
// Reset the encoders before starting
.beforeStarting(driveSubsystem::resetEncoders)
// End the command when the robot's driven distance exceeds the desired value
.interruptOn(
.withInterrupt(
() -> driveSubsystem.getAverageEncoderDistance() >= kAutoDriveDistanceInches),
// Release the hatch
@@ -53,7 +53,7 @@ public class ComplexAutoCommand extends SequentialCommandGroup {
driveSubsystem
)
.beforeStarting(driveSubsystem::resetEncoders)
.interruptOn(
.withInterrupt(
() -> driveSubsystem.getAverageEncoderDistance() <= -kAutoBackupDistanceInches)
);
}