WPILibC++ 2025.2.1
Loading...
Searching...
No Matches
Command.h
Go to the documentation of this file.
1// Copyright (c) FIRST and other WPILib contributors.
2// Open Source Software; you can modify and/or share it under the terms of
3// the WPILib BSD license file in the root directory of this project.
4
5#pragma once
6
7#include <functional>
8#include <memory>
9#include <optional>
10#include <string>
11
12#include <units/time.h>
13#include <wpi/Demangle.h>
14#include <wpi/SmallSet.h>
15#include <wpi/StackTrace.h>
17
20
21namespace frc2 {
22
23/**
24 * A state machine representing a complete action to be performed by the robot.
25 * Commands are run by the CommandScheduler, and can be composed into
26 * CommandGroups to allow users to build complicated multi-step actions without
27 * the need to roll the state machine logic themselves.
28 *
29 * <p>Commands are run synchronously from the main robot loop; no
30 * multithreading is used, unless specified explicitly from the command
31 * implementation.
32 *
33 * <p>Note: ALWAYS create a subclass by extending CommandHelper<Base, Subclass>,
34 * or decorators will not function!
35 *
36 * This class is provided by the NewCommands VendorDep
37 *
38 * @see CommandScheduler
39 * @see CommandHelper
40 */
41class Command : public wpi::Sendable, public wpi::SendableHelper<Command> {
42 public:
43 ~Command() override;
44
45 Command(const Command&) = default;
47 Command(Command&&) = default;
48 Command& operator=(Command&&) = default;
49
50 /**
51 * The initial subroutine of a command. Called once when the command is
52 * initially scheduled.
53 */
54 virtual void Initialize();
55
56 /**
57 * The main body of a command. Called repeatedly while the command is
58 * scheduled.
59 */
60 virtual void Execute();
61
62 /**
63 * The action to take when the command ends. Called when either the command
64 * finishes normally, or when it interrupted/canceled.
65 *
66 * @param interrupted whether the command was interrupted/canceled
67 */
68 virtual void End(bool interrupted);
69
70 /**
71 * Whether the command has finished. Once a command finishes, the scheduler
72 * will call its end() method and un-schedule it.
73 *
74 * @return whether the command has finished.
75 */
76 virtual bool IsFinished() { return false; }
77
78 /**
79 * Specifies the set of subsystems used by this command. Two commands cannot
80 * use the same subsystem at the same time. If another command is scheduled
81 * that shares a requirement, GetInterruptionBehavior() will be checked and
82 * followed. If no subsystems are required, return an empty set.
83 *
84 * <p>Note: it is recommended that user implementations contain the
85 * requirements as a field, and return that field here, rather than allocating
86 * a new set every time this is called.
87 *
88 * @return the set of subsystems that are required
89 * @see InterruptionBehavior
90 */
92
93 /**
94 * Adds the specified Subsystem requirements to the command.
95 *
96 * The scheduler will prevent two commands that require the same subsystem
97 * from being scheduled simultaneously.
98 *
99 * Note that the scheduler determines the requirements of a command when it
100 * is scheduled, so this method should normally be called from the command's
101 * constructor.
102 *
103 * While this overload can be used with {@code AddRequirements({&subsystem1,
104 * &subsystem2})}, {@code AddRequirements({&subsystem})} selects the {@code
105 * AddRequirements(Subsystem*)} overload, which will function identically but
106 * may cause warnings about redundant braces.
107 *
108 * @param requirements the Subsystem requirements to add, which can be
109 * implicitly constructed from an initializer list or a span
110 */
111 void AddRequirements(Requirements requirements);
112
113 /**
114 * Adds the specified Subsystem requirements to the command.
115 *
116 * The scheduler will prevent two commands that require the same subsystem
117 * from being scheduled simultaneously.
118 *
119 * Note that the scheduler determines the requirements of a command when it
120 * is scheduled, so this method should normally be called from the command's
121 * constructor.
122 *
123 * @param requirements the Subsystem requirements to add
124 */
126
127 /**
128 * Adds the specified Subsystem requirement to the command.
129 *
130 * The scheduler will prevent two commands that require the same subsystem
131 * from being scheduled simultaneously.
132 *
133 * Note that the scheduler determines the requirements of a command when it
134 * is scheduled, so this method should normally be called from the command's
135 * constructor.
136 *
137 * @param requirement the Subsystem requirement to add
138 */
139 void AddRequirements(Subsystem* requirement);
140
141 /**
142 * Gets the name of this Command.
143 *
144 * @return Name
145 */
146 std::string GetName() const;
147
148 /**
149 * Sets the name of this Command.
150 *
151 * @param name name
152 */
153 void SetName(std::string_view name);
154
155 /**
156 * Gets the subsystem name of this Command.
157 *
158 * @return Subsystem name
159 */
160 std::string GetSubsystem() const;
161
162 /**
163 * Sets the subsystem name of this Command.
164 *
165 * @param subsystem subsystem name
166 */
167 void SetSubsystem(std::string_view subsystem);
168
169 /**
170 * An enum describing the command's behavior when another command with a
171 * shared requirement is scheduled.
172 */
174 /**
175 * This command ends, End(true) is called, and the incoming command is
176 * scheduled normally.
177 *
178 * <p>This is the default behavior.
179 */
181 /** This command continues, and the incoming command is not scheduled. */
183 };
184
185 friend class CommandPtr;
186
187 /**
188 * Decorates this command with a timeout. If the specified timeout is
189 * exceeded before the command finishes normally, the command will be
190 * interrupted and un-scheduled.
191 *
192 * @param duration the timeout duration
193 * @return the command with the timeout added
194 */
195 [[nodiscard]]
196 CommandPtr WithTimeout(units::second_t duration) &&;
197
198 /**
199 * Decorates this command with an interrupt condition. If the specified
200 * condition becomes true before the command finishes normally, the command
201 * will be interrupted and un-scheduled.
202 *
203 * @param condition the interrupt condition
204 * @return the command with the interrupt condition added
205 */
206 [[nodiscard]]
207 CommandPtr Until(std::function<bool()> condition) &&;
208
209 /**
210 * Decorates this command with a run condition. If the specified condition
211 * becomes false before the command finishes normally, the command will be
212 * interrupted and un-scheduled.
213 *
214 * @param condition the run condition
215 * @return the command with the run condition added
216 */
217 [[nodiscard]]
218 CommandPtr OnlyWhile(std::function<bool()> condition) &&;
219
220 /**
221 * Decorates this command with a runnable to run before this command starts.
222 *
223 * @param toRun the Runnable to run
224 * @param requirements the required subsystems
225 * @return the decorated command
226 */
227 [[nodiscard]]
228 CommandPtr BeforeStarting(std::function<void()> toRun,
229 Requirements requirements = {}) &&;
230
231 /**
232 * Decorates this command with another command to run before this command
233 * starts.
234 *
235 * @param before the command to run before this one
236 * @return the decorated command
237 */
238 [[nodiscard]]
240
241 /**
242 * Decorates this command with a runnable to run after the command finishes.
243 *
244 * @param toRun the Runnable to run
245 * @param requirements the required subsystems
246 * @return the decorated command
247 */
248 [[nodiscard]]
249 CommandPtr AndThen(std::function<void()> toRun,
250 Requirements requirements = {}) &&;
251
252 /**
253 * Decorates this command with a set of commands to run after it in sequence.
254 * Often more convenient/less-verbose than constructing a
255 * SequentialCommandGroup explicitly.
256 *
257 * @param next the commands to run next
258 * @return the decorated command
259 */
260 [[nodiscard]]
262
263 /**
264 * Decorates this command to run repeatedly, restarting it when it ends, until
265 * this command is interrupted. The decorated command can still be canceled.
266 *
267 * @return the decorated command
268 */
269 [[nodiscard]]
271
272 /**
273 * Decorates this command to run "by proxy" by wrapping it in a ProxyCommand.
274 * Use this for "forking off" from command compositions when the user does not
275 * wish to extend the command's requirements to the entire command
276 * composition. ProxyCommand has unique implications and semantics, see <a
277 * href="https://docs.wpilib.org/en/stable/docs/software/commandbased/command-compositions.html#scheduling-other-commands">the
278 * WPILib docs</a> for a full explanation.
279 *
280 * <p>This overload transfers command ownership to the returned CommandPtr.
281 *
282 * @return the decorated command
283 * @see ProxyCommand
284 */
285 [[nodiscard]]
287
288 /**
289 * Decorates this command to only run if this condition is not met. If the
290 * command is already running and the condition changes to true, the command
291 * will not stop running. The requirements of this command will be kept for
292 * the new conditional command.
293 *
294 * @param condition the condition that will prevent the command from running
295 * @return the decorated command
296 */
297 [[nodiscard]]
298 CommandPtr Unless(std::function<bool()> condition) &&;
299
300 /**
301 * Decorates this command to only run if this condition is met. If the command
302 * is already running and the condition changes to false, the command will not
303 * stop running. The requirements of this command will be kept for the new
304 * conditional command.
305 *
306 * @param condition the condition that will allow the command to run
307 * @return the decorated command
308 */
309 [[nodiscard]]
310 CommandPtr OnlyIf(std::function<bool()> condition) &&;
311
312 /**
313 * Creates a new command that runs this command and the deadline in parallel,
314 * finishing (and interrupting this command) when the deadline finishes.
315 *
316 * @param deadline the deadline of the command group
317 * @return the decorated command
318 * @see DeadlineFor
319 */
321
322 /**
323 * Decorates this command with a set of commands to run parallel to it, ending
324 * when the calling command ends and interrupting all the others. Often more
325 * convenient/less-verbose than constructing a new {@link
326 * ParallelDeadlineGroup} explicitly.
327 *
328 * @param parallel the commands to run in parallel. Note the parallel commands
329 * will be interupted when the deadline command ends
330 * @return the decorated command
331 * @see WithDeadline
332 */
333 [[nodiscard]]
335
336 /**
337 * Decorates this command with a set of commands to run parallel to it, ending
338 * when the last command ends. Often more convenient/less-verbose than
339 * constructing a new {@link ParallelCommandGroup} explicitly.
340 *
341 * @param parallel the commands to run in parallel
342 * @return the decorated command
343 */
344 [[nodiscard]]
346
347 /**
348 * Decorates this command with a set of commands to run parallel to it, ending
349 * when the first command ends. Often more convenient/less-verbose than
350 * constructing a new {@link ParallelRaceGroup} explicitly.
351 *
352 * @param parallel the commands to run in parallel
353 * @return the decorated command
354 */
355 [[nodiscard]]
357
358 /**
359 * Decorates this command to run or stop when disabled.
360 *
361 * @param doesRunWhenDisabled true to run when disabled.
362 * @return the decorated command
363 */
364 [[nodiscard]]
365 CommandPtr IgnoringDisable(bool doesRunWhenDisabled) &&;
366
367 /**
368 * Decorates this command to have a different interrupt behavior.
369 *
370 * @param interruptBehavior the desired interrupt behavior
371 * @return the decorated command
372 */
373 [[nodiscard]]
375 Command::InterruptionBehavior interruptBehavior) &&;
376
377 /**
378 * Decorates this command with a lambda to call on interrupt or end, following
379 * the command's inherent Command::End(bool) method.
380 *
381 * @param end a lambda accepting a boolean parameter specifying whether the
382 * command was interrupted.
383 * @return the decorated command
384 */
385 [[nodiscard]]
386 CommandPtr FinallyDo(std::function<void(bool)> end) &&;
387
388 /**
389 * Decorates this command with a lambda to call on interrupt or end, following
390 * the command's inherent Command::End(bool) method. The provided lambda will
391 * run identically in both interrupt and end cases.
392 *
393 * @param end a lambda to run when the command ends, whether or not it was
394 * interrupted.
395 * @return the decorated command
396 */
397 [[nodiscard]]
398 CommandPtr FinallyDo(std::function<void()> end) &&;
399
400 /**
401 * Decorates this command with a lambda to call on interrupt, following the
402 * command's inherent Command::End(bool) method.
403 *
404 * @param handler a lambda to run when the command is interrupted
405 * @return the decorated command
406 */
407 [[nodiscard]]
408 CommandPtr HandleInterrupt(std::function<void()> handler) &&;
409
410 /**
411 * Decorates this Command with a name.
412 *
413 * @param name name
414 * @return the decorated Command
415 */
416 [[nodiscard]]
417 CommandPtr WithName(std::string_view name) &&;
418
419 /**
420 * Schedules this command.
421 */
422 void Schedule();
423
424 /**
425 * Cancels this command. Will call End(true). Commands will be canceled
426 * regardless of interruption behavior.
427 */
428 void Cancel();
429
430 /**
431 * Whether or not the command is currently scheduled. Note that this does not
432 * detect whether the command is in a composition, only whether it is directly
433 * being run by the scheduler.
434 *
435 * @return Whether the command is scheduled.
436 */
437 bool IsScheduled() const;
438
439 /**
440 * Whether the command requires a given subsystem. Named "HasRequirement"
441 * rather than "requires" to avoid confusion with Command::Requires(Subsystem)
442 * -- this may be able to be changed in a few years.
443 *
444 * @param requirement the subsystem to inquire about
445 * @return whether the subsystem is required
446 */
447 bool HasRequirement(Subsystem* requirement) const;
448
449 /**
450 * Whether the command is currently grouped in a command group. Used as extra
451 * insurance to prevent accidental independent use of grouped commands.
452 */
453 bool IsComposed() const;
454
455 /**
456 * Sets whether the command is currently composed in a command composition.
457 * Can be used to "reclaim" a command if a composition is no longer going to
458 * use it. NOT ADVISED!
459 */
460 void SetComposed(bool isComposed);
461
462 /**
463 * Get the stacktrace of where this command was composed, or an empty
464 * optional. Intended for internal use.
465 *
466 * @return optional string representation of the composition site stack trace.
467 */
468 std::optional<std::string> GetPreviousCompositionSite() const;
469
470 /**
471 * Whether the given command should run when the robot is disabled. Override
472 * to return true if the command should run when disabled.
473 *
474 * @return whether the command should run when the robot is disabled
475 */
476 virtual bool RunsWhenDisabled() const { return false; }
477
478 /**
479 * How the command behaves when another command with a shared requirement is
480 * scheduled.
481 *
482 * @return a variant of InterruptionBehavior, defaulting to kCancelSelf.
483 */
487
488 /**
489 * Transfers ownership of this command to a unique pointer. Used for
490 * decorator methods.
491 */
492 virtual CommandPtr ToPtr() && = 0;
493
494 void InitSendable(wpi::SendableBuilder& builder) override;
495
496 protected:
498
499 private:
500 /// Requirements set.
501 wpi::SmallSet<Subsystem*, 4> m_requirements;
502
503 std::optional<std::string> m_previousComposition;
504};
505
506/**
507 * Checks if two commands have disjoint requirement sets.
508 *
509 * @param first The first command to check.
510 * @param second The second command to check.
511 * @return False if first and second share a requirement.
512 */
514} // namespace frc2
This file defines the SmallSet class.
A state machine representing a complete action to be performed by the robot.
Definition Command.h:41
bool IsScheduled() const
Whether or not the command is currently scheduled.
void Cancel()
Cancels this command.
std::string GetSubsystem() const
Gets the subsystem name of this Command.
CommandPtr AsProxy() &&
Decorates this command to run "by proxy" by wrapping it in a ProxyCommand.
virtual void End(bool interrupted)
The action to take when the command ends.
void InitSendable(wpi::SendableBuilder &builder) override
Initializes this Sendable object.
void AddRequirements(Requirements requirements)
Adds the specified Subsystem requirements to the command.
Command(Command &&)=default
CommandPtr HandleInterrupt(std::function< void()> handler) &&
Decorates this command with a lambda to call on interrupt, following the command's inherent Command::...
CommandPtr FinallyDo(std::function< void()> end) &&
Decorates this command with a lambda to call on interrupt or end, following the command's inherent Co...
CommandPtr WithTimeout(units::second_t duration) &&
Decorates this command with a timeout.
~Command() override
CommandPtr WithDeadline(CommandPtr &&deadline) &&
Creates a new command that runs this command and the deadline in parallel, finishing (and interruptin...
CommandPtr AndThen(CommandPtr &&next) &&
Decorates this command with a set of commands to run after it in sequence.
CommandPtr BeforeStarting(CommandPtr &&before) &&
Decorates this command with another command to run before this command starts.
void AddRequirements(Subsystem *requirement)
Adds the specified Subsystem requirement to the command.
CommandPtr Repeatedly() &&
Decorates this command to run repeatedly, restarting it when it ends, until this command is interrupt...
std::optional< std::string > GetPreviousCompositionSite() const
Get the stacktrace of where this command was composed, or an empty optional.
void SetName(std::string_view name)
Sets the name of this Command.
virtual bool RunsWhenDisabled() const
Whether the given command should run when the robot is disabled.
Definition Command.h:476
CommandPtr BeforeStarting(std::function< void()> toRun, Requirements requirements={}) &&
Decorates this command with a runnable to run before this command starts.
CommandPtr WithInterruptBehavior(Command::InterruptionBehavior interruptBehavior) &&
Decorates this command to have a different interrupt behavior.
CommandPtr FinallyDo(std::function< void(bool)> end) &&
Decorates this command with a lambda to call on interrupt or end, following the command's inherent Co...
CommandPtr WithName(std::string_view name) &&
Decorates this Command with a name.
bool IsComposed() const
Whether the command is currently grouped in a command group.
Command(const Command &)=default
virtual wpi::SmallSet< Subsystem *, 4 > GetRequirements() const
Specifies the set of subsystems used by this command.
CommandPtr Until(std::function< bool()> condition) &&
Decorates this command with an interrupt condition.
virtual void Execute()
The main body of a command.
void AddRequirements(wpi::SmallSet< Subsystem *, 4 > requirements)
Adds the specified Subsystem requirements to the command.
CommandPtr OnlyWhile(std::function< bool()> condition) &&
Decorates this command with a run condition.
CommandPtr OnlyIf(std::function< bool()> condition) &&
Decorates this command to only run if this condition is met.
Command & operator=(const Command &rhs)
virtual InterruptionBehavior GetInterruptionBehavior() const
How the command behaves when another command with a shared requirement is scheduled.
Definition Command.h:484
CommandPtr AlongWith(CommandPtr &&parallel) &&
Decorates this command with a set of commands to run parallel to it, ending when the last command end...
std::string GetName() const
Gets the name of this Command.
virtual CommandPtr ToPtr() &&=0
Transfers ownership of this command to a unique pointer.
CommandPtr DeadlineFor(CommandPtr &&parallel) &&
Decorates this command with a set of commands to run parallel to it, ending when the calling command ...
CommandPtr IgnoringDisable(bool doesRunWhenDisabled) &&
Decorates this command to run or stop when disabled.
void SetComposed(bool isComposed)
Sets whether the command is currently composed in a command composition.
bool HasRequirement(Subsystem *requirement) const
Whether the command requires a given subsystem.
virtual void Initialize()
The initial subroutine of a command.
void Schedule()
Schedules this command.
void SetSubsystem(std::string_view subsystem)
Sets the subsystem name of this Command.
InterruptionBehavior
An enum describing the command's behavior when another command with a shared requirement is scheduled...
Definition Command.h:173
@ kCancelSelf
This command ends, End(true) is called, and the incoming command is scheduled normally.
@ kCancelIncoming
This command continues, and the incoming command is not scheduled.
CommandPtr RaceWith(CommandPtr &&parallel) &&
Decorates this command with a set of commands to run parallel to it, ending when the first command en...
Command & operator=(Command &&)=default
CommandPtr AndThen(std::function< void()> toRun, Requirements requirements={}) &&
Decorates this command with a runnable to run after the command finishes.
virtual bool IsFinished()
Whether the command has finished.
Definition Command.h:76
CommandPtr Unless(std::function< bool()> condition) &&
Decorates this command to only run if this condition is not met.
A wrapper around std::unique_ptr<Command> so commands have move-only semantics.
Definition CommandPtr.h:28
Represents requirements for a command, which is a set of (pointers to) subsystems.
Definition Requirements.h:20
A robot subsystem.
Definition Subsystem.h:43
Helper class for building Sendable dashboard representations.
Definition SendableBuilder.h:21
A helper class for use with objects that add themselves to SendableRegistry.
Definition SendableHelper.h:21
Interface for Sendable objects.
Definition Sendable.h:16
SmallSet - This maintains a set of unique values, optimizing for the case when the set is small (less...
Definition SmallSet.h:135
Definition FunctionalCommand.h:13
bool RequirementsDisjoint(Command *first, Command *second)
Checks if two commands have disjoint requirement sets.