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 org.wpilib.commands3; 006 007import static edu.wpi.first.util.ErrorMessages.requireNonNullParam; 008 009import edu.wpi.first.units.measure.Time; 010import java.util.Collection; 011import java.util.Collections; 012import java.util.Set; 013import java.util.function.BooleanSupplier; 014import java.util.function.Consumer; 015import org.wpilib.annotation.NoDiscard; 016 017/** 018 * Performs some task using one or more {@link Mechanism mechanisms}. Commands are fundamentally 019 * backed by a {@link Coroutine} that can be used to write imperative code that runs asynchronously. 020 * 021 * <p>Programmers familiar with the earlier versions of the command framework can think of a v3 022 * command similar to a v1 or v2 command that executes the lifecycle methods in a single method, as 023 * demonstrated in the example below. (Note, however, that more sophisticated code than this is 024 * possible! 025 * 026 * <pre>{@code 027 * coroutine -> { 028 * initialize(); 029 * while (!isFinished()) { 030 * execute(); 031 * coroutine.yield(); // be sure to yield at the end of the loop 032 * } 033 * end(); 034 * } 035 * }</pre> 036 * 037 * <p><strong>Note:</strong> Because coroutines are <i>opt-in</i> collaborate constructs, every 038 * command implementation <strong>must</strong> call {@link Coroutine#yield()} within any periodic 039 * loop. Failure to do so may result in an unrecoverable infinite loop. 040 * 041 * <h2>Requirements</h2> 042 * 043 * <p>Commands require zero or more mechanisms. To prevent conflicting control requests from running 044 * simultaneously (for example, commanding an elevator to both raise and lower at the same time), a 045 * running command has <i>exclusive ownership</i> of all of its required mechanisms. If another 046 * command with an equal or greater {@link #priority()} is scheduled that requires one or more of 047 * those same mechanisms, it will interrupt and cancel the running command. 048 * 049 * <p>The recommended way to create a command is using {@link Mechanism#run(Consumer)} or a related 050 * factory method to create commands that require a single mechanism (for example, a command that 051 * drives an elevator up and down or rotates an arm). Commands may be <i>composed</i> into {@link 052 * ParallelGroup parallel groups} and {@link SequentialGroup sequences} to build more complex 053 * behavior out of fundamental building blocks. These built-in compositions will require every 054 * mechanism used by every command in them, even if those commands aren't always running, and thus 055 * can leave certain required mechanisms in an <i>uncommanded</i> state: owned, but not used, this 056 * can lead to mechanisms sagging under gravity or running the previous motor control request they 057 * were given. 058 * 059 * <h2>Advanced Usage</h2> 060 * 061 * <p>For example, a hypothetical drive-and-score sequence could be coded in two ways: one with a 062 * sequence chain, or one that uses the lower-level coroutine API. Coroutines can be used in an 063 * async/await style that you may be familiar with from languages like JavaScript, Python, or C# 064 * (note that there is no {@code async} keyword; commands are inherently asynchronous). Nested 065 * commands may be forked and awaited, but will not outlive the command that forked them; there is 066 * no analog for something like a {@code ScheduleCommand} from the v2 commands framework. 067 * 068 * <pre>{@code 069 * class Robot extends TimedRobot { 070 * private final Drivetrain drivetrain = new Drivetrain(); 071 * private final Elevator elevator = new Elevator(); 072 * private final Gripper gripper = new Gripper(); 073 * 074 * // Basic sequence builder - owns all 3 mechanisms for the full duration, 075 * // even when they're not being used 076 * private Command basicScoringSequence() { 077 * return drivetrain.driveToScoringLocation() 078 * .andThen(elevator.moveToScoringHeight()) 079 * .andThen(gripper.release()) 080 * .named("Scoring Sequence (Basic)"); 081 * } 082 * 083 * // Advanced sequence with async/await - only owns mechanisms while they're 084 * // being used, allowing default commands or other user-triggered commands 085 * // to run when not in use. Interrupting one of the inner commands while it's 086 * // running will cancel the entire sequence. 087 * private Command advancedScoringSequence() { 088 * return Command.noRequirements().executing(coroutine -> { 089 * coroutine.await(drivetrain.driveToScoringLocation()); 090 * coroutine.await(elevator.moveToScoringHeight()); 091 * coroutine.await(gripper.release()); 092 * }).named("Scoring Sequence (Advanced)"); 093 * } 094 * } 095 * }</pre> 096 */ 097@NoDiscard("Commands must be used! Did you mean to fork it or bind it to a trigger?") 098public interface Command { 099 /** The default command priority. */ 100 int DEFAULT_PRIORITY = 0; 101 102 /** 103 * The lowest possible command priority. Commands with the lowest priority can be interrupted by 104 * any other command, including other minimum-priority commands. 105 */ 106 int LOWEST_PRIORITY = Integer.MIN_VALUE; 107 108 /** 109 * The highest possible command priority. Commands with the highest priority can only be 110 * interrupted by other maximum-priority commands. 111 */ 112 int HIGHEST_PRIORITY = Integer.MAX_VALUE; 113 114 /** 115 * Runs the command. Commands that need to periodically run until a goal state is reached should 116 * simply run a while loop like {@code while (!atGoal()) { ... } } and call {@link 117 * Coroutine#yield()} at the end of the loop. 118 * 119 * <p><strong>Warning:</strong> any loops in a command must call {@code coroutine.yield()}. 120 * Failure to do so will prevent anything else in your robot code from running. Commands are 121 * <i>opt-in</i> collaborative constructs; don't be greedy! 122 * 123 * @param coroutine the coroutine backing the command's execution 124 */ 125 void run(Coroutine coroutine); 126 127 /** 128 * An optional lifecycle hook that can be implemented to execute some code whenever this command 129 * is canceled before it naturally completes. Commands should be careful to do a single-shot 130 * cleanup (for example, setting a motor to zero volts) and not do any complex looping logic here. 131 */ 132 default void onCancel() { 133 // NOP by default 134 } 135 136 /** 137 * The name of the command. 138 * 139 * @return the name of the command 140 */ 141 @NoDiscard 142 String name(); 143 144 /** 145 * The mechanisms required by the command. This is used by the scheduler to determine if two 146 * commands conflict with each other. No mechanism may be required by more than one running 147 * command at a time. 148 * 149 * @return the set of mechanisms required by the command 150 */ 151 @NoDiscard 152 Set<Mechanism> requirements(); 153 154 /** 155 * The priority of the command. If a command is scheduled that conflicts with another running or 156 * pending command, their priority values are compared to determine which should run. If the 157 * scheduled command is lower priority than the running command, then it will not be scheduled and 158 * the running command will continue to run. If it is the same or higher priority, then the 159 * running command will be canceled and the scheduled command will start to run. 160 * 161 * @return the priority of the command 162 */ 163 @NoDiscard 164 default int priority() { 165 return DEFAULT_PRIORITY; 166 } 167 168 /** 169 * Checks if this command has a lower {@link #priority() priority} than another command. 170 * 171 * @param other the command to compare with 172 * @return true if this command has a lower priority than the other one, false otherwise 173 */ 174 @NoDiscard 175 default boolean isLowerPriorityThan(Command other) { 176 requireNonNullParam(other, "other", "Command.isLowerPriorityThan"); 177 178 return priority() < other.priority(); 179 } 180 181 /** 182 * Checks if this command requires a particular mechanism. 183 * 184 * @param mechanism the mechanism to check 185 * @return true if the mechanism is required, false if not 186 */ 187 @NoDiscard 188 default boolean requires(Mechanism mechanism) { 189 return requirements().contains(mechanism); 190 } 191 192 /** 193 * Checks if this command conflicts with another command. 194 * 195 * @param other the commands to check against 196 * @return true if both commands require at least one of the same mechanism, false if both 197 * commands have completely different requirements 198 */ 199 @NoDiscard 200 default boolean conflictsWith(Command other) { 201 requireNonNullParam(other, "other", "Command.conflictsWith"); 202 203 return !Collections.disjoint(requirements(), other.requirements()); 204 } 205 206 /** 207 * Creates a new command that runs this one for a maximum duration, after which it is forcibly 208 * canceled. This is particularly useful for autonomous routines where you want to prevent your 209 * entire autonomous period spent stuck on a single action because a mechanism doesn't quite reach 210 * its setpoint (for example, spinning up a flywheel or driving to a particular location on the 211 * field). The resulting command will have the same name as this one, with the timeout period 212 * appended. 213 * 214 * @param timeout the maximum duration that the command is permitted to run. Negative or zero 215 * values will result in the command running only once before being canceled. 216 * @return the timed out command. 217 */ 218 default Command withTimeout(Time timeout) { 219 requireNonNullParam(timeout, "timeout", "Command.withTimeout"); 220 221 return race(this, waitFor(timeout).named("Timeout: " + timeout.toLongString())) 222 .named(name() + " [" + timeout.toLongString() + " timeout]"); 223 } 224 225 /** 226 * Creates a command that does not require any hardware; that is, it does not affect the state of 227 * any physical objects. This is useful for commands that do some cleanup or state management, 228 * such as resetting odometry or sensors, that you don't want to interrupt a command that's 229 * controlling the mechanisms it affects. 230 * 231 * <p>More configuration options are needed after calling this function before the command can be 232 * created. See {@link StagedCommandBuilder} for details. 233 * 234 * @return a builder that can be used to configure the resulting command 235 */ 236 static NeedsExecutionBuilderStage noRequirements() { 237 return new StagedCommandBuilder().noRequirements(); 238 } 239 240 /** 241 * Creates a command that requires one or more mechanisms. 242 * 243 * <p>More configuration options are needed after calling this function before the command can be 244 * created. See {@link StagedCommandBuilder} for details. 245 * 246 * @param requirement The first required mechanism 247 * @param rest Any other required mechanisms 248 * @return A command builder 249 */ 250 static NeedsExecutionBuilderStage requiring(Mechanism requirement, Mechanism... rest) { 251 // parameters will be null checked by the builder 252 return new StagedCommandBuilder().requiring(requirement, rest); 253 } 254 255 /** 256 * Creates command that requires some number of mechanisms. 257 * 258 * <p>More configuration options are needed after calling this function before the command can be 259 * created. See {@link StagedCommandBuilder} for details. 260 * 261 * @param requirements The required mechanisms. May be empty, but cannot contain null values. 262 * @return A command builder 263 */ 264 static NeedsExecutionBuilderStage requiring(Collection<Mechanism> requirements) { 265 // parameters will be null checked by the builder 266 return new StagedCommandBuilder().requiring(requirements); 267 } 268 269 /** 270 * Starts creating a command that runs a group of multiple commands in parallel. The command will 271 * complete when every command in the group has completed naturally. 272 * 273 * <p>More configuration options are needed after calling this function before the command can be 274 * created. See {@link ParallelGroupBuilder} for details. 275 * 276 * @param commands The commands to run in parallel 277 * @return A command builder 278 */ 279 static ParallelGroupBuilder parallel(Command... commands) { 280 // parameters will be null checked by the builder 281 return new ParallelGroupBuilder().requiring(commands); 282 } 283 284 /** 285 * Starts creating a command that runs a group of multiple commands in parallel. The command will 286 * complete when any command in the group has completed naturally; all other commands in the group 287 * will be canceled. 288 * 289 * <p>More configuration options are needed after calling this function before the command can be 290 * created. See {@link ParallelGroupBuilder} for details. 291 * 292 * @param commands The commands to run in parallel 293 * @return A command builder 294 */ 295 static ParallelGroupBuilder race(Command... commands) { 296 // parameters will be null checked by the builder 297 return new ParallelGroupBuilder().optional(commands); 298 } 299 300 /** 301 * Starts creating a command that runs a group of multiple commands in sequence. The command will 302 * complete when the last command in the group has completed naturally. Commands in the group will 303 * run in the order they're passed to this method. 304 * 305 * <p>More configuration options are needed after calling this function before the command can be 306 * created. See {@link SequentialGroupBuilder} for details. 307 * 308 * @param commands The commands to run in sequence. 309 * @return A command builder 310 */ 311 static SequentialGroupBuilder sequence(Command... commands) { 312 // parameters will be null checked by the builder 313 return new SequentialGroupBuilder().andThen(commands); 314 } 315 316 /** 317 * Starts creating a command that simply waits for some condition to be met. The command will not 318 * require any mechanisms. 319 * 320 * <p>More configuration options are needed after calling this function before the command can be 321 * created. See {@link StagedCommandBuilder} for details. 322 * 323 * @param condition The condition to wait for 324 * @return A command builder 325 */ 326 static NeedsNameBuilderStage waitUntil(BooleanSupplier condition) { 327 requireNonNullParam(condition, "condition", "Command.waitUntil"); 328 329 return noRequirements().executing(coroutine -> coroutine.waitUntil(condition)); 330 } 331 332 /** 333 * Creates a command that simply waits for a given duration. The command will not require any 334 * mechanisms. 335 * 336 * @param duration How long to wait 337 * @return A command builder 338 */ 339 static NeedsNameBuilderStage waitFor(Time duration) { 340 requireNonNullParam(duration, "duration", "Command.waitFor"); 341 342 return noRequirements().executing(coroutine -> coroutine.wait(duration)); 343 } 344 345 /** 346 * Creates a command that runs this one and ends when the end condition is met (if this command 347 * has not already exited by then). 348 * 349 * <p>More configuration options are needed after calling this function before the command can be 350 * created. See {@link ParallelGroupBuilder} for details. 351 * 352 * @param endCondition The end condition to wait for. 353 * @return The waiting command 354 */ 355 default ParallelGroupBuilder until(BooleanSupplier endCondition) { 356 requireNonNullParam(endCondition, "endCondition", "Command.until"); 357 358 return new ParallelGroupBuilder() 359 .optional(this, Command.waitUntil(endCondition).named("Until Condition")); 360 } 361 362 /** 363 * Creates a command sequence, starting from this command and then running the next one. More 364 * commands can be added with the builder before naming and creating the sequence. 365 * 366 * <pre>{@code 367 * Sequence aThenBThenC = 368 * commandA() 369 * .andThen(commandB()) 370 * .andThen(commandC()) 371 * .withAutomaticName(); 372 * }</pre> 373 * 374 * @param next The command to run after this one in the sequence 375 * @return A sequence builder 376 */ 377 default SequentialGroupBuilder andThen(Command next) { 378 // parameter will be null checked by the builder 379 return new SequentialGroupBuilder().andThen(this).andThen(next); 380 } 381 382 /** 383 * Creates a parallel command group, running this command alongside one or more other commands. 384 * The group will exit once every command has finished. 385 * 386 * <p>More configuration options are needed after calling this function before the command can be 387 * created. See {@link ParallelGroupBuilder} for details. 388 * 389 * <pre>{@code 390 * ParallelGroup abc = 391 * commandA() 392 * .alongWith(commandB(), commandC()) 393 * .withAutomaticName(); 394 * }</pre> 395 * 396 * @param parallel The commands to run in parallel with this one 397 * @return A parallel group builder 398 */ 399 default ParallelGroupBuilder alongWith(Command... parallel) { 400 return new ParallelGroupBuilder().requiring(this).requiring(parallel); 401 } 402 403 /** 404 * Creates a parallel command group, running this command alongside one or more other commands. 405 * The group will exit after any command finishes. 406 * 407 * <p>More configuration options are needed after calling this function before the command can be 408 * created. See {@link ParallelGroupBuilder} for details. 409 * 410 * @param parallel The commands to run in parallel with this one 411 * @return A parallel group builder 412 */ 413 default ParallelGroupBuilder raceWith(Command... parallel) { 414 return new ParallelGroupBuilder().optional(this).optional(parallel); 415 } 416}