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}