WPILibC++  2020.3.2-60-g3011ebe
RobotBase.h
1 /*----------------------------------------------------------------------------*/
2 /* Copyright (c) 2008-2020 FIRST. All Rights Reserved. */
3 /* Open Source Software - may be modified and shared by FRC teams. The code */
4 /* must be accompanied by the FIRST BSD license file in the root directory of */
5 /* the project. */
6 /*----------------------------------------------------------------------------*/
7 
8 #pragma once
9 
10 #include <chrono>
11 #include <thread>
12 
13 #include <hal/Main.h>
14 #include <wpi/condition_variable.h>
15 #include <wpi/mutex.h>
16 #include <wpi/raw_ostream.h>
17 
18 #include "frc/Base.h"
19 
20 namespace frc {
21 
22 class DriverStation;
23 
24 int RunHALInitialization();
25 
26 namespace impl {
27 
28 template <class Robot>
29 void RunRobot(wpi::mutex& m, Robot** robot) {
30  static Robot theRobot;
31  {
32  std::scoped_lock lock{m};
33  *robot = &theRobot;
34  }
35  theRobot.StartCompetition();
36 }
37 
38 } // namespace impl
39 
40 template <class Robot>
41 int StartRobot() {
42  int halInit = RunHALInitialization();
43  if (halInit != 0) {
44  return halInit;
45  }
46 
47  static wpi::mutex m;
48  static wpi::condition_variable cv;
49  static Robot* robot = nullptr;
50  static bool exited = false;
51 
52  if (HAL_HasMain()) {
53  std::thread thr([] {
54  try {
55  impl::RunRobot<Robot>(m, &robot);
56  } catch (...) {
57  HAL_ExitMain();
58  {
59  std::scoped_lock lock{m};
60  robot = nullptr;
61  exited = true;
62  }
63  cv.notify_all();
64  throw;
65  }
66 
67  HAL_ExitMain();
68  {
69  std::scoped_lock lock{m};
70  robot = nullptr;
71  exited = true;
72  }
73  cv.notify_all();
74  });
75 
76  HAL_RunMain();
77 
78  // signal loop to exit
79  if (robot) robot->EndCompetition();
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  } else {
89  impl::RunRobot<Robot>(m, &robot);
90  }
91 
92  return 0;
93 }
94 
95 #define START_ROBOT_CLASS(_ClassName_) \
96  WPI_DEPRECATED("Call frc::StartRobot<" #_ClassName_ \
97  ">() in your own main() instead of using the " \
98  "START_ROBOT_CLASS(" #_ClassName_ ") macro.") \
99  int StartRobotClassImpl() { return frc::StartRobot<_ClassName_>(); } \
100  int main() { return StartRobotClassImpl(); }
101 
112 class RobotBase {
113  public:
119  bool IsEnabled() const;
120 
126  bool IsDisabled() const;
127 
134  bool IsAutonomous() const;
135 
142  bool IsOperatorControl() const;
143 
150  bool IsTest() const;
151 
158  bool IsNewDataAvailable() const;
159 
163  static std::thread::id GetThreadId();
164 
165  virtual void StartCompetition() = 0;
166 
167  virtual void EndCompetition() = 0;
168 
169  static constexpr bool IsReal() {
170 #ifdef __FRC_ROBORIO__
171  return true;
172 #else
173  return false;
174 #endif
175  }
176 
177  static constexpr bool IsSimulation() { return !IsReal(); }
178 
190  RobotBase();
191 
192  virtual ~RobotBase();
193 
194  protected:
195  // m_ds isn't moved in these because DriverStation is a singleton; every
196  // instance of RobotBase has a reference to the same object.
197  RobotBase(RobotBase&&) noexcept;
198  RobotBase& operator=(RobotBase&&) noexcept;
199 
200  DriverStation& m_ds;
201 
202  static std::thread::id m_threadId;
203 };
204 
205 } // namespace frc
HAL_ExitMain
void HAL_ExitMain(void)
Causes HAL_RunMain() to exit.
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::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::GetThreadId
static std::thread::id GetThreadId()
Gets the ID of the main robot thread.
frc
A class that enforces constraints on the differential drive kinematics.
Definition: PDPSim.h:16
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:112
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:33