WPILibC++ 2027.0.0-alpha-2
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 CommandPtr WithTimeout(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
477 void InitSendable(wpi::SendableBuilder& builder) override;
478
479 protected:
481
482 private:
483 /// Requirements set.
484 wpi::SmallSet<Subsystem*, 4> m_requirements;
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 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:459
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:467
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:29
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:132
Definition FunctionalCommand.h:13
bool RequirementsDisjoint(Command *first, Command *second)
Checks if two commands have disjoint requirement sets.