2020-12-26 14:12:05 -08:00
|
|
|
// Copyright (c) FIRST and other WPILib contributors.
|
|
|
|
|
// Open Source Software; you can modify and/or share it under the terms of
|
|
|
|
|
// the WPILib BSD license file in the root directory of this project.
|
2019-08-25 17:47:07 -04:00
|
|
|
|
2025-11-07 19:55:43 -05:00
|
|
|
package org.wpilib.command2;
|
2019-08-25 17:47:07 -04:00
|
|
|
|
2025-11-07 19:55:43 -05:00
|
|
|
import static org.wpilib.units.Units.Seconds;
|
|
|
|
|
import static org.wpilib.util.ErrorMessages.requireNonNullParam;
|
2022-10-11 19:53:27 +03:00
|
|
|
|
2025-11-07 19:55:43 -05:00
|
|
|
import org.wpilib.units.measure.Time;
|
|
|
|
|
import org.wpilib.util.function.BooleanConsumer;
|
|
|
|
|
import org.wpilib.util.sendable.Sendable;
|
|
|
|
|
import org.wpilib.util.sendable.SendableBuilder;
|
|
|
|
|
import org.wpilib.util.sendable.SendableRegistry;
|
2024-07-12 06:01:54 +08:00
|
|
|
import java.util.Collection;
|
2023-07-14 01:12:01 -04:00
|
|
|
import java.util.HashSet;
|
2019-08-25 17:47:07 -04:00
|
|
|
import java.util.Set;
|
|
|
|
|
import java.util.function.BooleanSupplier;
|
2025-10-03 20:42:47 -04:00
|
|
|
import org.wpilib.annotation.NoDiscard;
|
2019-08-25 17:47:07 -04:00
|
|
|
|
|
|
|
|
/**
|
2020-12-29 22:45:16 -08:00
|
|
|
* A state machine representing a complete action to be performed by the robot. Commands are run by
|
|
|
|
|
* the {@link CommandScheduler}, and can be composed into CommandGroups to allow users to build
|
2022-12-26 14:32:13 -05:00
|
|
|
* complicated multistep actions without the need to roll the state machine logic themselves.
|
2019-08-25 17:47:07 -04:00
|
|
|
*
|
|
|
|
|
* <p>Commands are run synchronously from the main robot loop; no multithreading is used, unless
|
|
|
|
|
* specified explicitly from the command implementation.
|
2022-01-08 11:11:34 -08:00
|
|
|
*
|
|
|
|
|
* <p>This class is provided by the NewCommands VendorDep
|
2019-08-25 17:47:07 -04:00
|
|
|
*/
|
2025-10-03 20:42:47 -04:00
|
|
|
@NoDiscard("Commands must be used! Did you mean to bind it to a trigger?")
|
2023-07-14 01:12:01 -04:00
|
|
|
public abstract class Command implements Sendable {
|
2024-01-04 08:38:06 -08:00
|
|
|
/** Requirements set. */
|
2024-07-12 21:51:21 +08:00
|
|
|
private final Set<Subsystem> m_requirements = new HashSet<>();
|
2023-07-14 01:12:01 -04:00
|
|
|
|
2024-01-04 08:38:06 -08:00
|
|
|
/** Default constructor. */
|
2023-12-09 21:45:02 -08:00
|
|
|
@SuppressWarnings("this-escape")
|
2023-07-14 01:12:01 -04:00
|
|
|
protected Command() {
|
|
|
|
|
String name = getClass().getName();
|
|
|
|
|
SendableRegistry.add(this, name.substring(name.lastIndexOf('.') + 1));
|
|
|
|
|
}
|
|
|
|
|
|
2020-12-29 22:45:16 -08:00
|
|
|
/** The initial subroutine of a command. Called once when the command is initially scheduled. */
|
2023-07-14 01:12:01 -04:00
|
|
|
public void initialize() {}
|
2019-08-25 17:47:07 -04:00
|
|
|
|
2020-12-29 22:45:16 -08:00
|
|
|
/** The main body of a command. Called repeatedly while the command is scheduled. */
|
2023-07-14 01:12:01 -04:00
|
|
|
public void execute() {}
|
2019-08-25 17:47:07 -04:00
|
|
|
|
|
|
|
|
/**
|
2020-12-29 22:45:16 -08:00
|
|
|
* The action to take when the command ends. Called when either the command finishes normally, or
|
|
|
|
|
* when it interrupted/canceled.
|
2019-08-25 17:47:07 -04:00
|
|
|
*
|
2020-12-29 22:45:16 -08:00
|
|
|
* <p>Do not schedule commands here that share requirements with this command. Use {@link
|
|
|
|
|
* #andThen(Command...)} instead.
|
2020-03-28 19:18:06 +03:00
|
|
|
*
|
2019-08-25 17:47:07 -04:00
|
|
|
* @param interrupted whether the command was interrupted/canceled
|
|
|
|
|
*/
|
2023-07-14 01:12:01 -04:00
|
|
|
public void end(boolean interrupted) {}
|
2019-08-25 17:47:07 -04:00
|
|
|
|
|
|
|
|
/**
|
2020-12-29 22:45:16 -08:00
|
|
|
* Whether the command has finished. Once a command finishes, the scheduler will call its end()
|
|
|
|
|
* method and un-schedule it.
|
2019-08-25 17:47:07 -04:00
|
|
|
*
|
|
|
|
|
* @return whether the command has finished.
|
|
|
|
|
*/
|
2023-07-14 01:12:01 -04:00
|
|
|
public boolean isFinished() {
|
2019-08-25 17:47:07 -04:00
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
2020-12-29 22:45:16 -08:00
|
|
|
* Specifies the set of subsystems used by this command. Two commands cannot use the same
|
2022-08-30 07:53:47 +03:00
|
|
|
* subsystem at the same time. If another command is scheduled that shares a requirement, {@link
|
|
|
|
|
* #getInterruptionBehavior()} will be checked and followed. If no subsystems are required, return
|
|
|
|
|
* an empty set.
|
2019-08-25 17:47:07 -04:00
|
|
|
*
|
2020-12-29 22:45:16 -08:00
|
|
|
* <p>Note: it is recommended that user implementations contain the requirements as a field, and
|
|
|
|
|
* return that field here, rather than allocating a new set every time this is called.
|
2019-08-25 17:47:07 -04:00
|
|
|
*
|
|
|
|
|
* @return the set of subsystems that are required
|
2022-08-30 07:53:47 +03:00
|
|
|
* @see InterruptionBehavior
|
2019-08-25 17:47:07 -04:00
|
|
|
*/
|
2023-07-14 01:12:01 -04:00
|
|
|
public Set<Subsystem> getRequirements() {
|
|
|
|
|
return m_requirements;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Adds the specified subsystems to the requirements of the command. The scheduler will prevent
|
|
|
|
|
* two commands that require the same subsystem from being scheduled simultaneously.
|
|
|
|
|
*
|
|
|
|
|
* <p>Note that the scheduler determines the requirements of a command when it is scheduled, so
|
|
|
|
|
* this method should normally be called from the command's constructor.
|
|
|
|
|
*
|
|
|
|
|
* @param requirements the requirements to add
|
|
|
|
|
*/
|
|
|
|
|
public final void addRequirements(Subsystem... requirements) {
|
|
|
|
|
for (Subsystem requirement : requirements) {
|
|
|
|
|
m_requirements.add(requireNonNullParam(requirement, "requirement", "addRequirements"));
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2024-07-12 06:01:54 +08:00
|
|
|
/**
|
|
|
|
|
* Adds the specified subsystems to the requirements of the command. The scheduler will prevent
|
|
|
|
|
* two commands that require the same subsystem from being scheduled simultaneously.
|
|
|
|
|
*
|
|
|
|
|
* <p>Note that the scheduler determines the requirements of a command when it is scheduled, so
|
|
|
|
|
* this method should normally be called from the command's constructor.
|
|
|
|
|
*
|
|
|
|
|
* @param requirements the requirements to add
|
|
|
|
|
*/
|
|
|
|
|
public final void addRequirements(Collection<Subsystem> requirements) {
|
|
|
|
|
m_requirements.addAll(requirements);
|
|
|
|
|
}
|
|
|
|
|
|
2023-07-14 01:12:01 -04:00
|
|
|
/**
|
|
|
|
|
* Gets the name of this Command.
|
|
|
|
|
*
|
|
|
|
|
* <p>By default, the simple class name is used. This can be changed with {@link
|
|
|
|
|
* #setName(String)}.
|
|
|
|
|
*
|
|
|
|
|
* @return The display name of the Command
|
|
|
|
|
*/
|
|
|
|
|
public String getName() {
|
|
|
|
|
return SendableRegistry.getName(this);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Sets the name of this Command.
|
|
|
|
|
*
|
|
|
|
|
* @param name The display name of the Command.
|
|
|
|
|
*/
|
|
|
|
|
public void setName(String name) {
|
|
|
|
|
SendableRegistry.setName(this, name);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Gets the subsystem name of this Command.
|
|
|
|
|
*
|
|
|
|
|
* @return Subsystem name
|
|
|
|
|
*/
|
|
|
|
|
public String getSubsystem() {
|
|
|
|
|
return SendableRegistry.getSubsystem(this);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Sets the subsystem name of this Command.
|
|
|
|
|
*
|
|
|
|
|
* @param subsystem subsystem name
|
|
|
|
|
*/
|
|
|
|
|
public void setSubsystem(String subsystem) {
|
|
|
|
|
SendableRegistry.setSubsystem(this, subsystem);
|
|
|
|
|
}
|
2019-08-25 17:47:07 -04:00
|
|
|
|
|
|
|
|
/**
|
2020-12-29 22:45:16 -08:00
|
|
|
* Decorates this command with a timeout. If the specified timeout is exceeded before the command
|
2023-06-22 19:43:51 -07:00
|
|
|
* finishes normally, the command will be interrupted and un-scheduled.
|
2019-08-25 17:47:07 -04:00
|
|
|
*
|
2022-12-07 07:13:31 +02:00
|
|
|
* <p>Note: This decorator works by adding this command to a composition. The command the
|
|
|
|
|
* decorator was called on cannot be scheduled independently or be added to a different
|
|
|
|
|
* composition (namely, decorators), unless it is manually cleared from the list of composed
|
|
|
|
|
* commands with {@link CommandScheduler#removeComposedCommand(Command)}. The command composition
|
|
|
|
|
* returned from this method can be further decorated without issue.
|
2019-08-25 17:47:07 -04:00
|
|
|
*
|
|
|
|
|
* @param seconds the timeout duration
|
|
|
|
|
* @return the command with the timeout added
|
|
|
|
|
*/
|
2023-07-14 01:12:01 -04:00
|
|
|
public ParallelRaceGroup withTimeout(double seconds) {
|
2021-06-14 02:05:14 +03:00
|
|
|
return raceWith(new WaitCommand(seconds));
|
2019-08-25 17:47:07 -04:00
|
|
|
}
|
|
|
|
|
|
2024-04-22 13:34:52 +08:00
|
|
|
/**
|
|
|
|
|
* Decorates this command with a timeout. If the specified timeout is exceeded before the command
|
|
|
|
|
* finishes normally, the command will be interrupted and un-scheduled.
|
|
|
|
|
*
|
|
|
|
|
* <p>Note: This decorator works by adding this command to a composition. The command the
|
|
|
|
|
* decorator was called on cannot be scheduled independently or be added to a different
|
|
|
|
|
* composition (namely, decorators), unless it is manually cleared from the list of composed
|
|
|
|
|
* commands with {@link CommandScheduler#removeComposedCommand(Command)}. The command composition
|
|
|
|
|
* returned from this method can be further decorated without issue.
|
|
|
|
|
*
|
|
|
|
|
* @param time the timeout duration
|
|
|
|
|
* @return the command with the timeout added
|
|
|
|
|
*/
|
2024-09-07 13:59:29 -04:00
|
|
|
public ParallelRaceGroup withTimeout(Time time) {
|
|
|
|
|
return withTimeout(time.in(Seconds));
|
2024-04-22 13:34:52 +08:00
|
|
|
}
|
|
|
|
|
|
2019-08-25 17:47:07 -04:00
|
|
|
/**
|
2020-12-29 22:45:16 -08:00
|
|
|
* Decorates this command with an interrupt condition. If the specified condition becomes true
|
2023-04-30 14:09:02 -07:00
|
|
|
* before the command finishes normally, the command will be interrupted and un-scheduled.
|
2019-08-25 17:47:07 -04:00
|
|
|
*
|
2022-12-07 07:13:31 +02:00
|
|
|
* <p>Note: This decorator works by adding this command to a composition. The command the
|
|
|
|
|
* decorator was called on cannot be scheduled independently or be added to a different
|
|
|
|
|
* composition (namely, decorators), unless it is manually cleared from the list of composed
|
|
|
|
|
* commands with {@link CommandScheduler#removeComposedCommand(Command)}. The command composition
|
|
|
|
|
* returned from this method can be further decorated without issue.
|
2019-08-25 17:47:07 -04:00
|
|
|
*
|
|
|
|
|
* @param condition the interrupt condition
|
|
|
|
|
* @return the command with the interrupt condition added
|
2023-04-30 14:09:02 -07:00
|
|
|
* @see #onlyWhile(BooleanSupplier)
|
2019-08-25 17:47:07 -04:00
|
|
|
*/
|
2023-07-14 01:12:01 -04:00
|
|
|
public ParallelRaceGroup until(BooleanSupplier condition) {
|
2021-06-14 02:05:14 +03:00
|
|
|
return raceWith(new WaitUntilCommand(condition));
|
2019-08-25 17:47:07 -04:00
|
|
|
}
|
|
|
|
|
|
2023-04-30 14:09:02 -07:00
|
|
|
/**
|
|
|
|
|
* Decorates this command with a run condition. If the specified condition becomes false before
|
|
|
|
|
* the command finishes normally, the command will be interrupted and un-scheduled.
|
|
|
|
|
*
|
|
|
|
|
* <p>Note: This decorator works by adding this command to a composition. The command the
|
|
|
|
|
* decorator was called on cannot be scheduled independently or be added to a different
|
|
|
|
|
* composition (namely, decorators), unless it is manually cleared from the list of composed
|
|
|
|
|
* commands with {@link CommandScheduler#removeComposedCommand(Command)}. The command composition
|
|
|
|
|
* returned from this method can be further decorated without issue.
|
|
|
|
|
*
|
2023-06-22 19:43:51 -07:00
|
|
|
* @param condition the run condition
|
|
|
|
|
* @return the command with the run condition added
|
2023-04-30 14:09:02 -07:00
|
|
|
* @see #until(BooleanSupplier)
|
|
|
|
|
*/
|
2023-07-14 01:12:01 -04:00
|
|
|
public ParallelRaceGroup onlyWhile(BooleanSupplier condition) {
|
2023-04-30 14:09:02 -07:00
|
|
|
return until(() -> !condition.getAsBoolean());
|
|
|
|
|
}
|
|
|
|
|
|
2019-08-25 17:47:07 -04:00
|
|
|
/**
|
2019-10-19 11:13:33 -04:00
|
|
|
* Decorates this command with a runnable to run before this command starts.
|
2019-08-25 17:47:07 -04:00
|
|
|
*
|
2022-12-07 07:13:31 +02:00
|
|
|
* <p>Note: This decorator works by adding this command to a composition. The command the
|
|
|
|
|
* decorator was called on cannot be scheduled independently or be added to a different
|
|
|
|
|
* composition (namely, decorators), unless it is manually cleared from the list of composed
|
|
|
|
|
* commands with {@link CommandScheduler#removeComposedCommand(Command)}. The command composition
|
|
|
|
|
* returned from this method can be further decorated without issue.
|
2019-08-25 17:47:07 -04:00
|
|
|
*
|
2020-12-29 22:45:16 -08:00
|
|
|
* @param toRun the Runnable to run
|
2019-11-08 21:30:30 -05:00
|
|
|
* @param requirements the required subsystems
|
2019-08-25 17:47:07 -04:00
|
|
|
* @return the decorated command
|
|
|
|
|
*/
|
2023-07-14 01:12:01 -04:00
|
|
|
public SequentialCommandGroup beforeStarting(Runnable toRun, Subsystem... requirements) {
|
2021-06-14 02:05:14 +03:00
|
|
|
return beforeStarting(new InstantCommand(toRun, requirements));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Decorates this command with another command to run before this command starts.
|
|
|
|
|
*
|
2022-12-07 07:13:31 +02:00
|
|
|
* <p>Note: This decorator works by adding this command to a composition. The command the
|
|
|
|
|
* decorator was called on cannot be scheduled independently or be added to a different
|
|
|
|
|
* composition (namely, decorators), unless it is manually cleared from the list of composed
|
|
|
|
|
* commands with {@link CommandScheduler#removeComposedCommand(Command)}. The command composition
|
|
|
|
|
* returned from this method can be further decorated without issue.
|
2021-06-14 02:05:14 +03:00
|
|
|
*
|
|
|
|
|
* @param before the command to run before this one
|
|
|
|
|
* @return the decorated command
|
|
|
|
|
*/
|
2023-07-14 01:12:01 -04:00
|
|
|
public SequentialCommandGroup beforeStarting(Command before) {
|
2021-06-14 02:05:14 +03:00
|
|
|
return new SequentialCommandGroup(before, this);
|
2019-08-25 17:47:07 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
2019-10-19 11:13:33 -04:00
|
|
|
* Decorates this command with a runnable to run after the command finishes.
|
2019-08-25 17:47:07 -04:00
|
|
|
*
|
2022-12-07 07:13:31 +02:00
|
|
|
* <p>Note: This decorator works by adding this command to a composition. The command the
|
|
|
|
|
* decorator was called on cannot be scheduled independently or be added to a different
|
|
|
|
|
* composition (namely, decorators), unless it is manually cleared from the list of composed
|
|
|
|
|
* commands with {@link CommandScheduler#removeComposedCommand(Command)}. The command composition
|
|
|
|
|
* returned from this method can be further decorated without issue.
|
2019-08-25 17:47:07 -04:00
|
|
|
*
|
2020-12-29 22:45:16 -08:00
|
|
|
* @param toRun the Runnable to run
|
2019-11-08 21:30:30 -05:00
|
|
|
* @param requirements the required subsystems
|
2019-08-25 17:47:07 -04:00
|
|
|
* @return the decorated command
|
|
|
|
|
*/
|
2023-07-14 01:12:01 -04:00
|
|
|
public SequentialCommandGroup andThen(Runnable toRun, Subsystem... requirements) {
|
2021-06-14 02:05:14 +03:00
|
|
|
return andThen(new InstantCommand(toRun, requirements));
|
2019-08-25 17:47:07 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
2020-12-29 22:45:16 -08:00
|
|
|
* Decorates this command with a set of commands to run after it in sequence. Often more
|
2019-08-25 17:47:07 -04:00
|
|
|
* convenient/less-verbose than constructing a new {@link SequentialCommandGroup} explicitly.
|
|
|
|
|
*
|
2022-12-07 07:13:31 +02:00
|
|
|
* <p>Note: This decorator works by adding this command to a composition. The command the
|
|
|
|
|
* decorator was called on cannot be scheduled independently or be added to a different
|
|
|
|
|
* composition (namely, decorators), unless it is manually cleared from the list of composed
|
|
|
|
|
* commands with {@link CommandScheduler#removeComposedCommand(Command)}. The command composition
|
|
|
|
|
* returned from this method can be further decorated without issue.
|
2019-08-25 17:47:07 -04:00
|
|
|
*
|
|
|
|
|
* @param next the commands to run next
|
|
|
|
|
* @return the decorated command
|
|
|
|
|
*/
|
2023-07-14 01:12:01 -04:00
|
|
|
public SequentialCommandGroup andThen(Command... next) {
|
2019-08-25 17:47:07 -04:00
|
|
|
SequentialCommandGroup group = new SequentialCommandGroup(this);
|
|
|
|
|
group.addCommands(next);
|
|
|
|
|
return group;
|
|
|
|
|
}
|
|
|
|
|
|
2024-12-13 20:30:02 -05:00
|
|
|
/**
|
|
|
|
|
* Creates a new command that runs this command and the deadline in parallel, finishing (and
|
|
|
|
|
* interrupting this command) when the deadline finishes.
|
|
|
|
|
*
|
|
|
|
|
* <p>Note: This decorator works by adding this command to a composition. The command the
|
|
|
|
|
* decorator was called on cannot be scheduled independently or be added to a different
|
|
|
|
|
* composition (namely, decorators), unless it is manually cleared from the list of composed
|
|
|
|
|
* commands with {@link CommandScheduler#removeComposedCommand(Command)}. The command composition
|
|
|
|
|
* returned from this method can be further decorated without issue.
|
|
|
|
|
*
|
|
|
|
|
* @param deadline the deadline of the command group
|
|
|
|
|
* @return the decorated command
|
|
|
|
|
* @see Command#deadlineFor
|
|
|
|
|
*/
|
|
|
|
|
public ParallelDeadlineGroup withDeadline(Command deadline) {
|
|
|
|
|
return new ParallelDeadlineGroup(deadline, this);
|
|
|
|
|
}
|
|
|
|
|
|
2019-08-25 17:47:07 -04:00
|
|
|
/**
|
|
|
|
|
* Decorates this command with a set of commands to run parallel to it, ending when the calling
|
2020-12-29 22:45:16 -08:00
|
|
|
* command ends and interrupting all the others. Often more convenient/less-verbose than
|
2019-08-25 17:47:07 -04:00
|
|
|
* constructing a new {@link ParallelDeadlineGroup} explicitly.
|
|
|
|
|
*
|
2022-12-07 07:13:31 +02:00
|
|
|
* <p>Note: This decorator works by adding this command to a composition. The command the
|
|
|
|
|
* decorator was called on cannot be scheduled independently or be added to a different
|
|
|
|
|
* composition (namely, decorators), unless it is manually cleared from the list of composed
|
|
|
|
|
* commands with {@link CommandScheduler#removeComposedCommand(Command)}. The command composition
|
|
|
|
|
* returned from this method can be further decorated without issue.
|
2019-08-25 17:47:07 -04:00
|
|
|
*
|
|
|
|
|
* @param parallel the commands to run in parallel
|
|
|
|
|
* @return the decorated command
|
2024-04-29 03:02:29 +08:00
|
|
|
* @deprecated Use {@link deadlineFor} instead.
|
2019-08-25 17:47:07 -04:00
|
|
|
*/
|
2024-04-29 03:02:29 +08:00
|
|
|
@Deprecated(since = "2025", forRemoval = true)
|
2023-07-14 01:12:01 -04:00
|
|
|
public ParallelDeadlineGroup deadlineWith(Command... parallel) {
|
2019-08-25 17:47:07 -04:00
|
|
|
return new ParallelDeadlineGroup(this, parallel);
|
|
|
|
|
}
|
|
|
|
|
|
2024-04-29 03:02:29 +08:00
|
|
|
/**
|
|
|
|
|
* Decorates this command with a set of commands to run parallel to it, ending when the calling
|
|
|
|
|
* command ends and interrupting all the others. Often more convenient/less-verbose than
|
|
|
|
|
* constructing a new {@link ParallelDeadlineGroup} explicitly.
|
|
|
|
|
*
|
|
|
|
|
* <p>Note: This decorator works by adding this command to a composition. The command the
|
|
|
|
|
* decorator was called on cannot be scheduled independently or be added to a different
|
|
|
|
|
* composition (namely, decorators), unless it is manually cleared from the list of composed
|
|
|
|
|
* commands with {@link CommandScheduler#removeComposedCommand(Command)}. The command composition
|
|
|
|
|
* returned from this method can be further decorated without issue.
|
|
|
|
|
*
|
2024-08-17 10:44:34 -04:00
|
|
|
* @param parallel the commands to run in parallel. Note the parallel commands will be interrupted
|
2024-04-29 03:02:29 +08:00
|
|
|
* when the deadline command ends
|
|
|
|
|
* @return the decorated command
|
2024-12-13 20:30:02 -05:00
|
|
|
* @see Command#withDeadline
|
2024-04-29 03:02:29 +08:00
|
|
|
*/
|
|
|
|
|
public ParallelDeadlineGroup deadlineFor(Command... parallel) {
|
|
|
|
|
return new ParallelDeadlineGroup(this, parallel);
|
|
|
|
|
}
|
|
|
|
|
|
2019-08-25 17:47:07 -04:00
|
|
|
/**
|
|
|
|
|
* Decorates this command with a set of commands to run parallel to it, ending when the last
|
2020-12-29 22:45:16 -08:00
|
|
|
* command ends. Often more convenient/less-verbose than constructing a new {@link
|
|
|
|
|
* ParallelCommandGroup} explicitly.
|
2019-08-25 17:47:07 -04:00
|
|
|
*
|
2022-12-07 07:13:31 +02:00
|
|
|
* <p>Note: This decorator works by adding this command to a composition. The command the
|
|
|
|
|
* decorator was called on cannot be scheduled independently or be added to a different
|
|
|
|
|
* composition (namely, decorators), unless it is manually cleared from the list of composed
|
|
|
|
|
* commands with {@link CommandScheduler#removeComposedCommand(Command)}. The command composition
|
|
|
|
|
* returned from this method can be further decorated without issue.
|
2019-08-25 17:47:07 -04:00
|
|
|
*
|
|
|
|
|
* @param parallel the commands to run in parallel
|
|
|
|
|
* @return the decorated command
|
|
|
|
|
*/
|
2023-07-14 01:12:01 -04:00
|
|
|
public ParallelCommandGroup alongWith(Command... parallel) {
|
2019-08-25 17:47:07 -04:00
|
|
|
ParallelCommandGroup group = new ParallelCommandGroup(this);
|
|
|
|
|
group.addCommands(parallel);
|
|
|
|
|
return group;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Decorates this command with a set of commands to run parallel to it, ending when the first
|
2020-12-29 22:45:16 -08:00
|
|
|
* command ends. Often more convenient/less-verbose than constructing a new {@link
|
|
|
|
|
* ParallelRaceGroup} explicitly.
|
2019-08-25 17:47:07 -04:00
|
|
|
*
|
2022-12-07 07:13:31 +02:00
|
|
|
* <p>Note: This decorator works by adding this command to a composition. The command the
|
|
|
|
|
* decorator was called on cannot be scheduled independently or be added to a different
|
|
|
|
|
* composition (namely, decorators), unless it is manually cleared from the list of composed
|
|
|
|
|
* commands with {@link CommandScheduler#removeComposedCommand(Command)}. The command composition
|
|
|
|
|
* returned from this method can be further decorated without issue.
|
2019-08-25 17:47:07 -04:00
|
|
|
*
|
|
|
|
|
* @param parallel the commands to run in parallel
|
|
|
|
|
* @return the decorated command
|
|
|
|
|
*/
|
2023-07-14 01:12:01 -04:00
|
|
|
public ParallelRaceGroup raceWith(Command... parallel) {
|
2019-08-25 17:47:07 -04:00
|
|
|
ParallelRaceGroup group = new ParallelRaceGroup(this);
|
|
|
|
|
group.addCommands(parallel);
|
|
|
|
|
return group;
|
|
|
|
|
}
|
|
|
|
|
|
2022-04-08 08:02:08 +03:00
|
|
|
/**
|
|
|
|
|
* Decorates this command to run repeatedly, restarting it when it ends, until this command is
|
|
|
|
|
* interrupted. The decorated command can still be canceled.
|
|
|
|
|
*
|
2022-12-07 07:13:31 +02:00
|
|
|
* <p>Note: This decorator works by adding this command to a composition. The command the
|
|
|
|
|
* decorator was called on cannot be scheduled independently or be added to a different
|
|
|
|
|
* composition (namely, decorators), unless it is manually cleared from the list of composed
|
|
|
|
|
* commands with {@link CommandScheduler#removeComposedCommand(Command)}. The command composition
|
|
|
|
|
* returned from this method can be further decorated without issue.
|
2022-04-08 08:02:08 +03:00
|
|
|
*
|
|
|
|
|
* @return the decorated command
|
|
|
|
|
*/
|
2023-07-14 01:12:01 -04:00
|
|
|
public RepeatCommand repeatedly() {
|
2022-04-08 08:02:08 +03:00
|
|
|
return new RepeatCommand(this);
|
|
|
|
|
}
|
|
|
|
|
|
2019-08-25 17:47:07 -04:00
|
|
|
/**
|
2024-04-28 00:41:04 -05:00
|
|
|
* Decorates this command to run "by proxy" by wrapping it in a {@link ProxyCommand}. Use this for
|
|
|
|
|
* "forking off" from command compositions when the user does not wish to extend the command's
|
|
|
|
|
* requirements to the entire command composition. ProxyCommand has unique implications and
|
|
|
|
|
* semantics, see the WPILib docs for a full explanation.
|
2019-08-25 17:47:07 -04:00
|
|
|
*
|
|
|
|
|
* @return the decorated command
|
2024-04-28 00:41:04 -05:00
|
|
|
* @see ProxyCommand
|
|
|
|
|
* @see <a
|
|
|
|
|
* href="https://docs.wpilib.org/en/stable/docs/software/commandbased/command-compositions.html#scheduling-other-commands">WPILib
|
|
|
|
|
* docs</a>
|
2019-08-25 17:47:07 -04:00
|
|
|
*/
|
2023-07-14 01:12:01 -04:00
|
|
|
public ProxyCommand asProxy() {
|
2022-11-29 00:43:10 +02:00
|
|
|
return new ProxyCommand(this);
|
2019-08-25 17:47:07 -04:00
|
|
|
}
|
|
|
|
|
|
2022-05-24 10:22:19 -06:00
|
|
|
/**
|
|
|
|
|
* Decorates this command to only run if this condition is not met. If the command is already
|
|
|
|
|
* running and the condition changes to true, the command will not stop running. The requirements
|
2022-12-26 14:32:13 -05:00
|
|
|
* of this command will be kept for the new conditional command.
|
2022-05-24 10:22:19 -06:00
|
|
|
*
|
2023-04-30 14:09:02 -07:00
|
|
|
* <p>Note: This decorator works by adding this command to a composition. The command the
|
|
|
|
|
* decorator was called on cannot be scheduled independently or be added to a different
|
|
|
|
|
* composition (namely, decorators), unless it is manually cleared from the list of composed
|
|
|
|
|
* commands with {@link CommandScheduler#removeComposedCommand(Command)}. The command composition
|
|
|
|
|
* returned from this method can be further decorated without issue.
|
|
|
|
|
*
|
2022-05-24 10:22:19 -06:00
|
|
|
* @param condition the condition that will prevent the command from running
|
|
|
|
|
* @return the decorated command
|
2023-04-30 14:09:02 -07:00
|
|
|
* @see #onlyIf(BooleanSupplier)
|
2022-05-24 10:22:19 -06:00
|
|
|
*/
|
2023-07-14 01:12:01 -04:00
|
|
|
public ConditionalCommand unless(BooleanSupplier condition) {
|
2022-05-24 10:22:19 -06:00
|
|
|
return new ConditionalCommand(new InstantCommand(), this, condition);
|
|
|
|
|
}
|
|
|
|
|
|
2023-04-30 14:09:02 -07:00
|
|
|
/**
|
|
|
|
|
* Decorates this command to only run if this condition is met. If the command is already running
|
|
|
|
|
* and the condition changes to false, the command will not stop running. The requirements of this
|
|
|
|
|
* command will be kept for the new conditional command.
|
|
|
|
|
*
|
|
|
|
|
* <p>Note: This decorator works by adding this command to a composition. The command the
|
|
|
|
|
* decorator was called on cannot be scheduled independently or be added to a different
|
|
|
|
|
* composition (namely, decorators), unless it is manually cleared from the list of composed
|
|
|
|
|
* commands with {@link CommandScheduler#removeComposedCommand(Command)}. The command composition
|
|
|
|
|
* returned from this method can be further decorated without issue.
|
|
|
|
|
*
|
|
|
|
|
* @param condition the condition that will allow the command to run
|
|
|
|
|
* @return the decorated command
|
|
|
|
|
* @see #unless(BooleanSupplier)
|
|
|
|
|
*/
|
2023-07-14 01:12:01 -04:00
|
|
|
public ConditionalCommand onlyIf(BooleanSupplier condition) {
|
2023-04-30 14:09:02 -07:00
|
|
|
return unless(() -> !condition.getAsBoolean());
|
|
|
|
|
}
|
|
|
|
|
|
2022-06-24 20:52:53 +03:00
|
|
|
/**
|
|
|
|
|
* Decorates this command to run or stop when disabled.
|
|
|
|
|
*
|
|
|
|
|
* @param doesRunWhenDisabled true to run when disabled.
|
|
|
|
|
* @return the decorated command
|
|
|
|
|
*/
|
2023-07-14 01:12:01 -04:00
|
|
|
public WrapperCommand ignoringDisable(boolean doesRunWhenDisabled) {
|
2022-06-24 20:52:53 +03:00
|
|
|
return new WrapperCommand(this) {
|
|
|
|
|
@Override
|
|
|
|
|
public boolean runsWhenDisabled() {
|
|
|
|
|
return doesRunWhenDisabled;
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|
|
2019-08-25 17:47:07 -04:00
|
|
|
/**
|
2022-08-30 07:53:47 +03:00
|
|
|
* Decorates this command to have a different {@link InterruptionBehavior interruption behavior}.
|
2019-08-25 17:47:07 -04:00
|
|
|
*
|
2022-08-30 07:53:47 +03:00
|
|
|
* @param interruptBehavior the desired interrupt behavior
|
|
|
|
|
* @return the decorated command
|
2019-08-25 17:47:07 -04:00
|
|
|
*/
|
2023-07-14 01:12:01 -04:00
|
|
|
public WrapperCommand withInterruptBehavior(InterruptionBehavior interruptBehavior) {
|
2022-08-30 07:53:47 +03:00
|
|
|
return new WrapperCommand(this) {
|
|
|
|
|
@Override
|
|
|
|
|
public InterruptionBehavior getInterruptionBehavior() {
|
|
|
|
|
return interruptBehavior;
|
|
|
|
|
}
|
|
|
|
|
};
|
2019-08-25 17:47:07 -04:00
|
|
|
}
|
|
|
|
|
|
2022-10-11 19:53:27 +03:00
|
|
|
/**
|
|
|
|
|
* Decorates this command with a lambda to call on interrupt or end, following the command's
|
|
|
|
|
* inherent {@link #end(boolean)} method.
|
|
|
|
|
*
|
|
|
|
|
* @param end a lambda accepting a boolean parameter specifying whether the command was
|
|
|
|
|
* interrupted.
|
|
|
|
|
* @return the decorated command
|
|
|
|
|
*/
|
2023-07-14 01:12:01 -04:00
|
|
|
public WrapperCommand finallyDo(BooleanConsumer end) {
|
2022-10-11 19:53:27 +03:00
|
|
|
requireNonNullParam(end, "end", "Command.finallyDo()");
|
|
|
|
|
return new WrapperCommand(this) {
|
|
|
|
|
@Override
|
|
|
|
|
public void end(boolean interrupted) {
|
|
|
|
|
super.end(interrupted);
|
|
|
|
|
end.accept(interrupted);
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|
|
2023-11-03 15:21:21 -07:00
|
|
|
/**
|
|
|
|
|
* Decorates this command with a lambda to call on interrupt or end, following the command's
|
|
|
|
|
* inherent {@link #end(boolean)} method. The provided lambda will run identically in both
|
|
|
|
|
* interrupt and end cases.
|
|
|
|
|
*
|
|
|
|
|
* @param end a lambda to run when the command ends, whether or not it was interrupted.
|
|
|
|
|
* @return the decorated command
|
|
|
|
|
*/
|
|
|
|
|
public WrapperCommand finallyDo(Runnable end) {
|
|
|
|
|
return finallyDo(interrupted -> end.run());
|
|
|
|
|
}
|
|
|
|
|
|
2022-10-11 19:53:27 +03:00
|
|
|
/**
|
|
|
|
|
* Decorates this command with a lambda to call on interrupt, following the command's inherent
|
|
|
|
|
* {@link #end(boolean)} method.
|
|
|
|
|
*
|
|
|
|
|
* @param handler a lambda to run when the command is interrupted
|
|
|
|
|
* @return the decorated command
|
|
|
|
|
*/
|
2023-07-14 01:12:01 -04:00
|
|
|
public WrapperCommand handleInterrupt(Runnable handler) {
|
2022-10-11 19:53:27 +03:00
|
|
|
requireNonNullParam(handler, "handler", "Command.handleInterrupt()");
|
|
|
|
|
return finallyDo(
|
|
|
|
|
interrupted -> {
|
|
|
|
|
if (interrupted) {
|
|
|
|
|
handler.run();
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
2025-07-02 16:46:59 -04:00
|
|
|
/**
|
|
|
|
|
* Schedules this command.
|
|
|
|
|
*
|
|
|
|
|
* @deprecated Use CommandScheduler.getInstance().schedule(Command...) instead
|
|
|
|
|
*/
|
|
|
|
|
@Deprecated(since = "2025", forRemoval = true)
|
2023-07-14 01:12:01 -04:00
|
|
|
public void schedule() {
|
2022-08-30 07:53:47 +03:00
|
|
|
CommandScheduler.getInstance().schedule(this);
|
2019-08-25 17:47:07 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
2022-08-30 07:53:47 +03:00
|
|
|
* Cancels this command. Will call {@link #end(boolean) end(true)}. Commands will be canceled
|
|
|
|
|
* regardless of {@link InterruptionBehavior interruption behavior}.
|
|
|
|
|
*
|
|
|
|
|
* @see CommandScheduler#cancel(Command...)
|
2019-08-25 17:47:07 -04:00
|
|
|
*/
|
2023-07-14 01:12:01 -04:00
|
|
|
public void cancel() {
|
2019-08-25 17:47:07 -04:00
|
|
|
CommandScheduler.getInstance().cancel(this);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
2022-12-26 14:32:13 -05:00
|
|
|
* Whether the command is currently scheduled. Note that this does not detect whether the command
|
|
|
|
|
* is in a composition, only whether it is directly being run by the scheduler.
|
2019-08-25 17:47:07 -04:00
|
|
|
*
|
|
|
|
|
* @return Whether the command is scheduled.
|
|
|
|
|
*/
|
2023-07-14 01:12:01 -04:00
|
|
|
public boolean isScheduled() {
|
2019-08-25 17:47:07 -04:00
|
|
|
return CommandScheduler.getInstance().isScheduled(this);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
2021-06-14 02:05:14 +03:00
|
|
|
* Whether the command requires a given subsystem.
|
2019-08-25 17:47:07 -04:00
|
|
|
*
|
|
|
|
|
* @param requirement the subsystem to inquire about
|
|
|
|
|
* @return whether the subsystem is required
|
|
|
|
|
*/
|
2023-07-14 01:12:01 -04:00
|
|
|
public boolean hasRequirement(Subsystem requirement) {
|
2019-08-25 17:47:07 -04:00
|
|
|
return getRequirements().contains(requirement);
|
|
|
|
|
}
|
|
|
|
|
|
2022-08-30 07:53:47 +03:00
|
|
|
/**
|
|
|
|
|
* How the command behaves when another command with a shared requirement is scheduled.
|
|
|
|
|
*
|
|
|
|
|
* @return a variant of {@link InterruptionBehavior}, defaulting to {@link
|
|
|
|
|
* InterruptionBehavior#kCancelSelf kCancelSelf}.
|
|
|
|
|
*/
|
2023-07-14 01:12:01 -04:00
|
|
|
public InterruptionBehavior getInterruptionBehavior() {
|
2022-08-30 07:53:47 +03:00
|
|
|
return InterruptionBehavior.kCancelSelf;
|
|
|
|
|
}
|
|
|
|
|
|
2019-08-25 17:47:07 -04:00
|
|
|
/**
|
2020-12-29 22:45:16 -08:00
|
|
|
* Whether the given command should run when the robot is disabled. Override to return true if the
|
|
|
|
|
* command should run when disabled.
|
2019-08-25 17:47:07 -04:00
|
|
|
*
|
|
|
|
|
* @return whether the command should run when the robot is disabled
|
|
|
|
|
*/
|
2023-07-14 01:12:01 -04:00
|
|
|
public boolean runsWhenDisabled() {
|
2019-08-25 17:47:07 -04:00
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
2022-10-23 22:08:22 +03:00
|
|
|
/**
|
2022-12-16 04:28:52 +02:00
|
|
|
* Decorates this Command with a name.
|
2022-10-23 22:08:22 +03:00
|
|
|
*
|
|
|
|
|
* @param name name
|
|
|
|
|
* @return the decorated Command
|
|
|
|
|
*/
|
2023-07-14 01:12:01 -04:00
|
|
|
public WrapperCommand withName(String name) {
|
2022-12-16 04:28:52 +02:00
|
|
|
WrapperCommand wrapper = new WrapperCommand(Command.this) {};
|
|
|
|
|
wrapper.setName(name);
|
|
|
|
|
return wrapper;
|
2022-10-23 22:08:22 +03:00
|
|
|
}
|
|
|
|
|
|
2023-07-14 01:12:01 -04:00
|
|
|
@Override
|
|
|
|
|
public void initSendable(SendableBuilder builder) {
|
|
|
|
|
builder.setSmartDashboardType("Command");
|
|
|
|
|
builder.addStringProperty(".name", this::getName, null);
|
|
|
|
|
builder.addBooleanProperty(
|
|
|
|
|
"running",
|
|
|
|
|
this::isScheduled,
|
|
|
|
|
value -> {
|
|
|
|
|
if (value) {
|
|
|
|
|
if (!isScheduled()) {
|
2025-07-02 16:46:59 -04:00
|
|
|
CommandScheduler.getInstance().schedule(this);
|
2023-07-14 01:12:01 -04:00
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
if (isScheduled()) {
|
|
|
|
|
cancel();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
builder.addBooleanProperty(
|
|
|
|
|
".isParented", () -> CommandScheduler.getInstance().isComposed(this), null);
|
|
|
|
|
builder.addStringProperty(
|
|
|
|
|
"interruptBehavior", () -> getInterruptionBehavior().toString(), null);
|
|
|
|
|
builder.addBooleanProperty("runsWhenDisabled", this::runsWhenDisabled, null);
|
|
|
|
|
}
|
|
|
|
|
|
2022-08-30 07:53:47 +03:00
|
|
|
/**
|
|
|
|
|
* An enum describing the command's behavior when another command with a shared requirement is
|
|
|
|
|
* scheduled.
|
|
|
|
|
*/
|
2023-07-14 01:12:01 -04:00
|
|
|
public enum InterruptionBehavior {
|
2022-08-30 07:53:47 +03:00
|
|
|
/**
|
|
|
|
|
* This command ends, {@link #end(boolean) end(true)} is called, and the incoming command is
|
|
|
|
|
* scheduled normally.
|
|
|
|
|
*
|
|
|
|
|
* <p>This is the default behavior.
|
|
|
|
|
*/
|
|
|
|
|
kCancelSelf,
|
|
|
|
|
/** This command continues, and the incoming command is not scheduled. */
|
|
|
|
|
kCancelIncoming
|
|
|
|
|
}
|
2019-08-25 17:47:07 -04:00
|
|
|
}
|