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