001// Copyright (c) FIRST and other WPILib contributors.
002// Open Source Software; you can modify and/or share it under the terms of
003// the WPILib BSD license file in the root directory of this project.
004
005package edu.wpi.first.wpilibj2.command;
006
007import java.util.Set;
008import java.util.function.BooleanSupplier;
009
010/**
011 * A state machine representing a complete action to be performed by the robot. Commands are run by
012 * the {@link CommandScheduler}, and can be composed into CommandGroups to allow users to build
013 * complicated multi-step actions without the need to roll the state machine logic themselves.
014 *
015 * <p>Commands are run synchronously from the main robot loop; no multithreading is used, unless
016 * specified explicitly from the command implementation.
017 */
018public interface Command {
019  /** The initial subroutine of a command. Called once when the command is initially scheduled. */
020  default void initialize() {}
021
022  /** The main body of a command. Called repeatedly while the command is scheduled. */
023  default void execute() {}
024
025  /**
026   * The action to take when the command ends. Called when either the command finishes normally, or
027   * when it interrupted/canceled.
028   *
029   * <p>Do not schedule commands here that share requirements with this command. Use {@link
030   * #andThen(Command...)} instead.
031   *
032   * @param interrupted whether the command was interrupted/canceled
033   */
034  default void end(boolean interrupted) {}
035
036  /**
037   * Whether the command has finished. Once a command finishes, the scheduler will call its end()
038   * method and un-schedule it.
039   *
040   * @return whether the command has finished.
041   */
042  default boolean isFinished() {
043    return false;
044  }
045
046  /**
047   * Specifies the set of subsystems used by this command. Two commands cannot use the same
048   * subsystem at the same time. If the command is scheduled as interruptible and another command is
049   * scheduled that shares a requirement, the command will be interrupted. Else, the command will
050   * not be scheduled. If no subsystems are required, return an empty set.
051   *
052   * <p>Note: it is recommended that user implementations contain the requirements as a field, and
053   * return that field here, rather than allocating a new set every time this is called.
054   *
055   * @return the set of subsystems that are required
056   */
057  Set<Subsystem> getRequirements();
058
059  /**
060   * Decorates this command with a timeout. If the specified timeout is exceeded before the command
061   * finishes normally, the command will be interrupted and un-scheduled. Note that the timeout only
062   * applies to the command returned by this method; the calling command is not itself changed.
063   *
064   * <p>Note: This decorator works by composing this command within a CommandGroup. The command
065   * cannot be used independently after being decorated, or be re-decorated with a different
066   * decorator, unless it is manually cleared from the list of grouped commands with {@link
067   * CommandGroupBase#clearGroupedCommand(Command)}. The decorated command can, however, be further
068   * decorated without issue.
069   *
070   * @param seconds the timeout duration
071   * @return the command with the timeout added
072   */
073  default ParallelRaceGroup withTimeout(double seconds) {
074    return raceWith(new WaitCommand(seconds));
075  }
076
077  /**
078   * Decorates this command with an interrupt condition. If the specified condition becomes true
079   * before the command finishes normally, the command will be interrupted and un-scheduled. Note
080   * that this only applies to the command returned by this method; the calling command is not
081   * itself changed.
082   *
083   * <p>Note: This decorator works by composing this command within a CommandGroup. The command
084   * cannot be used independently after being decorated, or be re-decorated with a different
085   * decorator, unless it is manually cleared from the list of grouped commands with {@link
086   * CommandGroupBase#clearGroupedCommand(Command)}. The decorated command can, however, be further
087   * decorated without issue.
088   *
089   * @param condition the interrupt condition
090   * @return the command with the interrupt condition added
091   */
092  default ParallelRaceGroup withInterrupt(BooleanSupplier condition) {
093    return raceWith(new WaitUntilCommand(condition));
094  }
095
096  /**
097   * Decorates this command with a runnable to run before this command starts.
098   *
099   * <p>Note: This decorator works by composing this command within a CommandGroup. The command
100   * cannot be used independently after being decorated, or be re-decorated with a different
101   * decorator, unless it is manually cleared from the list of grouped commands with {@link
102   * CommandGroupBase#clearGroupedCommand(Command)}. The decorated command can, however, be further
103   * decorated without issue.
104   *
105   * @param toRun the Runnable to run
106   * @param requirements the required subsystems
107   * @return the decorated command
108   */
109  default SequentialCommandGroup beforeStarting(Runnable toRun, Subsystem... requirements) {
110    return beforeStarting(new InstantCommand(toRun, requirements));
111  }
112
113  /**
114   * Decorates this command with another command to run before this command starts.
115   *
116   * <p>Note: This decorator works by composing this command within a CommandGroup. The command
117   * cannot be used independently after being decorated, or be re-decorated with a different
118   * decorator, unless it is manually cleared from the list of grouped commands with {@link
119   * CommandGroupBase#clearGroupedCommand(Command)}. The decorated command can, however, be further
120   * decorated without issue.
121   *
122   * @param before the command to run before this one
123   * @return the decorated command
124   */
125  default SequentialCommandGroup beforeStarting(Command before) {
126    return new SequentialCommandGroup(before, this);
127  }
128
129  /**
130   * Decorates this command with a runnable to run after the command finishes.
131   *
132   * <p>Note: This decorator works by composing this command within a CommandGroup. The command
133   * cannot be used independently after being decorated, or be re-decorated with a different
134   * decorator, unless it is manually cleared from the list of grouped commands with {@link
135   * CommandGroupBase#clearGroupedCommand(Command)}. The decorated command can, however, be further
136   * decorated without issue.
137   *
138   * @param toRun the Runnable to run
139   * @param requirements the required subsystems
140   * @return the decorated command
141   */
142  default SequentialCommandGroup andThen(Runnable toRun, Subsystem... requirements) {
143    return andThen(new InstantCommand(toRun, requirements));
144  }
145
146  /**
147   * Decorates this command with a set of commands to run after it in sequence. Often more
148   * convenient/less-verbose than constructing a new {@link SequentialCommandGroup} explicitly.
149   *
150   * <p>Note: This decorator works by composing this command within a CommandGroup. The command
151   * cannot be used independently after being decorated, or be re-decorated with a different
152   * decorator, unless it is manually cleared from the list of grouped commands with {@link
153   * CommandGroupBase#clearGroupedCommand(Command)}. The decorated command can, however, be further
154   * decorated without issue.
155   *
156   * @param next the commands to run next
157   * @return the decorated command
158   */
159  default SequentialCommandGroup andThen(Command... next) {
160    SequentialCommandGroup group = new SequentialCommandGroup(this);
161    group.addCommands(next);
162    return group;
163  }
164
165  /**
166   * Decorates this command with a set of commands to run parallel to it, ending when the calling
167   * command ends and interrupting all the others. Often more convenient/less-verbose than
168   * constructing a new {@link ParallelDeadlineGroup} explicitly.
169   *
170   * <p>Note: This decorator works by composing this command within a CommandGroup. The command
171   * cannot be used independently after being decorated, or be re-decorated with a different
172   * decorator, unless it is manually cleared from the list of grouped commands with {@link
173   * CommandGroupBase#clearGroupedCommand(Command)}. The decorated command can, however, be further
174   * decorated without issue.
175   *
176   * @param parallel the commands to run in parallel
177   * @return the decorated command
178   */
179  default ParallelDeadlineGroup deadlineWith(Command... parallel) {
180    return new ParallelDeadlineGroup(this, parallel);
181  }
182
183  /**
184   * Decorates this command with a set of commands to run parallel to it, ending when the last
185   * command ends. Often more convenient/less-verbose than constructing a new {@link
186   * ParallelCommandGroup} explicitly.
187   *
188   * <p>Note: This decorator works by composing this command within a CommandGroup. The command
189   * cannot be used independently after being decorated, or be re-decorated with a different
190   * decorator, unless it is manually cleared from the list of grouped commands with {@link
191   * CommandGroupBase#clearGroupedCommand(Command)}. The decorated command can, however, be further
192   * decorated without issue.
193   *
194   * @param parallel the commands to run in parallel
195   * @return the decorated command
196   */
197  default ParallelCommandGroup alongWith(Command... parallel) {
198    ParallelCommandGroup group = new ParallelCommandGroup(this);
199    group.addCommands(parallel);
200    return group;
201  }
202
203  /**
204   * Decorates this command with a set of commands to run parallel to it, ending when the first
205   * command ends. Often more convenient/less-verbose than constructing a new {@link
206   * ParallelRaceGroup} explicitly.
207   *
208   * <p>Note: This decorator works by composing this command within a CommandGroup. The command
209   * cannot be used independently after being decorated, or be re-decorated with a different
210   * decorator, unless it is manually cleared from the list of grouped commands with {@link
211   * CommandGroupBase#clearGroupedCommand(Command)}. The decorated command can, however, be further
212   * decorated without issue.
213   *
214   * @param parallel the commands to run in parallel
215   * @return the decorated command
216   */
217  default ParallelRaceGroup raceWith(Command... parallel) {
218    ParallelRaceGroup group = new ParallelRaceGroup(this);
219    group.addCommands(parallel);
220    return group;
221  }
222
223  /**
224   * Decorates this command to run perpetually, ignoring its ordinary end conditions. The decorated
225   * command can still be interrupted or canceled.
226   *
227   * <p>Note: This decorator works by composing this command within a CommandGroup. The command
228   * cannot be used independently after being decorated, or be re-decorated with a different
229   * decorator, unless it is manually cleared from the list of grouped commands with {@link
230   * CommandGroupBase#clearGroupedCommand(Command)}. The decorated command can, however, be further
231   * decorated without issue.
232   *
233   * @return the decorated command
234   */
235  default PerpetualCommand perpetually() {
236    return new PerpetualCommand(this);
237  }
238
239  /**
240   * Decorates this command to run "by proxy" by wrapping it in a {@link ProxyScheduleCommand}. This
241   * is useful for "forking off" from command groups when the user does not wish to extend the
242   * command's requirements to the entire command group.
243   *
244   * @return the decorated command
245   */
246  default ProxyScheduleCommand asProxy() {
247    return new ProxyScheduleCommand(this);
248  }
249
250  /**
251   * Schedules this command.
252   *
253   * @param interruptible whether this command can be interrupted by another command that shares one
254   *     of its requirements
255   */
256  default void schedule(boolean interruptible) {
257    CommandScheduler.getInstance().schedule(interruptible, this);
258  }
259
260  /** Schedules this command, defaulting to interruptible. */
261  default void schedule() {
262    schedule(true);
263  }
264
265  /**
266   * Cancels this command. Will call the command's interrupted() method. Commands will be canceled
267   * even if they are not marked as interruptible.
268   */
269  default void cancel() {
270    CommandScheduler.getInstance().cancel(this);
271  }
272
273  /**
274   * Whether or not the command is currently scheduled. Note that this does not detect whether the
275   * command is being run by a CommandGroup, only whether it is directly being run by the scheduler.
276   *
277   * @return Whether the command is scheduled.
278   */
279  default boolean isScheduled() {
280    return CommandScheduler.getInstance().isScheduled(this);
281  }
282
283  /**
284   * Whether the command requires a given subsystem.
285   *
286   * @param requirement the subsystem to inquire about
287   * @return whether the subsystem is required
288   */
289  default boolean hasRequirement(Subsystem requirement) {
290    return getRequirements().contains(requirement);
291  }
292
293  /**
294   * Whether the given command should run when the robot is disabled. Override to return true if the
295   * command should run when disabled.
296   *
297   * @return whether the command should run when the robot is disabled
298   */
299  default boolean runsWhenDisabled() {
300    return false;
301  }
302
303  /**
304   * Gets the name of this Command.
305   *
306   * @return Name
307   */
308  default String getName() {
309    return this.getClass().getSimpleName();
310  }
311}