WPILibC++ 2024.3.2
RobotBase.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 <chrono>
8#include <thread>
9
10#include <hal/DriverStation.h>
11#include <hal/HALBase.h>
12#include <hal/Main.h>
14#include <wpi/mutex.h>
15
16#include "frc/Errors.h"
17#include "frc/RuntimeType.h"
18
19namespace frc {
20
22
23namespace impl {
24#ifndef __FRC_ROBORIO__
26#endif
27
28template <class Robot>
29void RunRobot(wpi::mutex& m, Robot** robot) {
30 try {
31 static Robot theRobot;
32 {
33 std::scoped_lock lock{m};
34 *robot = &theRobot;
35 }
36 theRobot.StartCompetition();
37 } catch (const frc::RuntimeError& e) {
38 e.Report();
40 err::Error,
41 "The robot program quit unexpectedly."
42 " This is usually due to a code error.\n"
43 " The above stacktrace can help determine where the error occurred.\n"
44 " See https://wpilib.org/stacktrace for more information.\n");
45 throw;
46 } catch (const std::exception& e) {
47 HAL_SendError(1, err::Error, 0, e.what(), "", "", 1);
48 throw;
49 }
50}
51
52} // namespace impl
53
54template <class Robot>
56 int halInit = RunHALInitialization();
57 if (halInit != 0) {
58 return halInit;
59 }
60
61 static wpi::mutex m;
63 static Robot* robot = nullptr;
64 static bool exited = false;
65
66 if (HAL_HasMain()) {
67 std::thread thr([] {
68 try {
69 impl::RunRobot<Robot>(m, &robot);
70 } catch (...) {
72 {
73 std::scoped_lock lock{m};
74 robot = nullptr;
75 exited = true;
76 }
77 cv.notify_all();
78 throw;
79 }
80
82 {
83 std::scoped_lock lock{m};
84 robot = nullptr;
85 exited = true;
86 }
87 cv.notify_all();
88 });
89
91
92 // signal loop to exit
93 if (robot) {
94 robot->EndCompetition();
95 }
96
97 // prefer to join, but detach to exit if it doesn't exit in a timely manner
98 using namespace std::chrono_literals;
99 std::unique_lock lock{m};
100 if (cv.wait_for(lock, 1s, [] { return exited; })) {
101 thr.join();
102 } else {
103 thr.detach();
104 }
105 } else {
106 impl::RunRobot<Robot>(m, &robot);
107 }
108
109#ifndef __FRC_ROBORIO__
111#endif
112 HAL_Shutdown();
113
114 return 0;
115}
116
117/**
118 * Implement a Robot Program framework. The RobotBase class is intended to be
119 * subclassed to create a robot program. The user must implement
120 * StartCompetition() which will be called once and is not expected to exit. The
121 * user must also implement EndCompetition(), which signals to the code in
122 * StartCompetition() that it should exit.
123 *
124 * It is not recommended to subclass this class directly - instead subclass
125 * IterativeRobotBase or TimedRobot.
126 */
128 public:
129 /**
130 * Determine if the Robot is currently enabled.
131 *
132 * @return True if the Robot is currently enabled by the Driver Station.
133 */
134 bool IsEnabled() const;
135
136 /**
137 * Determine if the Robot is currently disabled.
138 *
139 * @return True if the Robot is currently disabled by the Driver Station.
140 */
141 bool IsDisabled() const;
142
143 /**
144 * Determine if the robot is currently in Autonomous mode.
145 *
146 * @return True if the robot is currently operating Autonomously as determined
147 * by the Driver Station.
148 */
149 bool IsAutonomous() const;
150
151 /**
152 * Determine if the robot is currently in Autonomous mode and enabled.
153 *
154 * @return True if the robot us currently operating Autonomously while enabled
155 * as determined by the Driver Station.
156 */
158
159 /**
160 * Determine if the robot is currently in Operator Control mode.
161 *
162 * @return True if the robot is currently operating in Tele-Op mode as
163 * determined by the Driver Station.
164 */
165 bool IsTeleop() const;
166
167 /**
168 * Determine if the robot is current in Operator Control mode and enabled.
169 *
170 * @return True if the robot is currently operating in Tele-Op mode while
171 * enabled as determined by the Driver Station.
172 */
173 bool IsTeleopEnabled() const;
174
175 /**
176 * Determine if the robot is currently in Test mode.
177 *
178 * @return True if the robot is currently running in Test mode as determined
179 * by the Driver Station.
180 */
181 bool IsTest() const;
182
183 /**
184 * Determine if the robot is current in Test mode and enabled.
185 *
186 * @return True if the robot is currently operating in Test mode while
187 * enabled as determined by the Driver Station.
188 */
189 bool IsTestEnabled() const;
190
191 /**
192 * Returns the main thread ID.
193 *
194 * @return The main thread ID.
195 */
196 static std::thread::id GetThreadId();
197
198 /**
199 * Start the main robot code. This function will be called once and should not
200 * exit until signalled by EndCompetition()
201 */
202 virtual void StartCompetition() = 0;
203
204 /** Ends the main loop in StartCompetition(). */
205 virtual void EndCompetition() = 0;
206
207 /**
208 * Get the current runtime type.
209 *
210 * @return Current runtime type.
211 */
213
214 /**
215 * Get if the robot is real.
216 *
217 * @return If the robot is running in the real world.
218 */
219 static constexpr bool IsReal() {
220#ifdef __FRC_ROBORIO__
221 return true;
222#else
223 return false;
224#endif
225 }
226
227 /**
228 * Get if the robot is a simulation.
229 *
230 * @return If the robot is running in simulation.
231 */
232 static constexpr bool IsSimulation() {
233#ifdef __FRC_ROBORIO__
234 return false;
235#else
236 return true;
237#endif
238 }
239
240 /**
241 * Constructor for a generic robot program.
242 *
243 * User code can be placed in the constructor that runs before the
244 * Autonomous or Operator Control period starts. The constructor will run to
245 * completion before Autonomous is entered.
246 *
247 * This must be used to ensure that the communications code starts. In the
248 * future it would be nice to put this code into it's own task that loads on
249 * boot so ensure that it runs.
250 */
252
253 virtual ~RobotBase() = default;
254
255 protected:
256 RobotBase(RobotBase&&) = default;
258
259 static std::thread::id m_threadId;
260};
261
262} // namespace frc
you may not use this file except in compliance with the License You may obtain a copy of the License at software distributed under the License is distributed on an AS IS WITHOUT WARRANTIES OR CONDITIONS OF ANY either express or implied See the License for the specific language governing permissions and limitations under the License LLVM Exceptions to the Apache License As an exception
Definition: ThirdPartyNotices.txt:289
Implement a Robot Program framework.
Definition: RobotBase.h:127
RobotBase()
Constructor for a generic robot program.
bool IsTestEnabled() const
Determine if the robot is current in Test mode and enabled.
static constexpr bool IsReal()
Get if the robot is real.
Definition: RobotBase.h:219
static constexpr bool IsSimulation()
Get if the robot is a simulation.
Definition: RobotBase.h:232
bool IsTest() const
Determine if the robot is currently in Test mode.
static std::thread::id GetThreadId()
Returns the main thread ID.
static std::thread::id m_threadId
Definition: RobotBase.h:259
RobotBase & operator=(RobotBase &&)=default
bool IsAutonomousEnabled() const
Determine if the robot is currently in Autonomous mode and enabled.
bool IsEnabled() const
Determine if the Robot is currently enabled.
virtual void StartCompetition()=0
Start the main robot code.
bool IsTeleop() const
Determine if the robot is currently in Operator Control mode.
static RuntimeType GetRuntimeType()
Get the current runtime type.
bool IsDisabled() const
Determine if the Robot is currently disabled.
virtual void EndCompetition()=0
Ends the main loop in StartCompetition().
bool IsAutonomous() const
Determine if the robot is currently in Autonomous mode.
bool IsTeleopEnabled() const
Determine if the robot is current in Operator Control mode and enabled.
virtual ~RobotBase()=default
RobotBase(RobotBase &&)=default
Runtime error exception.
Definition: Errors.h:20
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.
Definition: VisionPipeline.h:7
void ResetMotorSafety()
void RunRobot(wpi::mutex &m, Robot **robot)
Definition: RobotBase.h:29
Definition: AprilTagPoseEstimator.h:15
int StartRobot()
Definition: RobotBase.h:55
int RunHALInitialization()
RuntimeType
Runtime type.
Definition: RuntimeType.h:11
static constexpr const charge::coulomb_t e(1.6021766208e-19)
elementary charge.
::std::condition_variable condition_variable
Definition: condition_variable.h:16
::std::mutex mutex
Definition: mutex.h:17
#define FRC_ReportError(status, format,...)
Reports an error to the driver station (using HAL_SendError).
Definition: Errors.h:137