WPILibC++ 2024.3.2
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 */
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 */
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 */
180 kCancelSelf,
181 /** This command continues, and the incoming command is not scheduled. */
182 kCancelIncoming
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 a runnable to run after the command finishes.
233 *
234 * @param toRun the Runnable to run
235 * @param requirements the required subsystems
236 * @return the decorated command
237 */
238 [[nodiscard]]
239 CommandPtr AndThen(std::function<void()> toRun,
240 Requirements requirements = {}) &&;
241
242 /**
243 * Decorates this command to run repeatedly, restarting it when it ends, until
244 * this command is interrupted. The decorated command can still be canceled.
245 *
246 * @return the decorated command
247 */
248 [[nodiscard]]
250
251 /**
252 * Decorates this command to run "by proxy" by wrapping it in a
253 * ProxyCommand. This is useful for "forking off" from command groups
254 * when the user does not wish to extend the command's requirements to the
255 * entire command group.
256 *
257 * <p>This overload transfers command ownership to the returned CommandPtr.
258 *
259 * @return the decorated command
260 */
261 [[nodiscard]]
263
264 /**
265 * Decorates this command to only run if this condition is not met. If the
266 * command is already running and the condition changes to true, the command
267 * will not stop running. The requirements of this command will be kept for
268 * the new conditional command.
269 *
270 * @param condition the condition that will prevent the command from running
271 * @return the decorated command
272 */
273 [[nodiscard]]
274 CommandPtr Unless(std::function<bool()> condition) &&;
275
276 /**
277 * Decorates this command to only run if this condition is met. If the command
278 * is already running and the condition changes to false, the command will not
279 * stop running. The requirements of this command will be kept for the new
280 * conditional command.
281 *
282 * @param condition the condition that will allow the command to run
283 * @return the decorated command
284 */
285 [[nodiscard]]
286 CommandPtr OnlyIf(std::function<bool()> condition) &&;
287
288 /**
289 * Decorates this command to run or stop when disabled.
290 *
291 * @param doesRunWhenDisabled true to run when disabled.
292 * @return the decorated command
293 */
294 [[nodiscard]]
295 CommandPtr IgnoringDisable(bool doesRunWhenDisabled) &&;
296
297 /**
298 * Decorates this command to have a different interrupt behavior.
299 *
300 * @param interruptBehavior the desired interrupt behavior
301 * @return the decorated command
302 */
303 [[nodiscard]]
305 Command::InterruptionBehavior interruptBehavior) &&;
306
307 /**
308 * Decorates this command with a lambda to call on interrupt or end, following
309 * the command's inherent Command::End(bool) method.
310 *
311 * @param end a lambda accepting a boolean parameter specifying whether the
312 * command was interrupted.
313 * @return the decorated command
314 */
315 [[nodiscard]]
316 CommandPtr FinallyDo(std::function<void(bool)> end) &&;
317
318 /**
319 * Decorates this command with a lambda to call on interrupt or end, following
320 * the command's inherent Command::End(bool) method. The provided lambda will
321 * run identically in both interrupt and end cases.
322 *
323 * @param end a lambda to run when the command ends, whether or not it was
324 * interrupted.
325 * @return the decorated command
326 */
327 [[nodiscard]]
328 CommandPtr FinallyDo(std::function<void()> end) &&;
329
330 /**
331 * Decorates this command with a lambda to call on interrupt, following the
332 * command's inherent Command::End(bool) method.
333 *
334 * @param handler a lambda to run when the command is interrupted
335 * @return the decorated command
336 */
337 [[nodiscard]]
338 CommandPtr HandleInterrupt(std::function<void()> handler) &&;
339
340 /**
341 * Decorates this Command with a name.
342 *
343 * @param name name
344 * @return the decorated Command
345 */
346 [[nodiscard]]
348
349 /**
350 * Schedules this command.
351 */
352 void Schedule();
353
354 /**
355 * Cancels this command. Will call End(true). Commands will be canceled
356 * regardless of interruption behavior.
357 */
358 void Cancel();
359
360 /**
361 * Whether or not the command is currently scheduled. Note that this does not
362 * detect whether the command is in a composition, only whether it is directly
363 * being run by the scheduler.
364 *
365 * @return Whether the command is scheduled.
366 */
367 bool IsScheduled() const;
368
369 /**
370 * Whether the command requires a given subsystem. Named "HasRequirement"
371 * rather than "requires" to avoid confusion with Command::Requires(Subsystem)
372 * -- this may be able to be changed in a few years.
373 *
374 * @param requirement the subsystem to inquire about
375 * @return whether the subsystem is required
376 */
377 bool HasRequirement(Subsystem* requirement) const;
378
379 /**
380 * Whether the command is currently grouped in a command group. Used as extra
381 * insurance to prevent accidental independent use of grouped commands.
382 */
383 bool IsComposed() const;
384
385 /**
386 * Sets whether the command is currently composed in a command composition.
387 * Can be used to "reclaim" a command if a composition is no longer going to
388 * use it. NOT ADVISED!
389 */
390 void SetComposed(bool isComposed);
391
392 /**
393 * Get the stacktrace of where this command was composed, or an empty
394 * optional. Intended for internal use.
395 *
396 * @return optional string representation of the composition site stack trace.
397 */
398 std::optional<std::string> GetPreviousCompositionSite() const;
399
400 /**
401 * Whether the given command should run when the robot is disabled. Override
402 * to return true if the command should run when disabled.
403 *
404 * @return whether the command should run when the robot is disabled
405 */
406 virtual bool RunsWhenDisabled() const { return false; }
407
408 /**
409 * How the command behaves when another command with a shared requirement is
410 * scheduled.
411 *
412 * @return a variant of InterruptionBehavior, defaulting to kCancelSelf.
413 */
416 }
417
418 /**
419 * Transfers ownership of this command to a unique pointer. Used for
420 * decorator methods.
421 */
422 virtual CommandPtr ToPtr() && = 0;
423
424 void InitSendable(wpi::SendableBuilder& builder) override;
425
426 protected:
428
429 /// Requirements set.
431
432 /**
433 * Transfers ownership of this command to a unique pointer. Used for
434 * decorator methods.
435 */
436 [[deprecated("Use ToPtr() instead")]]
437 virtual std::unique_ptr<Command> TransferOwnership() && = 0;
438
439 std::optional<std::string> m_previousComposition;
440};
441
442/**
443 * Checks if two commands have disjoint requirement sets.
444 *
445 * @param first The first command to check.
446 * @param second The second command to check.
447 * @return False if first and second share a requirement.
448 */
450} // 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
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:406
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:414
std::string GetName() const
Gets the name of this Command.
wpi::SmallSet< Subsystem *, 4 > m_requirements
Requirements set.
Definition: Command.h:430
virtual CommandPtr ToPtr() &&=0
Transfers ownership of this command to a unique pointer.
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.
Command & operator=(Command &&)=default
CommandPtr AndThen(std::function< void()> toRun, Requirements requirements={}) &&
Decorates this command with a runnable to run after the command finishes.
std::optional< std::string > m_previousComposition
Definition: Command.h:439
virtual std::unique_ptr< Command > TransferOwnership() &&=0
Transfers ownership of this command to a unique pointer.
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:19
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
basic_string_view< char > string_view
Definition: core.h:501
const T & first(const T &value, const Tail &...)
Definition: compile.h:60
Definition: TrapezoidProfileSubsystem.h:12
bool RequirementsDisjoint(Command *first, Command *second)
Checks if two commands have disjoint requirement sets.
constexpr const char * name(const T &)