WPILibC++ 2023.4.3
SelectCommand.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#ifdef _WIN32
8#pragma warning(push)
9#pragma warning(disable : 4521)
10#endif
11
12#include <memory>
13#include <string>
14#include <type_traits>
15#include <unordered_map>
16#include <utility>
17#include <vector>
18
20
23
24namespace frc2 {
25/**
26 * A command composition that runs one of a selection of commands, either using
27 * a selector and a key to command mapping, or a supplier that returns the
28 * command directly at runtime.
29 *
30 * <p>The rules for command compositions apply: command instances that are
31 * passed to it are owned by the composition and cannot be added to any other
32 * composition or scheduled individually, and the composition requires all
33 * subsystems its components require.
34 *
35 * This class is provided by the NewCommands VendorDep
36 */
37template <typename Key>
38class SelectCommand : public CommandHelper<CommandBase, SelectCommand<Key>> {
39 public:
40 /**
41 * Creates a new SelectCommand.
42 *
43 * @param commands the map of commands to choose from
44 * @param selector the selector to determine which command to run
45 */
46 template <class... Types,
47 typename = std::enable_if_t<std::conjunction_v<
48 std::is_base_of<Command, std::remove_reference_t<Types>>...>>>
49 explicit SelectCommand(std::function<Key()> selector,
50 std::pair<Key, Types>... commands)
51 : m_selector{std::move(selector)} {
52 std::vector<std::pair<Key, std::unique_ptr<Command>>> foo;
53
54 ((void)foo.emplace_back(commands.first,
55 std::make_unique<std::remove_reference_t<Types>>(
56 std::move(commands.second))),
57 ...);
58
59 for (auto&& command : foo) {
60 CommandScheduler::GetInstance().RequireUngrouped(command.second.get());
61 }
62
63 for (auto&& command : foo) {
64 this->AddRequirements(command.second->GetRequirements());
65 m_runsWhenDisabled &= command.second->RunsWhenDisabled();
66 if (command.second->GetInterruptionBehavior() ==
69 }
70 m_commands.emplace(std::move(command.first), std::move(command.second));
71 }
72 }
73
75 std::function<Key()> selector,
76 std::vector<std::pair<Key, std::unique_ptr<Command>>>&& commands)
77 : m_selector{std::move(selector)} {
78 for (auto&& command : commands) {
79 CommandScheduler::GetInstance().RequireUngrouped(command.second.get());
80 }
81
82 for (auto&& command : commands) {
83 this->AddRequirements(command.second->GetRequirements());
84 m_runsWhenDisabled &= command.second->RunsWhenDisabled();
85 if (command.second->GetInterruptionBehavior() ==
88 }
89 m_commands.emplace(std::move(command.first), std::move(command.second));
90 }
91 }
92
93 // No copy constructors for command groups
94 SelectCommand(const SelectCommand& other) = delete;
95
96 // Prevent template expansion from emulating copy ctor
98
99 /**
100 * Creates a new selectcommand.
101 *
102 * @param toRun a supplier providing the command to run
103 * @deprecated Replace with {@link ProxyCommand},
104 * composing multiple of them in a {@link ParallelRaceGroup} if needed.
105 */
106 WPI_DEPRECATED("Replace with ProxyCommand")
107 explicit SelectCommand(std::function<Command*()> toRun)
108 : m_toRun{std::move(toRun)} {}
109
110 SelectCommand(SelectCommand&& other) = default;
111
112 void Initialize() override;
113
114 void Execute() override { m_selectedCommand->Execute(); }
115
116 void End(bool interrupted) override {
117 return m_selectedCommand->End(interrupted);
118 }
119
120 bool IsFinished() override { return m_selectedCommand->IsFinished(); }
121
122 bool RunsWhenDisabled() const override { return m_runsWhenDisabled; }
123
125 return m_interruptBehavior;
126 }
127
128 void InitSendable(wpi::SendableBuilder& builder) override {
130
131 builder.AddStringProperty(
132 "selected",
133 [this] {
134 if (m_selectedCommand) {
135 return m_selectedCommand->GetName();
136 } else {
137 return std::string{"null"};
138 }
139 },
140 nullptr);
141 }
142
143 protected:
144 std::unique_ptr<Command> TransferOwnership() && override {
145 return std::make_unique<SelectCommand>(std::move(*this));
146 }
147
148 private:
149 std::unordered_map<Key, std::unique_ptr<Command>> m_commands;
150 std::function<Key()> m_selector;
151 std::function<Command*()> m_toRun;
152 Command* m_selectedCommand;
153 bool m_runsWhenDisabled = true;
154 Command::InterruptionBehavior m_interruptBehavior{
156};
157
158template <typename T>
160 if (m_selector) {
161 auto find = m_commands.find(m_selector());
162 if (find == m_commands.end()) {
163 m_selectedCommand = new PrintCommand(
164 "SelectCommand selector value does not correspond to any command!");
165 return;
166 }
167 m_selectedCommand = find->second.get();
168 } else {
169 m_selectedCommand = m_toRun();
170 }
171 m_selectedCommand->Initialize();
172}
173
174} // namespace frc2
175
176#ifdef _WIN32
177#pragma warning(pop)
178#endif
void AddRequirements(std::initializer_list< Subsystem * > requirements)
Adds the specified Subsystem requirements to the command.
void InitSendable(wpi::SendableBuilder &builder) override
Initializes this Sendable object.
CRTP implementation to allow polymorphic decorator functions in Command.
Definition: CommandHelper.h:26
A state machine representing a complete action to be performed by the robot.
Definition: Command.h:47
virtual void End(bool interrupted)
The action to take when the command ends.
virtual std::string GetName() const
Gets the name of this Command.
virtual void Execute()
The main body of a command.
InterruptionBehavior
An enum describing the command's behavior when another command with a shared requirement is scheduled...
Definition: Command.h:104
@ 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.
virtual bool IsFinished()
Whether the command has finished.
Definition: Command.h:83
void RequireUngrouped(const Command *command)
Requires that the specified command hasn't been already added to a composition.
static CommandScheduler & GetInstance()
Returns the Scheduler instance.
A command that prints a string when initialized.
Definition: PrintCommand.h:18
A command composition that runs one of a selection of commands, either using a selector and a key to ...
Definition: SelectCommand.h:38
std::unique_ptr< Command > TransferOwnership() &&override
Transfers ownership of this command to a unique pointer.
Definition: SelectCommand.h:144
SelectCommand(SelectCommand &&other)=default
SelectCommand(std::function< Key()> selector, std::vector< std::pair< Key, std::unique_ptr< Command > > > &&commands)
Definition: SelectCommand.h:74
void InitSendable(wpi::SendableBuilder &builder) override
Initializes this Sendable object.
Definition: SelectCommand.h:128
void End(bool interrupted) override
The action to take when the command ends.
Definition: SelectCommand.h:116
SelectCommand(std::function< Key()> selector, std::pair< Key, Types >... commands)
Creates a new SelectCommand.
Definition: SelectCommand.h:49
void Initialize() override
The initial subroutine of a command.
Definition: SelectCommand.h:159
bool RunsWhenDisabled() const override
Whether the given command should run when the robot is disabled.
Definition: SelectCommand.h:122
bool IsFinished() override
Whether the command has finished.
Definition: SelectCommand.h:120
Command::InterruptionBehavior GetInterruptionBehavior() const override
How the command behaves when another command with a shared requirement is scheduled.
Definition: SelectCommand.h:124
SelectCommand(SelectCommand &)=delete
SelectCommand(const SelectCommand &other)=delete
void Execute() override
The main body of a command.
Definition: SelectCommand.h:114
Definition: SendableBuilder.h:18
virtual void AddStringProperty(std::string_view key, std::function< std::string()> getter, std::function< void(std::string_view)> setter)=0
Add a string property.
typename std::enable_if< B, T >::type enable_if_t
Definition: core.h:298
FMT_CONSTEXPR auto find(Ptr first, Ptr last, T value, Ptr &out) -> bool
Definition: core.h:2318
Definition: InstantCommand.h:14
Definition: StdDeque.h:50