blob: f2511df7da46cb8d14ac4a0a47517bc9e3840652 [file] [log] [blame]
Brian Silverman26e4e522015-12-17 01:56:40 -05001/*----------------------------------------------------------------------------*/
2/* Copyright (c) FIRST 2008. 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 $(WIND_BASE)/WPILib. */
5/*----------------------------------------------------------------------------*/
6#include "IterativeRobot.h"
7
8#include "DriverStation.h"
9#include "SmartDashboard/SmartDashboard.h"
10#include "LiveWindow/LiveWindow.h"
11#include "networktables/NetworkTable.h"
12
13//not sure what this is used for yet.
14#ifdef _UNIX
15 #include <unistd.h>
16#endif
17
18const double IterativeRobot::kDefaultPeriod = 0;
19
20/**
21 * Set the period for the periodic functions.
22 *
23 * @param period The period of the periodic function calls. 0.0 means sync to driver station control data.
24 */
25void IterativeRobot::SetPeriod(double period)
26{
27 if (period > 0.0)
28 {
29 // Not syncing with the DS, so start the timer for the main loop
30 m_mainLoopTimer.Reset();
31 m_mainLoopTimer.Start();
32 }
33 else
34 {
35 // Syncing with the DS, don't need the timer
36 m_mainLoopTimer.Stop();
37 }
38 m_period = period;
39}
40
41/**
42 * Get the period for the periodic functions.
43 * Returns 0.0 if configured to syncronize with DS control data packets.
44 * @return Period of the periodic function calls
45 */
46double IterativeRobot::GetPeriod()
47{
48 return m_period;
49}
50
51/**
52 * Get the number of loops per second for the IterativeRobot
53 * @return Frequency of the periodic function calls
54 */
55double IterativeRobot::GetLoopsPerSec()
56{
57 // If syncing to the driver station, we don't know the rate,
58 // so guess something close.
59 if (m_period <= 0.0)
60 return 50.0;
61 return 1.0 / m_period;
62}
63
64/**
65 * Provide an alternate "main loop" via StartCompetition().
66 *
67 * This specific StartCompetition() implements "main loop" behavior like that of the FRC
68 * control system in 2008 and earlier, with a primary (slow) loop that is
69 * called periodically, and a "fast loop" (a.k.a. "spin loop") that is
70 * called as fast as possible with no delay between calls.
71 */
72void IterativeRobot::StartCompetition()
73{
74 LiveWindow *lw = LiveWindow::GetInstance();
75 // first and one-time initialization
76 SmartDashboard::init();
77 NetworkTable::GetTable("LiveWindow")->GetSubTable("~STATUS~")->PutBoolean("LW Enabled", false);
78 RobotInit();
79
80 // loop forever, calling the appropriate mode-dependent function
81 lw->SetEnabled(false);
82 while (true)
83 {
84 // Call the appropriate function depending upon the current robot mode
85 if (IsDisabled())
86 {
87 // call DisabledInit() if we are now just entering disabled mode from
88 // either a different mode or from power-on
89 if(!m_disabledInitialized)
90 {
91 lw->SetEnabled(false);
92 DisabledInit();
93 m_disabledInitialized = true;
94 // reset the initialization flags for the other modes
95 m_autonomousInitialized = false;
96 m_teleopInitialized = false;
97 m_testInitialized = false;
98 }
99 if (NextPeriodReady())
100 {
101 // TODO: HALNetworkCommunicationObserveUserProgramDisabled();
102 DisabledPeriodic();
103 }
104 }
105 else if (IsAutonomous())
106 {
107 // call AutonomousInit() if we are now just entering autonomous mode from
108 // either a different mode or from power-on
109 if(!m_autonomousInitialized)
110 {
111 lw->SetEnabled(false);
112 AutonomousInit();
113 m_autonomousInitialized = true;
114 // reset the initialization flags for the other modes
115 m_disabledInitialized = false;
116 m_teleopInitialized = false;
117 m_testInitialized = false;
118 }
119 if (NextPeriodReady())
120 {
121 // TODO: HALNetworkCommunicationObserveUserProgramAutonomous();
122 AutonomousPeriodic();
123 }
124 }
125 else if (IsTest())
126 {
127 // call TestInit() if we are now just entering test mode from
128 // either a different mode or from power-on
129 if(!m_testInitialized)
130 {
131 lw->SetEnabled(true);
132 TestInit();
133 m_testInitialized = true;
134 // reset the initialization flags for the other modes
135 m_disabledInitialized = false;
136 m_autonomousInitialized = false;
137 m_teleopInitialized = false;
138 }
139 if (NextPeriodReady())
140 {
141 // TODO: HALNetworkCommunicationObserveUserProgramTest();
142 TestPeriodic();
143 }
144 }
145 else
146 {
147 // call TeleopInit() if we are now just entering teleop mode from
148 // either a different mode or from power-on
149 if(!m_teleopInitialized)
150 {
151 lw->SetEnabled(false);
152 TeleopInit();
153 m_teleopInitialized = true;
154 // reset the initialization flags for the other modes
155 m_disabledInitialized = false;
156 m_autonomousInitialized = false;
157 m_testInitialized = false;
158 Scheduler::GetInstance()->SetEnabled(true);
159 }
160 if (NextPeriodReady())
161 {
162 // TODO: HALNetworkCommunicationObserveUserProgramTeleop();
163 TeleopPeriodic();
164 }
165 }
166 // wait for driver station data so the loop doesn't hog the CPU
167 m_ds.WaitForData();
168 }
169}
170
171/**
172 * Determine if the periodic functions should be called.
173 *
174 * If m_period > 0.0, call the periodic function every m_period as compared
175 * to Timer.Get(). If m_period == 0.0, call the periodic functions whenever
176 * a packet is received from the Driver Station, or about every 20ms.
177 *
178 * @todo Decide what this should do if it slips more than one cycle.
179 */
180
181bool IterativeRobot::NextPeriodReady()
182{
183 if (m_period > 0.0)
184 {
185 return m_mainLoopTimer.HasPeriodPassed(m_period);
186 }
187 else
188 {
189 // XXX: BROKEN! return m_ds->IsNewControlData();
190 }
191 return true;
192}
193
194/**
195 * Robot-wide initialization code should go here.
196 *
197 * Users should override this method for default Robot-wide initialization which will
198 * be called when the robot is first powered on. It will be called exactly 1 time.
199 */
200void IterativeRobot::RobotInit()
201{
202 printf("Default %s() method... Overload me!\n", __FUNCTION__);
203}
204
205/**
206 * Initialization code for disabled mode should go here.
207 *
208 * Users should override this method for initialization code which will be called each time
209 * the robot enters disabled mode.
210 */
211void IterativeRobot::DisabledInit()
212{
213 printf("Default %s() method... Overload me!\n", __FUNCTION__);
214}
215
216/**
217 * Initialization code for autonomous mode should go here.
218 *
219 * Users should override this method for initialization code which will be called each time
220 * the robot enters autonomous mode.
221 */
222void IterativeRobot::AutonomousInit()
223{
224 printf("Default %s() method... Overload me!\n", __FUNCTION__);
225}
226
227/**
228 * Initialization code for teleop mode should go here.
229 *
230 * Users should override this method for initialization code which will be called each time
231 * the robot enters teleop mode.
232 */
233void IterativeRobot::TeleopInit()
234{
235 printf("Default %s() method... Overload me!\n", __FUNCTION__);
236}
237
238/**
239 * Initialization code for test mode should go here.
240 *
241 * Users should override this method for initialization code which will be called each time
242 * the robot enters test mode.
243 */
244void IterativeRobot::TestInit()
245{
246 printf("Default %s() method... Overload me!\n", __FUNCTION__);
247}
248
249/**
250 * Periodic code for disabled mode should go here.
251 *
252 * Users should override this method for code which will be called periodically at a regular
253 * rate while the robot is in disabled mode.
254 */
255void IterativeRobot::DisabledPeriodic()
256{
257 static bool firstRun = true;
258 if (firstRun)
259 {
260 printf("Default %s() method... Overload me!\n", __FUNCTION__);
261 firstRun = false;
262 }
263}
264
265/**
266 * Periodic code for autonomous mode should go here.
267 *
268 * Users should override this method for code which will be called periodically at a regular
269 * rate while the robot is in autonomous mode.
270 */
271void IterativeRobot::AutonomousPeriodic()
272{
273 static bool firstRun = true;
274 if (firstRun)
275 {
276 printf("Default %s() method... Overload me!\n", __FUNCTION__);
277 firstRun = false;
278 }
279}
280
281/**
282 * Periodic code for teleop mode should go here.
283 *
284 * Users should override this method for code which will be called periodically at a regular
285 * rate while the robot is in teleop mode.
286 */
287void IterativeRobot::TeleopPeriodic()
288{
289 static bool firstRun = true;
290 if (firstRun)
291 {
292 printf("Default %s() method... Overload me!\n", __FUNCTION__);
293 firstRun = false;
294 }
295}
296
297/**
298 * Periodic code for test mode should go here.
299 *
300 * Users should override this method for code which will be called periodically at a regular
301 * rate while the robot is in test mode.
302 */
303void IterativeRobot::TestPeriodic()
304{
305 static bool firstRun = true;
306 if (firstRun)
307 {
308 printf("Default %s() method... Overload me!\n", __FUNCTION__);
309 firstRun = false;
310 }
311}
312