WPILibC++ 2023.4.3-108-ge5452e3
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 <initializer_list>
9#include <memory>
10#include <span>
11#include <string>
12
13#include <units/time.h>
14#include <wpi/Demangle.h>
15#include <wpi/SmallSet.h>
16
18
19namespace frc2 {
20
21template <typename T>
22std::string GetTypeName(const T& type) {
23 return wpi::Demangle(typeid(type).name());
24}
25
26/**
27 * A state machine representing a complete action to be performed by the robot.
28 * Commands are run by the CommandScheduler, and can be composed into
29 * CommandGroups to allow users to build complicated multi-step actions without
30 * the need to roll the state machine logic themselves.
31 *
32 * <p>Commands are run synchronously from the main robot loop; no
33 * multithreading is used, unless specified explicitly from the command
34 * implementation.
35 *
36 * <p>Note: ALWAYS create a subclass by extending CommandHelper<Base, Subclass>,
37 * or decorators will not function!
38 *
39 * This class is provided by the NewCommands VendorDep
40 *
41 * @see CommandScheduler
42 * @see CommandHelper
43 */
44class Command {
45 public:
46 Command() = default;
47 virtual ~Command();
48
49 Command(const Command&) = default;
51 Command(Command&&) = default;
52 Command& operator=(Command&&) = default;
53
54 /**
55 * The initial subroutine of a command. Called once when the command is
56 * initially scheduled.
57 */
58 virtual void Initialize();
59
60 /**
61 * The main body of a command. Called repeatedly while the command is
62 * scheduled.
63 */
64 virtual void Execute();
65
66 /**
67 * The action to take when the command ends. Called when either the command
68 * finishes normally, or when it interrupted/canceled.
69 *
70 * @param interrupted whether the command was interrupted/canceled
71 */
72 virtual void End(bool interrupted);
73
74 /**
75 * Whether the command has finished. Once a command finishes, the scheduler
76 * will call its end() method and un-schedule it.
77 *
78 * @return whether the command has finished.
79 */
80 virtual bool IsFinished() { return false; }
81
82 /**
83 * Specifies the set of subsystems used by this command. Two commands cannot
84 * use the same subsystem at the same time. If another command is scheduled
85 * that shares a requirement, GetInterruptionBehavior() will be checked and
86 * followed. If no subsystems are required, return an empty set.
87 *
88 * <p>Note: it is recommended that user implementations contain the
89 * requirements as a field, and return that field here, rather than allocating
90 * a new set every time this is called.
91 *
92 * @return the set of subsystems that are required
93 * @see InterruptionBehavior
94 */
96
97 /**
98 * An enum describing the command's behavior when another command with a
99 * shared requirement is scheduled.
100 */
102 /**
103 * This command ends, End(true) is called, and the incoming command is
104 * scheduled normally.
105 *
106 * <p>This is the default behavior.
107 */
108 kCancelSelf,
109 /** This command continues, and the incoming command is not scheduled. */
110 kCancelIncoming
111 };
112
113 friend class CommandPtr;
114
115 /**
116 * Decorates this command with a timeout. If the specified timeout is
117 * exceeded before the command finishes normally, the command will be
118 * interrupted and un-scheduled.
119 *
120 * @param duration the timeout duration
121 * @return the command with the timeout added
122 */
123 [[nodiscard]]
124 CommandPtr WithTimeout(units::second_t duration) &&;
125
126 /**
127 * Decorates this command with an interrupt condition. If the specified
128 * condition becomes true before the command finishes normally, the command
129 * will be interrupted and un-scheduled.
130 *
131 * @param condition the interrupt condition
132 * @return the command with the interrupt condition added
133 */
134 [[nodiscard]]
135 CommandPtr Until(std::function<bool()> condition) &&;
136
137 /**
138 * Decorates this command with a run condition. If the specified condition
139 * becomes false before the command finishes normally, the command will be
140 * interrupted and un-scheduled.
141 *
142 * @param condition the run condition
143 * @return the command with the run condition added
144 */
145 [[nodiscard]]
146 CommandPtr OnlyWhile(std::function<bool()> condition) &&;
147
148 /**
149 * Decorates this command with a runnable to run before this command starts.
150 *
151 * @param toRun the Runnable to run
152 * @param requirements the required subsystems
153 * @return the decorated command
154 */
155 [[nodiscard]]
156 CommandPtr BeforeStarting(std::function<void()> toRun,
157 std::initializer_list<Subsystem*> requirements) &&;
158
159 /**
160 * Decorates this command with a runnable to run before this command starts.
161 *
162 * @param toRun the Runnable to run
163 * @param requirements the required subsystems
164 * @return the decorated command
165 */
166 [[nodiscard]]
167 CommandPtr BeforeStarting(std::function<void()> toRun,
168 std::span<Subsystem* const> requirements = {}) &&;
169
170 /**
171 * Decorates this command with a runnable to run after the command finishes.
172 *
173 * @param toRun the Runnable to run
174 * @param requirements the required subsystems
175 * @return the decorated command
176 */
177 [[nodiscard]]
178 CommandPtr AndThen(std::function<void()> toRun,
179 std::initializer_list<Subsystem*> requirements) &&;
180
181 /**
182 * Decorates this command with a runnable to run after the command finishes.
183 *
184 * @param toRun the Runnable to run
185 * @param requirements the required subsystems
186 * @return the decorated command
187 */
188 [[nodiscard]]
189 CommandPtr AndThen(std::function<void()> toRun,
190 std::span<Subsystem* const> requirements = {}) &&;
191
192 /**
193 * Decorates this command to run repeatedly, restarting it when it ends, until
194 * this command is interrupted. The decorated command can still be canceled.
195 *
196 * @return the decorated command
197 */
198 [[nodiscard]]
200
201 /**
202 * Decorates this command to run "by proxy" by wrapping it in a
203 * ProxyCommand. This is useful for "forking off" from command groups
204 * when the user does not wish to extend the command's requirements to the
205 * entire command group.
206 *
207 * <p>This overload transfers command ownership to the returned CommandPtr.
208 *
209 * @return the decorated command
210 */
211 [[nodiscard]]
213
214 /**
215 * Decorates this command to only run if this condition is not met. If the
216 * command is already running and the condition changes to true, the command
217 * will not stop running. The requirements of this command will be kept for
218 * the new conditional command.
219 *
220 * @param condition the condition that will prevent the command from running
221 * @return the decorated command
222 */
223 [[nodiscard]]
224 CommandPtr Unless(std::function<bool()> condition) &&;
225
226 /**
227 * Decorates this command to only run if this condition is met. If the command
228 * is already running and the condition changes to false, the command will not
229 * stop running. The requirements of this command will be kept for the new
230 * conditional command.
231 *
232 * @param condition the condition that will allow the command to run
233 * @return the decorated command
234 */
235 [[nodiscard]]
236 CommandPtr OnlyIf(std::function<bool()> condition) &&;
237
238 /**
239 * Decorates this command to run or stop when disabled.
240 *
241 * @param doesRunWhenDisabled true to run when disabled.
242 * @return the decorated command
243 */
244 [[nodiscard]]
245 CommandPtr IgnoringDisable(bool doesRunWhenDisabled) &&;
246
247 /**
248 * Decorates this command to have a different interrupt behavior.
249 *
250 * @param interruptBehavior the desired interrupt behavior
251 * @return the decorated command
252 */
253 [[nodiscard]]
255 Command::InterruptionBehavior interruptBehavior) &&;
256
257 /**
258 * Decorates this command with a lambda to call on interrupt or end, following
259 * the command's inherent Command::End(bool) method.
260 *
261 * @param end a lambda accepting a boolean parameter specifying whether the
262 * command was interrupted.
263 * @return the decorated command
264 */
265 [[nodiscard]]
266 CommandPtr FinallyDo(std::function<void(bool)> end) &&;
267
268 /**
269 * Decorates this command with a lambda to call on interrupt, following the
270 * command's inherent Command::End(bool) method.
271 *
272 * @param handler a lambda to run when the command is interrupted
273 * @return the decorated command
274 */
275 [[nodiscard]]
276 CommandPtr HandleInterrupt(std::function<void()> handler) &&;
277
278 /**
279 * Decorates this Command with a name.
280 *
281 * @param name name
282 * @return the decorated Command
283 */
284 [[nodiscard]]
286
287 /**
288 * Schedules this command.
289 */
290 void Schedule();
291
292 /**
293 * Cancels this command. Will call End(true). Commands will be canceled
294 * regardless of interruption behavior.
295 */
296 void Cancel();
297
298 /**
299 * Whether or not the command is currently scheduled. Note that this does not
300 * detect whether the command is in a composition, only whether it is directly
301 * being run by the scheduler.
302 *
303 * @return Whether the command is scheduled.
304 */
305 bool IsScheduled() const;
306
307 /**
308 * Whether the command requires a given subsystem. Named "HasRequirement"
309 * rather than "requires" to avoid confusion with Command::Requires(Subsystem)
310 * -- this may be able to be changed in a few years.
311 *
312 * @param requirement the subsystem to inquire about
313 * @return whether the subsystem is required
314 */
315 bool HasRequirement(Subsystem* requirement) const;
316
317 /**
318 * Whether the command is currently grouped in a command group. Used as extra
319 * insurance to prevent accidental independent use of grouped commands.
320 */
321 bool IsComposed() const;
322
323 /**
324 * Sets whether the command is currently composed in a command composition.
325 * Can be used to "reclaim" a command if a composition is no longer going to
326 * use it. NOT ADVISED!
327 */
328 void SetComposed(bool isComposed);
329
330 /**
331 * Whether the given command should run when the robot is disabled. Override
332 * to return true if the command should run when disabled.
333 *
334 * @return whether the command should run when the robot is disabled
335 */
336 virtual bool RunsWhenDisabled() const { return false; }
337
338 /**
339 * How the command behaves when another command with a shared requirement is
340 * scheduled.
341 *
342 * @return a variant of InterruptionBehavior, defaulting to kCancelSelf.
343 */
346 }
347
348 /**
349 * Gets the name of this Command. Defaults to the simple class name if not
350 * overridden.
351 *
352 * @return The display name of the Command
353 */
354 virtual std::string GetName() const;
355
356 /**
357 * Sets the name of this Command. Nullop if not overridden.
358 *
359 * @param name The display name of the Command.
360 */
362
363 /**
364 * Transfers ownership of this command to a unique pointer. Used for
365 * decorator methods.
366 */
367 virtual CommandPtr ToPtr() && = 0;
368
369 protected:
370 /**
371 * Transfers ownership of this command to a unique pointer. Used for
372 * decorator methods.
373 */
374 virtual std::unique_ptr<Command> TransferOwnership() && = 0;
375
376 bool m_isComposed = false;
377};
378
379/**
380 * Checks if two commands have disjoint requirement sets.
381 *
382 * @param first The first command to check.
383 * @param second The second command to check.
384 * @return False if first and second share a requirement.
385 */
387} // namespace frc2
This file defines the SmallSet class.
A state machine representing a complete action to be performed by the robot.
Definition: Command.h:44
bool IsScheduled() const
Whether or not the command is currently scheduled.
void Cancel()
Cancels 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.
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 WithTimeout(units::second_t duration) &&
Decorates this command with a timeout.
CommandPtr BeforeStarting(std::function< void()> toRun, std::initializer_list< Subsystem * > requirements) &&
Decorates this command with a runnable to run before this command starts.
virtual ~Command()
virtual std::string GetName() const
Gets the name of this Command.
virtual wpi::SmallSet< Subsystem *, 4 > GetRequirements() const =0
Specifies the set of subsystems used by this command.
CommandPtr Repeatedly() &&
Decorates this command to run repeatedly, restarting it when it ends, until this command is interrupt...
virtual bool RunsWhenDisabled() const
Whether the given command should run when the robot is disabled.
Definition: Command.h:336
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.
bool m_isComposed
Definition: Command.h:376
Command(const Command &)=default
CommandPtr BeforeStarting(std::function< void()> toRun, std::span< Subsystem *const > requirements={}) &&
Decorates this command with a runnable to run before this command starts.
CommandPtr Until(std::function< bool()> condition) &&
Decorates this command with an interrupt condition.
CommandPtr AndThen(std::function< void()> toRun, std::span< Subsystem *const > requirements={}) &&
Decorates this command with a runnable to run after the command finishes.
Command()=default
virtual void Execute()
The main body of a command.
CommandPtr OnlyWhile(std::function< bool()> condition) &&
Decorates this command with a run condition.
CommandPtr AndThen(std::function< void()> toRun, std::initializer_list< Subsystem * > requirements) &&
Decorates this command with a runnable to run after the command finishes.
CommandPtr OnlyIf(std::function< bool()> condition) &&
Decorates this command to only run if this condition is met.
Command & operator=(const Command &rhs)
virtual void SetName(std::string_view name)
Sets the name of this Command.
virtual InterruptionBehavior GetInterruptionBehavior() const
How the command behaves when another command with a shared requirement is scheduled.
Definition: Command.h:344
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.
InterruptionBehavior
An enum describing the command's behavior when another command with a shared requirement is scheduled...
Definition: Command.h:101
@ kCancelSelf
This command ends, End(true) is called, and the incoming command is scheduled normally.
Command & operator=(Command &&)=default
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:80
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
A robot subsystem.
Definition: Subsystem.h:39
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:520
type
Definition: core.h:575
EIGEN_CONSTEXPR Index first(const T &x) EIGEN_NOEXCEPT
Definition: IndexedViewHelper.h:81
static EIGEN_DEPRECATED const end_t end
Definition: IndexedViewHelper.h:181
Definition: ProfiledPIDCommand.h:18
std::string GetTypeName(const T &type)
Definition: Command.h:22
bool RequirementsDisjoint(Command *first, Command *second)
Checks if two commands have disjoint requirement sets.
std::string Demangle(std::string_view mangledSymbol)
Demangle a C++ symbol.