WPILibC++  2021.3.1
RobotBase.h
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/HALBase.h>
11 #include <hal/Main.h>
12 #include <wpi/condition_variable.h>
13 #include <wpi/mutex.h>
14 #include <wpi/raw_ostream.h>
15 
16 #include "frc/Base.h"
17 
18 namespace frc {
19 
20 class DriverStation;
21 
22 int RunHALInitialization();
23 
24 namespace impl {
25 
26 template <class Robot>
27 void RunRobot(wpi::mutex& m, Robot** robot) {
28  static Robot theRobot;
29  {
30  std::scoped_lock lock{m};
31  *robot = &theRobot;
32  }
33  theRobot.StartCompetition();
34 }
35 
36 } // namespace impl
37 
38 template <class Robot>
39 int StartRobot() {
40  int halInit = RunHALInitialization();
41  if (halInit != 0) {
42  return halInit;
43  }
44 
45  static wpi::mutex m;
46  static wpi::condition_variable cv;
47  static Robot* robot = nullptr;
48  static bool exited = false;
49 
50  if (HAL_HasMain()) {
51  std::thread thr([] {
52  try {
53  impl::RunRobot<Robot>(m, &robot);
54  } catch (...) {
55  HAL_ExitMain();
56  {
57  std::scoped_lock lock{m};
58  robot = nullptr;
59  exited = true;
60  }
61  cv.notify_all();
62  throw;
63  }
64 
65  HAL_ExitMain();
66  {
67  std::scoped_lock lock{m};
68  robot = nullptr;
69  exited = true;
70  }
71  cv.notify_all();
72  });
73 
74  HAL_RunMain();
75 
76  // signal loop to exit
77  if (robot) {
78  robot->EndCompetition();
79  }
80 
81  // prefer to join, but detach to exit if it doesn't exit in a timely manner
82  using namespace std::chrono_literals;
83  std::unique_lock lock{m};
84  if (cv.wait_for(lock, 1s, [] { return exited; })) {
85  thr.join();
86  } else {
87  thr.detach();
88  }
89  } else {
90  impl::RunRobot<Robot>(m, &robot);
91  }
92 
93  HAL_Shutdown();
94 
95  return 0;
96 }
97 
98 #define START_ROBOT_CLASS(_ClassName_) \
99  WPI_DEPRECATED("Call frc::StartRobot<" #_ClassName_ \
100  ">() in your own main() instead of using the " \
101  "START_ROBOT_CLASS(" #_ClassName_ ") macro.") \
102  int StartRobotClassImpl() { return frc::StartRobot<_ClassName_>(); } \
103  int main() { return StartRobotClassImpl(); }
104 
115 class RobotBase {
116  public:
122  bool IsEnabled() const;
123 
129  bool IsDisabled() const;
130 
137  bool IsAutonomous() const;
138 
145  bool IsAutonomousEnabled() const;
146 
153  bool IsOperatorControl() const;
154 
162 
169  bool IsTest() const;
170 
177  bool IsNewDataAvailable() const;
178 
182  static std::thread::id GetThreadId();
183 
184  virtual void StartCompetition() = 0;
185 
186  virtual void EndCompetition() = 0;
187 
193  static constexpr bool IsReal() {
194 #ifdef __FRC_ROBORIO__
195  return true;
196 #else
197  return false;
198 #endif
199  }
200 
206  static constexpr bool IsSimulation() { return !IsReal(); }
207 
220 
221  virtual ~RobotBase();
222 
223  protected:
224  // m_ds isn't moved in these because DriverStation is a singleton; every
225  // instance of RobotBase has a reference to the same object.
226  RobotBase(RobotBase&&) noexcept;
227  RobotBase& operator=(RobotBase&&) noexcept;
228 
229  DriverStation& m_ds;
230 
231  static std::thread::id m_threadId;
232 };
233 
234 } // namespace frc
HAL_ExitMain
void HAL_ExitMain(void)
Causes HAL_RunMain() to exit.
frc::RobotBase::IsAutonomousEnabled
bool IsAutonomousEnabled() const
Determine if the robot is currently in Autonomous mode and enabled.
frc::RobotBase::IsOperatorControlEnabled
bool IsOperatorControlEnabled() const
Determine if the robot is current in Operator Control mode and enabled.
HAL_RunMain
void HAL_RunMain(void)
Runs the main function provided to HAL_SetMain().
frc::RobotBase::IsEnabled
bool IsEnabled() const
Determine if the Robot is currently enabled.
frc::RobotBase::IsDisabled
bool IsDisabled() const
Determine if the Robot is currently disabled.
frc::RobotBase::IsSimulation
static constexpr bool IsSimulation()
Get if the robot is a simulation.
Definition: RobotBase.h:206
HAL_Shutdown
void HAL_Shutdown(void)
Call this to shut down HAL.
frc::RobotBase::IsAutonomous
bool IsAutonomous() const
Determine if the robot is currently in Autonomous mode.
frc::RobotBase::RobotBase
RobotBase()
Constructor for a generic robot program.
frc::RobotBase::IsTest
bool IsTest() const
Determine if the robot is currently in Test mode.
HAL_HasMain
HAL_Bool HAL_HasMain(void)
Returns true if HAL_SetMain() has been called.
frc::RobotBase::IsReal
static constexpr bool IsReal()
Get if the robot is real.
Definition: RobotBase.h:193
frc::RobotBase::GetThreadId
static std::thread::id GetThreadId()
Gets the ID of the main robot thread.
frc
WPILib FRC namespace.
Definition: VisionRunner.inc:9
frc::RobotBase::IsNewDataAvailable
bool IsNewDataAvailable() const
Indicates if new data is available from the driver station.
frc::RobotBase
Implement a Robot Program framework.
Definition: RobotBase.h:115
frc::RobotBase::IsOperatorControl
bool IsOperatorControl() const
Determine if the robot is currently in Operator Control mode.
frc::DriverStation
Provide access to the network communication data to / from the Driver Station.
Definition: DriverStation.h:28