WPILibC++ 2027.0.0-alpha-4
Loading...
Searching...
No Matches
Command.hpp
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
14#include "wpi/units/time.hpp"
15#include "wpi/util/Demangle.hpp"
16#include "wpi/util/SmallSet.hpp"
19
20namespace wpi::cmd {
21
22/**
23 * A state machine representing a complete action to be performed by the robot.
24 * Commands are run by the CommandScheduler, and can be composed into
25 * CommandGroups to allow users to build complicated multi-step actions without
26 * the need to roll the state machine logic themselves.
27 *
28 * <p>Commands are run synchronously from the main robot loop; no
29 * multithreading is used, unless specified explicitly from the command
30 * implementation.
31 *
32 * <p>Note: ALWAYS create a subclass by extending CommandHelper<Base, Subclass>,
33 * or decorators will not function!
34 *
35 * This class is provided by the NewCommands VendorDep
36 *
37 * @see CommandScheduler
38 * @see CommandHelper
39 */
41 public wpi::util::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 CommandPtr WithTimeout(wpi::units::second_t duration) &&;
196
197 /**
198 * Decorates this command with an interrupt condition. If the specified
199 * condition becomes true before the command finishes normally, the command
200 * will be interrupted and un-scheduled.
201 *
202 * @param condition the interrupt condition
203 * @return the command with the interrupt condition added
204 */
205 CommandPtr Until(std::function<bool()> condition) &&;
206
207 /**
208 * Decorates this command with a run condition. If the specified condition
209 * becomes false before the command finishes normally, the command will be
210 * interrupted and un-scheduled.
211 *
212 * @param condition the run condition
213 * @return the command with the run condition added
214 */
215 CommandPtr OnlyWhile(std::function<bool()> condition) &&;
216
217 /**
218 * Decorates this command with a runnable to run before this command starts.
219 *
220 * @param toRun the Runnable to run
221 * @param requirements the required subsystems
222 * @return the decorated command
223 */
224 CommandPtr BeforeStarting(std::function<void()> toRun,
225 Requirements requirements = {}) &&;
226
227 /**
228 * Decorates this command with another command to run before this command
229 * starts.
230 *
231 * @param before the command to run before this one
232 * @return the decorated command
233 */
235
236 /**
237 * Decorates this command with a runnable to run after the command finishes.
238 *
239 * @param toRun the Runnable to run
240 * @param requirements the required subsystems
241 * @return the decorated command
242 */
243 CommandPtr AndThen(std::function<void()> toRun,
244 Requirements requirements = {}) &&;
245
246 /**
247 * Decorates this command with a set of commands to run after it in sequence.
248 * Often more convenient/less-verbose than constructing a
249 * SequentialCommandGroup explicitly.
250 *
251 * @param next the commands to run next
252 * @return the decorated command
253 */
255
256 /**
257 * Decorates this command to run repeatedly, restarting it when it ends, until
258 * this command is interrupted. The decorated command can still be canceled.
259 *
260 * @return the decorated command
261 */
263
264 /**
265 * Decorates this command to run "by proxy" by wrapping it in a ProxyCommand.
266 * Use this for "forking off" from command compositions when the user does not
267 * wish to extend the command's requirements to the entire command
268 * composition. ProxyCommand has unique implications and semantics, see <a
269 * href="https://docs.wpilib.org/en/stable/docs/software/commandbased/command-compositions.html#scheduling-other-commands">the
270 * WPILib docs</a> for a full explanation.
271 *
272 * <p>This overload transfers command ownership to the returned CommandPtr.
273 *
274 * @return the decorated command
275 * @see ProxyCommand
276 */
278
279 /**
280 * Decorates this command to only run if this condition is not met. If the
281 * command is already running and the condition changes to true, the command
282 * will not stop running. The requirements of this command will be kept for
283 * the new conditional command.
284 *
285 * @param condition the condition that will prevent the command from running
286 * @return the decorated command
287 */
288 CommandPtr Unless(std::function<bool()> condition) &&;
289
290 /**
291 * Decorates this command to only run if this condition is met. If the command
292 * is already running and the condition changes to false, the command will not
293 * stop running. The requirements of this command will be kept for the new
294 * conditional command.
295 *
296 * @param condition the condition that will allow the command to run
297 * @return the decorated command
298 */
299 CommandPtr OnlyIf(std::function<bool()> condition) &&;
300
301 /**
302 * Creates a new command that runs this command and the deadline in parallel,
303 * finishing (and interrupting this command) when the deadline finishes.
304 *
305 * @param deadline the deadline of the command group
306 * @return the decorated command
307 * @see DeadlineFor
308 */
310
311 /**
312 * Decorates this command with a set of commands to run parallel to it, ending
313 * when the calling command ends and interrupting all the others. Often more
314 * convenient/less-verbose than constructing a new {@link
315 * ParallelDeadlineGroup} explicitly.
316 *
317 * @param parallel the commands to run in parallel. Note the parallel commands
318 * will be interupted when the deadline command ends
319 * @return the decorated command
320 * @see WithDeadline
321 */
323
324 /**
325 * Decorates this command with a set of commands to run parallel to it, ending
326 * when the last command ends. Often more convenient/less-verbose than
327 * constructing a new {@link ParallelCommandGroup} explicitly.
328 *
329 * @param parallel the commands to run in parallel
330 * @return the decorated command
331 */
333
334 /**
335 * Decorates this command with a set of commands to run parallel to it, ending
336 * when the first command ends. Often more convenient/less-verbose than
337 * constructing a new {@link ParallelRaceGroup} explicitly.
338 *
339 * @param parallel the commands to run in parallel
340 * @return the decorated command
341 */
343
344 /**
345 * Decorates this command to run or stop when disabled.
346 *
347 * @param doesRunWhenDisabled true to run when disabled.
348 * @return the decorated command
349 */
350 CommandPtr IgnoringDisable(bool doesRunWhenDisabled) &&;
351
352 /**
353 * Decorates this command to have a different interrupt behavior.
354 *
355 * @param interruptBehavior the desired interrupt behavior
356 * @return the decorated command
357 */
359 Command::InterruptionBehavior interruptBehavior) &&;
360
361 /**
362 * Decorates this command with a lambda to call on interrupt or end, following
363 * the command's inherent Command::End(bool) method.
364 *
365 * @param end a lambda accepting a boolean parameter specifying whether the
366 * command was interrupted.
367 * @return the decorated command
368 */
369 CommandPtr FinallyDo(std::function<void(bool)> end) &&;
370
371 /**
372 * Decorates this command with a lambda to call on interrupt or end, following
373 * the command's inherent Command::End(bool) method. The provided lambda will
374 * run identically in both interrupt and end cases.
375 *
376 * @param end a lambda to run when the command ends, whether or not it was
377 * interrupted.
378 * @return the decorated command
379 */
380 CommandPtr FinallyDo(std::function<void()> end) &&;
381
382 /**
383 * Decorates this command with a lambda to call on interrupt, following the
384 * command's inherent Command::End(bool) method.
385 *
386 * @param handler a lambda to run when the command is interrupted
387 * @return the decorated command
388 */
389 CommandPtr HandleInterrupt(std::function<void()> handler) &&;
390
391 /**
392 * Decorates this Command with a name.
393 *
394 * @param name name
395 * @return the decorated Command
396 */
397 CommandPtr WithName(std::string_view name) &&;
398
399 /**
400 * Schedules this command.
401 *
402 * @deprecated Use CommandScheduler::GetInstance().Schedule() instead
403 */
404 [[deprecated("Use CommandScheduler::GetInstance().Schedule() instead.")]]
405 void Schedule();
406
407 /**
408 * Cancels this command. Will call End(true). Commands will be canceled
409 * regardless of interruption behavior.
410 */
411 void Cancel();
412
413 /**
414 * Whether or not the command is currently scheduled. Note that this does not
415 * detect whether the command is in a composition, only whether it is directly
416 * being run by the scheduler.
417 *
418 * @return Whether the command is scheduled.
419 */
420 bool IsScheduled() const;
421
422 /**
423 * Whether the command requires a given subsystem. Named "HasRequirement"
424 * rather than "requires" to avoid confusion with Command::Requires(Subsystem)
425 * -- this may be able to be changed in a few years.
426 *
427 * @param requirement the subsystem to inquire about
428 * @return whether the subsystem is required
429 */
430 bool HasRequirement(Subsystem* requirement) const;
431
432 /**
433 * Whether the command is currently grouped in a command group. Used as extra
434 * insurance to prevent accidental independent use of grouped commands.
435 */
436 bool IsComposed() const;
437
438 /**
439 * Sets whether the command is currently composed in a command composition.
440 * Can be used to "reclaim" a command if a composition is no longer going to
441 * use it. NOT ADVISED!
442 */
443 void SetComposed(bool isComposed);
444
445 /**
446 * Get the stacktrace of where this command was composed, or an empty
447 * optional. Intended for internal use.
448 *
449 * @return optional string representation of the composition site stack trace.
450 */
451 std::optional<std::string> GetPreviousCompositionSite() const;
452
453 /**
454 * Whether the given command should run when the robot is disabled. Override
455 * to return true if the command should run when disabled.
456 *
457 * @return whether the command should run when the robot is disabled
458 */
459 virtual bool RunsWhenDisabled() const { return false; }
460
461 /**
462 * How the command behaves when another command with a shared requirement is
463 * scheduled.
464 *
465 * @return a variant of InterruptionBehavior, defaulting to kCancelSelf.
466 */
470
471 /**
472 * Transfers ownership of this command to a unique pointer. Used for
473 * decorator methods.
474 */
475 virtual CommandPtr ToPtr() && = 0;
476
478
479 protected:
481
482 private:
483 /// Requirements set.
485
486 std::optional<std::string> m_previousComposition;
487};
488
489/**
490 * Checks if two commands have disjoint requirement sets.
491 *
492 * @param first The first command to check.
493 * @param second The second command to check.
494 * @return False if first and second share a requirement.
495 */
497} // namespace wpi::cmd
This file defines the SmallSet class.
@ name
Definition base.h:690
A state machine representing a complete action to be performed by the robot.
Definition Command.hpp:41
Command & operator=(const Command &rhs)
virtual bool RunsWhenDisabled() const
Whether the given command should run when the robot is disabled.
Definition Command.hpp:459
CommandPtr Unless(std::function< bool()> condition) &&
Decorates this command to only run if this condition is not met.
friend class CommandPtr
Definition Command.hpp:185
void SetComposed(bool isComposed)
Sets whether the command is currently composed in a command composition.
std::optional< std::string > GetPreviousCompositionSite() const
Get the stacktrace of where this command was composed, or an empty optional.
CommandPtr WithTimeout(wpi::units::second_t duration) &&
Decorates this command with a timeout.
CommandPtr AsProxy() &&
Decorates this command to run "by proxy" by wrapping it in a ProxyCommand.
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.
Command(const Command &)=default
void AddRequirements(wpi::util::SmallSet< Subsystem *, 4 > requirements)
Adds the specified Subsystem requirements to the command.
bool IsScheduled() const
Whether or not the command is currently scheduled.
bool HasRequirement(Subsystem *requirement) const
Whether the command requires a given subsystem.
bool IsComposed() const
Whether the command is currently grouped in a command group.
CommandPtr OnlyIf(std::function< bool()> condition) &&
Decorates this command to only run if this condition is met.
virtual void End(bool interrupted)
The action to take when the command ends.
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...
std::string GetName() const
Gets the name of this Command.
InterruptionBehavior
An enum describing the command's behavior when another command with a shared requirement is scheduled...
Definition Command.hpp:173
@ kCancelSelf
This command ends, End(true) is called, and the incoming command is scheduled normally.
Definition Command.hpp:180
@ kCancelIncoming
This command continues, and the incoming command is not scheduled.
Definition Command.hpp:182
CommandPtr AndThen(CommandPtr &&next) &&
Decorates this command with a set of commands to run after it in sequence.
CommandPtr DeadlineFor(CommandPtr &&parallel) &&
Decorates this command with a set of commands to run parallel to it, ending when the calling command ...
virtual InterruptionBehavior GetInterruptionBehavior() const
How the command behaves when another command with a shared requirement is scheduled.
Definition Command.hpp:467
std::string GetSubsystem() const
Gets the subsystem name of this Command.
CommandPtr AndThen(std::function< void()> toRun, Requirements requirements={}) &&
Decorates this command with a runnable to run after the command finishes.
void Cancel()
Cancels this command.
CommandPtr RaceWith(CommandPtr &&parallel) &&
Decorates this command with a set of commands to run parallel to it, ending when the first command en...
void AddRequirements(Requirements requirements)
Adds the specified Subsystem requirements to the command.
virtual void Execute()
The main body of a command.
CommandPtr BeforeStarting(CommandPtr &&before) &&
Decorates this command with another command to run before this command starts.
CommandPtr WithName(std::string_view name) &&
Decorates this Command with a name.
void InitSendable(wpi::util::SendableBuilder &builder) override
Initializes this Sendable object.
void Schedule()
Schedules this command.
CommandPtr AlongWith(CommandPtr &&parallel) &&
Decorates this command with a set of commands to run parallel to it, ending when the last command end...
CommandPtr WithDeadline(CommandPtr &&deadline) &&
Creates a new command that runs this command and the deadline in parallel, finishing (and interruptin...
void SetSubsystem(std::string_view subsystem)
Sets the subsystem name of this Command.
Command & operator=(Command &&)=default
virtual CommandPtr ToPtr() &&=0
Transfers ownership of this command to a unique pointer.
virtual void Initialize()
The initial subroutine of a command.
CommandPtr OnlyWhile(std::function< bool()> condition) &&
Decorates this command with a run condition.
CommandPtr HandleInterrupt(std::function< void()> handler) &&
Decorates this command with a lambda to call on interrupt, following the command's inherent Command::...
CommandPtr Repeatedly() &&
Decorates this command to run repeatedly, restarting it when it ends, until this command is interrupt...
~Command() override
void SetName(std::string_view name)
Sets the name of this Command.
CommandPtr IgnoringDisable(bool doesRunWhenDisabled) &&
Decorates this command to run or stop when disabled.
CommandPtr Until(std::function< bool()> condition) &&
Decorates this command with an interrupt condition.
Command(Command &&)=default
CommandPtr FinallyDo(std::function< void()> end) &&
Decorates this command with a lambda to call on interrupt or end, following the command's inherent Co...
virtual bool IsFinished()
Whether the command has finished.
Definition Command.hpp:76
void AddRequirements(Subsystem *requirement)
Adds the specified Subsystem requirement to the command.
virtual wpi::util::SmallSet< Subsystem *, 4 > GetRequirements() const
Specifies the set of subsystems used by this command.
Represents requirements for a command, which is a set of (pointers to) subsystems.
Definition Requirements.hpp:20
A robot subsystem.
Definition Subsystem.hpp:42
Helper class for building Sendable dashboard representations.
Definition SendableBuilder.hpp:21
A helper class for use with objects that add themselves to SendableRegistry.
Definition SendableHelper.hpp:21
Interface for Sendable objects.
Definition Sendable.hpp:16
SmallSet - This maintains a set of unique values, optimizing for the case when the set is small (less...
Definition SmallSet.hpp:132
Definition CommandNiDsStadiaController.hpp:15
bool RequirementsDisjoint(Command *first, Command *second)
Checks if two commands have disjoint requirement sets.