WPILibC++ 2027.0.0-alpha-4
Loading...
Searching...
No Matches
RobotBase.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 <chrono>
8#include <string>
9#include <thread>
10
12#include "wpi/hal/HALBase.h"
13#include "wpi/hal/Main.h"
15#include "wpi/system/Errors.hpp"
19#include "wpi/util/mutex.hpp"
20#include "wpi/util/string.h"
21
22namespace wpi {
23
25
26namespace impl {
27#ifndef __FRC_SYSTEMCORE__
29#endif
30
31template <class Robot>
32void RunRobot(wpi::util::mutex& m, Robot** robot) {
33 try {
34 static Robot theRobot;
35 {
36 std::scoped_lock lock{m};
37 *robot = &theRobot;
38 }
39 theRobot.StartCompetition();
40 } catch (const wpi::RuntimeError& e) {
41 e.Report();
43 err::Error,
44 "The robot program quit unexpectedly."
45 " This is usually due to a code error.\n"
46 " The above stacktrace can help determine where the error occurred.\n"
47 " See https://wpilib.org/stacktrace for more information.\n");
48 throw;
49 } catch (const std::exception& e) {
50 HAL_SendError(1, err::Error, 0, e.what(), "", "", 1);
51 throw;
52 }
53}
54
55} // namespace impl
56
57template <class Robot>
59 uint32_t foundMajor;
60 uint32_t foundMinor;
61 uint32_t expectedMajor;
62 uint32_t expectedMinor;
63 WPI_String runtimePath;
64 if (!WPI_IsRuntimeValid(&foundMajor, &foundMinor, &expectedMajor,
65 &expectedMinor, &runtimePath)) {
66 // We could make this error better, however unlike Java, there is only a
67 // single scenario that could be occuring. The entirety of VS is too out
68 // of date. In most cases the linker should detect this, but not always.
69 fmt::println(
70 "Your copy of Visual Studio is out of date. Please update it.\n");
71 return 1;
72 }
73
74 int halInit = RunHALInitialization();
75 if (halInit != 0) {
76 return halInit;
77 }
78
79 static wpi::util::mutex m;
81 static Robot* robot = nullptr;
82 static bool exited = false;
83
84 if (HAL_HasMain()) {
85 std::thread thr([] {
86 try {
87 impl::RunRobot<Robot>(m, &robot);
88 } catch (...) {
90 {
91 std::scoped_lock lock{m};
92 robot = nullptr;
93 exited = true;
94 }
95 cv.notify_all();
96 throw;
97 }
98
100 {
101 std::scoped_lock lock{m};
102 robot = nullptr;
103 exited = true;
104 }
105 cv.notify_all();
106 });
107
108 HAL_RunMain();
109
110 // signal loop to exit
111 if (robot) {
112 robot->EndCompetition();
113 }
114
115 // prefer to join, but detach to exit if it doesn't exit in a timely manner
116 using namespace std::chrono_literals;
117 std::unique_lock lock{m};
118 if (cv.wait_for(lock, 1s, [] { return exited; })) {
119 thr.join();
120 } else {
121 thr.detach();
122 }
123 } else {
124 impl::RunRobot<Robot>(m, &robot);
125 }
126
127#ifndef __FRC_SYSTEMCORE__
129#endif
130 HAL_Shutdown();
131
132 return 0;
133}
134
135/**
136 * Implement a Robot Program framework. The RobotBase class is intended to be
137 * subclassed to create a robot program. The user must implement
138 * StartCompetition() which will be called once and is not expected to exit. The
139 * user must also implement EndCompetition(), which signals to the code in
140 * StartCompetition() that it should exit.
141 *
142 * It is not recommended to subclass this class directly - instead subclass
143 * IterativeRobotBase or TimedRobot.
144 */
146 public:
147 /**
148 * Determine if the Robot is currently enabled.
149 *
150 * @return True if the Robot is currently enabled by the Driver Station.
151 */
152 static bool IsEnabled();
153
154 /**
155 * Determine if the Robot is currently disabled.
156 *
157 * @return True if the Robot is currently disabled by the Driver Station.
158 */
159 static bool IsDisabled();
160
161 /**
162 * Determine if the robot is currently in Autonomous mode.
163 *
164 * @return True if the robot is currently operating Autonomously as determined
165 * by the Driver Station.
166 */
167 static bool IsAutonomous();
168
169 /**
170 * Determine if the robot is currently in Autonomous mode and enabled.
171 *
172 * @return True if the robot us currently operating Autonomously while enabled
173 * as determined by the Driver Station.
174 */
175 static bool IsAutonomousEnabled();
176
177 /**
178 * Determine if the robot is currently in Operator Control mode.
179 *
180 * @return True if the robot is currently operating in Tele-Op mode as
181 * determined by the Driver Station.
182 */
183 static bool IsTeleop();
184
185 /**
186 * Determine if the robot is current in Operator Control mode and enabled.
187 *
188 * @return True if the robot is currently operating in Tele-Op mode while
189 * enabled as determined by the Driver Station.
190 */
191 static bool IsTeleopEnabled();
192
193 /**
194 * Determine if the robot is currently in Test mode.
195 *
196 * @return True if the robot is currently running in Test mode as determined
197 * by the Driver Station.
198 */
199 static bool IsTest();
200
201 /**
202 * Determine if the robot is current in Test mode and enabled.
203 *
204 * @return True if the robot is currently operating in Test mode while
205 * enabled as determined by the Driver Station.
206 */
207 static bool IsTestEnabled();
208
209 /**
210 * Gets the currently selected operating mode of the driver station. Note this
211 * does not mean the robot is enabled; use IsEnabled() for that.
212 *
213 * @return the unique ID provided by the DriverStation::AddOpMode() function;
214 * may return 0 or a unique ID not added, so callers should be prepared to
215 * handle that case
216 */
217 static int64_t GetOpModeId();
218
219 /**
220 * Gets the currently selected operating mode of the driver station. Note this
221 * does not mean the robot is enabled; use IsEnabled() for that.
222 *
223 * @return Operating mode string; may return a string not in the list of
224 * options, so callers should be prepared to handle that case
225 */
226 static std::string GetOpMode();
227
228 /**
229 * Returns the main thread ID.
230 *
231 * @return The main thread ID.
232 */
233 static std::thread::id GetThreadId();
234
235 /**
236 * Start the main robot code. This function will be called once and should not
237 * exit until signalled by EndCompetition()
238 */
239 virtual void StartCompetition() = 0;
240
241 /** Ends the main loop in StartCompetition(). */
242 virtual void EndCompetition() = 0;
243
244 /**
245 * Get the current runtime type.
246 *
247 * @return Current runtime type.
248 */
250
251 /**
252 * Get if the robot is real.
253 *
254 * @return If the robot is running in the real world.
255 */
256 static constexpr bool IsReal() {
257#ifdef __FRC_SYSTEMCORE__
258 return true;
259#else
260 return false;
261#endif
262 }
263
264 /**
265 * Get if the robot is a simulation.
266 *
267 * @return If the robot is running in simulation.
268 */
269 static constexpr bool IsSimulation() {
270#ifdef __FRC_SYSTEMCORE__
271 return false;
272#else
273 return true;
274#endif
275 }
276
277 /**
278 * Constructor for a generic robot program.
279 *
280 * User code can be placed in the constructor that runs before the
281 * Autonomous or Operator Control period starts. The constructor will run to
282 * completion before Autonomous is entered.
283 *
284 * This must be used to ensure that the communications code starts. In the
285 * future it would be nice to put this code into it's own task that loads on
286 * boot so ensure that it runs.
287 */
289
290 virtual ~RobotBase() = default;
291
292 protected:
293 RobotBase(RobotBase&&) = default;
295
296 static std::thread::id m_threadId;
298};
299
300} // namespace wpi
#define WPILIB_ReportError(status, format,...)
Reports an error to the driver station (using HAL_SendError).
Definition Errors.hpp:137
int32_t WPI_IsRuntimeValid(uint32_t *FoundMajor, uint32_t *FoundMinor, uint32_t *ExpectedMajor, uint32_t *ExpectedMinor, WPI_String *RuntimePath)
NT_Listener connListenerHandle
Definition RobotBase.hpp:297
static int64_t GetOpModeId()
Gets the currently selected operating mode of the driver station.
virtual void EndCompetition()=0
Ends the main loop in StartCompetition().
static constexpr bool IsSimulation()
Get if the robot is a simulation.
Definition RobotBase.hpp:269
RobotBase(RobotBase &&)=default
static bool IsDisabled()
Determine if the Robot is currently disabled.
static std::thread::id GetThreadId()
Returns the main thread ID.
static std::thread::id m_threadId
Definition RobotBase.hpp:296
static RuntimeType GetRuntimeType()
Get the current runtime type.
static std::string GetOpMode()
Gets the currently selected operating mode of the driver station.
static bool IsEnabled()
Determine if the Robot is currently enabled.
virtual ~RobotBase()=default
RobotBase()
Constructor for a generic robot program.
static bool IsTeleop()
Determine if the robot is currently in Operator Control mode.
static bool IsTest()
Determine if the robot is currently in Test mode.
static constexpr bool IsReal()
Get if the robot is real.
Definition RobotBase.hpp:256
static bool IsAutonomous()
Determine if the robot is currently in Autonomous mode.
static bool IsTestEnabled()
Determine if the robot is current in Test mode and enabled.
virtual void StartCompetition()=0
Start the main robot code.
static bool IsTeleopEnabled()
Determine if the robot is current in Operator Control mode and enabled.
static bool IsAutonomousEnabled()
Determine if the robot is currently in Autonomous mode and enabled.
RobotBase & operator=(RobotBase &&)=default
Runtime error exception.
Definition Errors.hpp:20
void Report() const
Reports error to Driver Station (using HAL_SendError).
void HAL_Shutdown(void)
Call this to shut down HAL.
int32_t HAL_SendError(HAL_Bool isError, int32_t errorCode, HAL_Bool isLVCode, const char *details, const char *location, const char *callStack, HAL_Bool printMsg)
Sends an error to the driver station.
void HAL_RunMain(void)
Runs the main function provided to HAL_SetMain().
HAL_Bool HAL_HasMain(void)
Returns true if HAL_SetMain() has been called.
void HAL_ExitMain(void)
Causes HAL_RunMain() to exit.
NT_Handle NT_Listener
Definition ntcore_c.h:39
Definition VisionPipeline.hpp:7
Definition RobotBase.hpp:26
void RunRobot(wpi::util::mutex &m, Robot **robot)
Definition RobotBase.hpp:32
void ResetMotorSafety()
::std::condition_variable condition_variable
Definition condition_variable.hpp:16
::std::mutex mutex
Definition mutex.hpp:17
Definition CvSource.hpp:15
RuntimeType
Runtime type.
Definition RuntimeType.hpp:11
int RunHALInitialization()
int StartRobot()
Definition RobotBase.hpp:58
A const UTF8 string.
Definition string.h:12