WPILibC++ 2027.0.0-alpha-5
Loading...
Searching...
No Matches
OpModeRobot.hpp
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 <concepts>
8#include <functional>
9#include <memory>
10#include <string>
11#include <vector>
12
17#include "wpi/opmode/OpMode.hpp"
19#include "wpi/units/time.hpp"
20#include "wpi/util/DenseMap.hpp"
21#include "wpi/util/mutex.hpp"
22
23namespace wpi::util {
24class Color;
25} // namespace wpi::util
26
27namespace wpi {
28
30
31namespace detail {
32template <typename T>
33concept OpModeDerived = std::derived_from<T, OpMode>;
34template <typename T>
35concept NoArgOpMode = std::constructible_from<T> && OpModeDerived<T>;
36template <typename T, typename R>
37concept OneArgOpMode = std::constructible_from<T, R&> && OpModeDerived<T>;
38} // namespace detail
39
40/**
41 * Concept indicating a class is derived from OpMode and has either a
42 * no-argument constructor or a constructor that accepts R&.
43 *
44 * @tparam T opmode class
45 * @tparam R robot class
46 */
47template <typename T, typename R>
50
51/**
52 * OpModeRobotBase is the non-templated base class for OpModeRobot. Users should
53 * generally prefer using OpModeRobot instead of this class.
54 *
55 * Opmodes are constructed when selected on the driver station, and destroyed
56 * when the robot is disabled after being enabled or a different opmode is
57 * selected. When no opmode is selected, NonePeriodic() is called. The
58 * DriverStationConnected() function is called the first time the driver station
59 * connects to the robot.
60 */
61class OpModeRobotBase : public RobotBase {
62 public:
63 using OpModeFactory = std::function<std::unique_ptr<OpMode>()>;
64
65 /// Default loop period.
66 static constexpr auto DEFAULT_PERIOD = 20_ms;
67
68 /**
69 * Provide an alternate "main loop" via StartCompetition().
70 */
71 void StartCompetition() override;
72
73 /**
74 * Ends the main loop in StartCompetition().
75 */
76 void EndCompetition() override;
77
78 /**
79 * Constructor.
80 *
81 * @param period The period of the robot loop function.
82 */
83 explicit OpModeRobotBase(wpi::units::second_t period);
84
85 /**
86 * Constructor for an OpModeRobot with a default loop time of 0.02 seconds.
87 */
88 explicit OpModeRobotBase();
89
92
93 /**
94 * Code that needs to know the DS state should go here.
95 *
96 * Users should override this method for initialization that needs to occur
97 * after the DS is connected, such as needing the alliance information.
98 */
99 virtual void DriverStationConnected() {}
100
101 /**
102 * Function called periodically every loop, regardless of enabled state or
103 * OpMode selection.
104 */
105 virtual void RobotPeriodic() {}
106
107 /**
108 * Function called once during robot initialization in simulation.
109 */
110 virtual void SimulationInit() {}
111
112 /**
113 * Function called periodically in simulation.
114 */
115 virtual void SimulationPeriodic() {}
116
117 /**
118 * Function called once when the robot becomes disabled.
119 */
120 virtual void DisabledInit() {}
121
122 /**
123 * Function called periodically while the robot is disabled.
124 */
125 virtual void DisabledPeriodic() {}
126
127 /**
128 * Function called once when the robot exits disabled state.
129 */
130 virtual void DisabledExit() {}
131
132 /**
133 * Function called periodically anytime when no opmode is selected, including
134 * when the Driver Station is disconnected.
135 */
136 virtual void NonePeriodic() {}
137
138 /**
139 * Add a callback to run at a specific period.
140 *
141 * @param callback The callback to run.
142 * @param period The period at which to run the callback.
143 */
144 void AddPeriodic(std::function<void()> callback, wpi::units::second_t period);
145
146 /**
147 * Return the system clock time in microseconds for the start of the current
148 * periodic loop. This is in the same time base as
149 * Timer.getMonotonicTimeStamp(), but is stable through a loop. It is updated
150 * at the beginning of every periodic callback (including the normal periodic
151 * loop).
152 *
153 * @return Robot running time in microseconds, as of the start of the current
154 * periodic function.
155 */
156 wpi::units::microsecond_t GetLoopStartTime() const {
157 return m_callbacks.GetLoopStartTime();
158 }
159
160 /**
161 * Adds an operating mode option using a factory function that creates the
162 * opmode. It's necessary to call PublishOpModes() to make the added modes
163 * visible to the driver station.
164 *
165 * @param factory factory function
166 * @param mode robot mode
167 * @param name name of the operating mode
168 * @param group group of the operating mode
169 * @param description description of the operating mode
170 * @param textColor text color
171 * @param backgroundColor background color
172 */
174 std::string_view name, std::string_view group,
175 std::string_view description,
176 const wpi::util::Color& textColor,
177 const wpi::util::Color& backgroundColor);
178
179 /**
180 * Adds an operating mode option using a factory function that creates the
181 * opmode. It's necessary to call PublishOpModes() to make the added modes
182 * visible to the driver station.
183 *
184 * @param factory factory function
185 * @param mode robot mode
186 * @param name name of the operating mode
187 * @param group group of the operating mode
188 * @param description description of the operating mode
189 */
191 std::string_view name, std::string_view group = {},
192 std::string_view description = {});
193
194 /**
195 * Removes an operating mode option. It's necessary to call PublishOpModes()
196 * to make the removed mode no longer visible to the driver station.
197 *
198 * @param mode robot mode
199 * @param name name of the operating mode
200 */
201 void RemoveOpMode(RobotMode mode, std::string_view name);
202
203 /**
204 * Publishes the operating mode options to the driver station.
205 */
207
208 /**
209 * Clears all operating mode options and publishes an empty list to the driver
210 * station.
211 */
213
214 protected:
215 /**
216 * Main robot loop function. Handles disabled state logic.
217 */
218 void LoopFunc();
219
220 private:
221 struct OpModeData {
222 std::string name;
223 OpModeFactory factory;
224 };
225
227 wpi::util::mutex m_opModeMutex;
228
230 HAL_NotifierHandle m_notifier;
231 wpi::units::second_t m_period;
232 std::chrono::microseconds m_startTime;
233 Alert m_loopOverrunAlert;
234 Watchdog m_watchdog;
235
236 // OpMode lifecycle state
237 int64_t m_lastModeId = -1;
238 bool m_calledDriverStationConnected = false;
239 bool m_lastEnabledState = false;
240 std::shared_ptr<OpMode> m_currentOpMode;
241 std::vector<wpi::internal::PeriodicPriorityQueue::Callback>
242 m_activeOpModeCallbacks;
243 std::optional<wpi::internal::PeriodicPriorityQueue::Callback>
244 m_opmodePeriodic;
245};
246
247/**
248 * OpModeRobot implements the opmode-based robot program framework.
249 *
250 * The OpModeRobot class is intended to be subclassed by a user creating a robot
251 * program. Users must provide their derived class as a template parameter to
252 * this class.
253 *
254 * Opmodes are constructed when selected on the driver station, and destroyed
255 * when the robot is disabled after being enabled or a different opmode is
256 * selected. When no opmode is selected, NonePeriodic() is called. The
257 * DriverStationConnected() function is called the first time the driver station
258 * connects to the robot.
259 *
260 * @tparam Derived derived class
261 */
262template <typename Derived>
264 public:
265 /**
266 * Constructor.
267 *
268 * @param period The period of the robot loop function.
269 */
270 explicit OpModeRobot(wpi::units::second_t period) : OpModeRobotBase{period} {}
271
272 /**
273 * Constructor for an OpModeRobot with a default loop time of 0.02 seconds.
274 */
275 explicit OpModeRobot() : OpModeRobotBase{} {}
276
277 /**
278 * Adds an operating mode option. It's necessary to call PublishOpModes() to
279 * make the added modes visible to the driver station.
280 *
281 * @tparam T opmode class; must be a public, non-abstract subclass of OpMode
282 * with a public constructor that either takes no arguments or accepts a
283 * single argument of this class's type (the latter is preferred).
284 * @param mode robot mode
285 * @param name name of the operating mode
286 * @param group group of the operating mode
287 * @param description description of the operating mode
288 * @param textColor text color
289 * @param backgroundColor background color
290 */
291 template <ConstructibleOpMode<Derived> T>
292 void AddOpMode(RobotMode mode, std::string_view name, std::string_view group,
293 std::string_view description,
294 const wpi::util::Color& textColor,
295 const wpi::util::Color& backgroundColor) {
296 if constexpr (detail::OneArgOpMode<T, Derived>) {
298 [this] { return std::make_unique<T>(*static_cast<Derived*>(this)); },
299 mode, name, group, description, textColor, backgroundColor);
300 } else if constexpr (detail::NoArgOpMode<T>) {
301 AddOpModeFactory([] { return std::make_unique<T>(); }, mode, name, group,
302 description, textColor, backgroundColor);
303 }
304 }
305
306 /**
307 * Adds an operating mode option. It's necessary to call PublishOpModes() to
308 * make the added modes visible to the driver station.
309 *
310 * @tparam T opmode class; must be a public, non-abstract subclass of OpMode
311 * with a public constructor that either takes no arguments or accepts a
312 * single argument of this class's type (the latter is preferred).
313 * @param mode robot mode
314 * @param name name of the operating mode
315 * @param group group of the operating mode
316 * @param description description of the operating mode
317 */
318 template <ConstructibleOpMode<Derived> T>
319 void AddOpMode(RobotMode mode, std::string_view name,
320 std::string_view group = {},
321 std::string_view description = {}) {
322 if constexpr (detail::OneArgOpMode<T, Derived>) {
324 [this] { return std::make_unique<T>(*static_cast<Derived*>(this)); },
325 mode, name, group, description);
326 } else if constexpr (detail::NoArgOpMode<T>) {
327 AddOpModeFactory([] { return std::make_unique<T>(); }, mode, name, group,
328 description);
329 }
330 }
331};
332
333} // namespace wpi
This file defines the DenseMap class.
@ name
Definition base.h:690
Persistent alert to be sent to the driver station.
Definition Alert.hpp:36
void PublishOpModes()
Publishes the operating mode options to the driver station.
void EndCompetition() override
Ends the main loop in StartCompetition().
virtual void SimulationInit()
Function called once during robot initialization in simulation.
Definition OpModeRobot.hpp:110
virtual void NonePeriodic()
Function called periodically anytime when no opmode is selected, including when the Driver Station is...
Definition OpModeRobot.hpp:136
void ClearOpModes()
Clears all operating mode options and publishes an empty list to the driver station.
OpModeRobotBase(OpModeRobotBase &&)=delete
virtual void DisabledExit()
Function called once when the robot exits disabled state.
Definition OpModeRobot.hpp:130
void LoopFunc()
Main robot loop function.
virtual void DisabledInit()
Function called once when the robot becomes disabled.
Definition OpModeRobot.hpp:120
void RemoveOpMode(RobotMode mode, std::string_view name)
Removes an operating mode option.
virtual void RobotPeriodic()
Function called periodically every loop, regardless of enabled state or OpMode selection.
Definition OpModeRobot.hpp:105
static constexpr auto DEFAULT_PERIOD
Default loop period.
Definition OpModeRobot.hpp:66
virtual void SimulationPeriodic()
Function called periodically in simulation.
Definition OpModeRobot.hpp:115
OpModeRobotBase & operator=(OpModeRobotBase &&)=delete
OpModeRobotBase()
Constructor for an OpModeRobot with a default loop time of 0.02 seconds.
void AddOpModeFactory(OpModeFactory factory, RobotMode mode, std::string_view name, std::string_view group, std::string_view description, const wpi::util::Color &textColor, const wpi::util::Color &backgroundColor)
Adds an operating mode option using a factory function that creates the opmode.
void AddOpModeFactory(OpModeFactory factory, RobotMode mode, std::string_view name, std::string_view group={}, std::string_view description={})
Adds an operating mode option using a factory function that creates the opmode.
OpModeRobotBase(wpi::units::second_t period)
Constructor.
std::function< std::unique_ptr< OpMode >()> OpModeFactory
Definition OpModeRobot.hpp:63
void AddPeriodic(std::function< void()> callback, wpi::units::second_t period)
Add a callback to run at a specific period.
virtual void DriverStationConnected()
Code that needs to know the DS state should go here.
Definition OpModeRobot.hpp:99
void StartCompetition() override
Provide an alternate "main loop" via StartCompetition().
wpi::units::microsecond_t GetLoopStartTime() const
Return the system clock time in microseconds for the start of the current periodic loop.
Definition OpModeRobot.hpp:156
virtual void DisabledPeriodic()
Function called periodically while the robot is disabled.
Definition OpModeRobot.hpp:125
OpModeRobot()
Constructor for an OpModeRobot with a default loop time of 0.02 seconds.
Definition OpModeRobot.hpp:275
OpModeRobot(wpi::units::second_t period)
Constructor.
Definition OpModeRobot.hpp:270
void AddOpMode(RobotMode mode, std::string_view name, std::string_view group, std::string_view description, const wpi::util::Color &textColor, const wpi::util::Color &backgroundColor)
Adds an operating mode option.
Definition OpModeRobot.hpp:292
void AddOpMode(RobotMode mode, std::string_view name, std::string_view group={}, std::string_view description={})
Adds an operating mode option.
Definition OpModeRobot.hpp:319
RobotBase()
Constructor for a generic robot program.
A class that's a wrapper around a watchdog timer.
Definition Watchdog.hpp:25
A priority queue for scheduling periodic callbacks based on their next execution time.
Definition PeriodicPriorityQueue.hpp:30
Represents colors that can be used with Addressable LEDs.
Definition Color.hpp:42
Definition DenseMap.hpp:728
Concept indicating a class is derived from OpMode and has either a no-argument constructor or a const...
Definition OpModeRobot.hpp:48
Definition OpModeRobot.hpp:35
Definition OpModeRobot.hpp:37
Definition OpModeRobot.hpp:33
HAL_Handle HAL_NotifierHandle
Definition Types.h:37
Converts a string literal into a format string that will be parsed at compile time and converted into...
Definition printf.h:50
RobotMode
The overall robot mode (not including enabled state).
Definition DriverStationTypes.hpp:15
Definition raw_os_ostream.hpp:19
::std::mutex mutex
Definition mutex.hpp:17
Definition CvSource.hpp:15