WPILibC++ 2024.3.2-104-gb0d3bf4
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 <concepts>
13#include <functional>
14#include <memory>
15#include <string>
16#include <unordered_map>
17#include <utility>
18#include <vector>
19
21
24
25namespace frc2 {
26/**
27 * A command composition that runs one of a selection of commands using a
28 * selector and a key to command mapping.
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<Command, 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 <std::derived_from<Command>... Commands>
47 explicit SelectCommand(std::function<Key()> selector,
48 std::pair<Key, Commands>... commands)
49 : m_selector{std::move(selector)} {
50 std::vector<std::pair<Key, std::unique_ptr<Command>>> foo;
51
52 ((void)foo.emplace_back(
53 commands.first,
54 std::make_unique<std::decay_t<Commands>>(std::move(commands.second))),
55 ...);
56
57 m_defaultCommand.SetComposed(true);
58 for (auto&& command : foo) {
60 command.second.get());
61 command.second.get()->SetComposed(true);
62 }
63
64 for (auto&& command : foo) {
65 this->AddRequirements(command.second->GetRequirements());
66 m_runsWhenDisabled &= command.second->RunsWhenDisabled();
67 if (command.second->GetInterruptionBehavior() ==
70 }
71 m_commands.emplace(std::move(command.first), std::move(command.second));
72 }
73 }
74
76 std::function<Key()> selector,
77 std::vector<std::pair<Key, std::unique_ptr<Command>>>&& commands)
78 : m_selector{std::move(selector)} {
79 m_defaultCommand.SetComposed(true);
80 for (auto&& command : commands) {
82 command.second.get());
83 command.second.get()->SetComposed(true);
84 }
85
86 for (auto&& command : commands) {
87 this->AddRequirements(command.second->GetRequirements());
88 m_runsWhenDisabled &= command.second->RunsWhenDisabled();
89 if (command.second->GetInterruptionBehavior() ==
92 }
93 m_commands.emplace(std::move(command.first), std::move(command.second));
94 }
95 }
96
97 // No copy constructors for command groups
98 SelectCommand(const SelectCommand& other) = delete;
99
100 // Prevent template expansion from emulating copy ctor
102
103 SelectCommand(SelectCommand&& other) = default;
104
105 void Initialize() override;
106
107 void Execute() override { m_selectedCommand->Execute(); }
108
109 void End(bool interrupted) override {
110 return m_selectedCommand->End(interrupted);
111 }
112
113 bool IsFinished() override { return m_selectedCommand->IsFinished(); }
114
115 bool RunsWhenDisabled() const override { return m_runsWhenDisabled; }
116
118 return m_interruptBehavior;
119 }
120
121 void InitSendable(wpi::SendableBuilder& builder) override {
122 Command::InitSendable(builder);
123
124 builder.AddStringProperty(
125 "selected",
126 [this] {
127 if (m_selectedCommand) {
128 return m_selectedCommand->GetName();
129 } else {
130 return std::string{"null"};
131 }
132 },
133 nullptr);
134 }
135
136 protected:
137 [[deprecated("Use ToPtr() instead")]]
138 std::unique_ptr<Command> TransferOwnership() &&
139 override {
140 return std::make_unique<SelectCommand>(std::move(*this));
141 }
142
143 private:
144 std::unordered_map<Key, std::unique_ptr<Command>> m_commands;
145 std::function<Key()> m_selector;
146 Command* m_selectedCommand;
147 bool m_runsWhenDisabled = true;
148 Command::InterruptionBehavior m_interruptBehavior{
150
151 PrintCommand m_defaultCommand{
152 "SelectCommand selector value does not correspond to any command!"};
153};
154
155template <typename T>
157 auto find = m_commands.find(m_selector());
158 if (find == m_commands.end()) {
159 m_selectedCommand = &m_defaultCommand;
160 } else {
161 m_selectedCommand = find->second.get();
162 }
163 m_selectedCommand->Initialize();
164}
165
166} // namespace frc2
167
168#ifdef _WIN32
169#pragma warning(pop)
170#endif
CRTP implementation to allow polymorphic decorator functions in Command.
Definition: CommandHelper.h:25
A state machine representing a complete action to be performed by the robot.
Definition: Command.h:41
virtual void End(bool interrupted)
The action to take when the command ends.
void InitSendable(wpi::SendableBuilder &builder) override
Initializes this Sendable object.
virtual void Execute()
The main body of a command.
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.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.
virtual bool IsFinished()
Whether the command has finished.
Definition: Command.h:76
void RequireUngroupedAndUnscheduled(const Command *command)
Requires that the specified command has not already been added to a composition and is not currently ...
static CommandScheduler & GetInstance()
Returns the Scheduler instance.
A command composition that runs one of a selection of commands using a selector and a key to command ...
Definition: SelectCommand.h:38
std::unique_ptr< Command > TransferOwnership() &&override
Definition: SelectCommand.h:138
SelectCommand(SelectCommand &&other)=default
SelectCommand(std::function< Key()> selector, std::vector< std::pair< Key, std::unique_ptr< Command > > > &&commands)
Definition: SelectCommand.h:75
SelectCommand(std::function< Key()> selector, std::pair< Key, Commands >... commands)
Creates a new SelectCommand.
Definition: SelectCommand.h:47
void InitSendable(wpi::SendableBuilder &builder) override
Definition: SelectCommand.h:121
void End(bool interrupted) override
Definition: SelectCommand.h:109
void Initialize() override
Definition: SelectCommand.h:156
bool RunsWhenDisabled() const override
Definition: SelectCommand.h:115
bool IsFinished() override
Definition: SelectCommand.h:113
Command::InterruptionBehavior GetInterruptionBehavior() const override
Definition: SelectCommand.h:117
SelectCommand(SelectCommand &)=delete
SelectCommand(const SelectCommand &other)=delete
void Execute() override
Definition: SelectCommand.h:107
Helper class for building Sendable dashboard representations.
Definition: SendableBuilder.h:21
virtual void AddStringProperty(std::string_view key, std::function< std::string()> getter, std::function< void(std::string_view)> setter)=0
Add a string property.
FMT_CONSTEXPR auto find(Ptr first, Ptr last, T value, Ptr &out) -> bool
Definition: core.h:2154
Definition: NotifierCommand.h:16
Implement std::hash so that hash_code can be used in STL containers.
Definition: array.h:89