001 /*----------------------------------------------------------------------------*/ 002 /* Copyright (c) FIRST 2008-2012. All Rights Reserved. */ 003 /* Open Source Software - may be modified and shared by FRC teams. The code */ 004 /* must be accompanied by the FIRST BSD license file in the root directory of */ 005 /* the project. */ 006 /*----------------------------------------------------------------------------*/ 007 package edu.wpi.first.wpilibj; 008 009 import com.sun.squawk.*; 010 import edu.wpi.first.wpilibj.communication.FRCControl; 011 import edu.wpi.first.wpilibj.communication.UsageReporting; 012 import edu.wpi.first.wpilibj.livewindow.LiveWindow; 013 014 /** 015 * IterativeRobot implements a specific type of Robot Program framework, extending the RobotBase class. 016 * 017 * The IterativeRobot class is intended to be subclassed by a user creating a robot program. 018 * 019 * This class is intended to implement the "old style" default code, by providing 020 * the following functions which are called by the main loop, startCompetition(), at the appropriate times: 021 * 022 * robotInit() -- provide for initialization at robot power-on 023 * 024 * init() functions -- each of the following functions is called once when the 025 * appropriate mode is entered: 026 * - DisabledInit() -- called only when first disabled 027 * - AutonomousInit() -- called each and every time autonomous is entered from another mode 028 * - TeleopInit() -- called each and every time teleop is entered from another mode 029 * - TestInit() -- called each and every time test mode is entered from anothermode 030 * 031 * Periodic() functions -- each of these functions is called iteratively at the 032 * appropriate periodic rate (aka the "slow loop"). The period of 033 * the iterative robot is synced to the driver station control packets, 034 * giving a periodic frequency of about 50Hz (50 times per second). 035 * - disabledPeriodic() 036 * - autonomousPeriodic() 037 * - teleopPeriodic() 038 * - testPeriodoc() 039 * 040 */ 041 public class IterativeRobot extends RobotBase { 042 043 private final static boolean TRACE_LOOP_ALLOCATIONS = false; // master tracing switch 044 private final static boolean TRACE_LOOP_ALLOCATIONS_AFTER_INIT = true; // trace before or after all phases initialize 045 046 private boolean m_disabledInitialized; 047 private boolean m_autonomousInitialized; 048 private boolean m_teleopInitialized; 049 private boolean m_testInitialized; 050 051 /** 052 * Constructor for RobotIterativeBase 053 * 054 * The constructor initializes the instance variables for the robot to indicate 055 * the status of initialization for disabled, autonomous, and teleop code. 056 */ 057 public IterativeRobot() { 058 // set status for initialization of disabled, autonomous, and teleop code. 059 m_disabledInitialized = false; 060 m_autonomousInitialized = false; 061 m_teleopInitialized = false; 062 m_testInitialized = false; 063 } 064 065 /** 066 * Provide an alternate "main loop" via startCompetition(). 067 * 068 */ 069 public void startCompetition() { 070 UsageReporting.report(UsageReporting.kResourceType_Framework, UsageReporting.kFramework_Iterative); 071 072 robotInit(); 073 074 // tracing support: 075 final int TRACE_LOOP_MAX = 100; 076 int loopCount = TRACE_LOOP_MAX; 077 Object marker = null; 078 boolean didDisabledPeriodic = false; 079 boolean didAutonomousPeriodic = false; 080 boolean didTeleopPeriodic = false; 081 boolean didTestPeriodic = false; 082 if (TRACE_LOOP_ALLOCATIONS) { 083 GC.initHeapStats(); 084 if (!TRACE_LOOP_ALLOCATIONS_AFTER_INIT) { 085 System.out.println("=== Trace allocation in competition loop! ===="); 086 marker = new Object(); // start counting objects before any loop starts - includes class initialization 087 } 088 } 089 090 // loop forever, calling the appropriate mode-dependent function 091 LiveWindow.setEnabled(false); 092 while (true) { 093 if (TRACE_LOOP_ALLOCATIONS && didDisabledPeriodic && didAutonomousPeriodic && didTeleopPeriodic && --loopCount <= 0) { 094 System.out.println("!!!!! Stop loop!"); 095 break; 096 } 097 // Call the appropriate function depending upon the current robot mode 098 if (isDisabled()) { 099 // call DisabledInit() if we are now just entering disabled mode from 100 // either a different mode or from power-on 101 if (!m_disabledInitialized) { 102 LiveWindow.setEnabled(false); 103 disabledInit(); 104 m_disabledInitialized = true; 105 // reset the initialization flags for the other modes 106 m_autonomousInitialized = false; 107 m_teleopInitialized = false; 108 m_testInitialized = false; 109 } 110 if (nextPeriodReady()) { 111 FRCControl.observeUserProgramDisabled(); 112 disabledPeriodic(); 113 didDisabledPeriodic = true; 114 } 115 } else if (isTest()) { 116 // call TestInit() if we are now just entering test mode from either 117 // a different mode or from power-on 118 if (!m_testInitialized) { 119 LiveWindow.setEnabled(true); 120 testInit(); 121 m_testInitialized = true; 122 m_autonomousInitialized = false; 123 m_teleopInitialized = false; 124 m_disabledInitialized = false; 125 } 126 if (nextPeriodReady()) { 127 FRCControl.observeUserProgramTest(); 128 testPeriodic(); 129 didTestPeriodic = true; 130 } 131 } else if (isAutonomous()) { 132 // call Autonomous_Init() if this is the first time 133 // we've entered autonomous_mode 134 if (!m_autonomousInitialized) { 135 LiveWindow.setEnabled(false); 136 // KBS NOTE: old code reset all PWMs and relays to "safe values" 137 // whenever entering autonomous mode, before calling 138 // "Autonomous_Init()" 139 autonomousInit(); 140 m_autonomousInitialized = true; 141 m_testInitialized = false; 142 m_teleopInitialized = false; 143 m_disabledInitialized = false; 144 } 145 if (nextPeriodReady()) { 146 getWatchdog().feed(); 147 FRCControl.observeUserProgramAutonomous(); 148 autonomousPeriodic(); 149 didAutonomousPeriodic = true; 150 } 151 } else { 152 // call Teleop_Init() if this is the first time 153 // we've entered teleop_mode 154 if (!m_teleopInitialized) { 155 LiveWindow.setEnabled(false); 156 teleopInit(); 157 m_teleopInitialized = true; 158 m_testInitialized = false; 159 m_autonomousInitialized = false; 160 m_disabledInitialized = false; 161 } 162 if (nextPeriodReady()) { 163 getWatchdog().feed(); 164 FRCControl.observeUserProgramTeleop(); 165 teleopPeriodic(); 166 didTeleopPeriodic = true; 167 } 168 } 169 170 if (TRACE_LOOP_ALLOCATIONS && TRACE_LOOP_ALLOCATIONS_AFTER_INIT && 171 didDisabledPeriodic && didAutonomousPeriodic && didTeleopPeriodic && loopCount == TRACE_LOOP_MAX) { 172 System.out.println("=== Trace allocation in competition loop! ===="); 173 marker = new Object(); // start counting objects after 1st loop completes - ignore class initialization 174 } 175 m_ds.waitForData(); 176 } 177 if (TRACE_LOOP_ALLOCATIONS) { 178 GC.printHeapStats(marker, false); 179 } 180 } 181 182 /** 183 * Determine if the appropriate next periodic function should be called. 184 * Call the periodic functions whenever a packet is received from the Driver Station, or about every 20ms. 185 */ 186 private boolean nextPeriodReady() { 187 return m_ds.isNewControlData(); 188 } 189 190 /* ----------- Overridable initialization code -----------------*/ 191 192 /** 193 * Robot-wide initialization code should go here. 194 * 195 * Users should override this method for default Robot-wide initialization which will 196 * be called when the robot is first powered on. It will be called exactly 1 time. 197 */ 198 public void robotInit() { 199 System.out.println("Default IterativeRobot.robotInit() method... Overload me!"); 200 } 201 202 /** 203 * Initialization code for disabled mode should go here. 204 * 205 * Users should override this method for initialization code which will be called each time 206 * the robot enters disabled mode. 207 */ 208 public void disabledInit() { 209 System.out.println("Default IterativeRobot.disabledInit() method... Overload me!"); 210 } 211 212 /** 213 * Initialization code for autonomous mode should go here. 214 * 215 * Users should override this method for initialization code which will be called each time 216 * the robot enters autonomous mode. 217 */ 218 public void autonomousInit() { 219 System.out.println("Default IterativeRobot.autonomousInit() method... Overload me!"); 220 } 221 222 /** 223 * Initialization code for teleop mode should go here. 224 * 225 * Users should override this method for initialization code which will be called each time 226 * the robot enters teleop mode. 227 */ 228 public void teleopInit() { 229 System.out.println("Default IterativeRobot.teleopInit() method... Overload me!"); 230 } 231 232 /** 233 * Initialization code for test mode should go here. 234 * 235 * Users should override this method for initialization code which will be called each time 236 * the robot enters test mode. 237 */ 238 public void testInit() { 239 System.out.println("Default IterativeRobot.testInit() method... Overload me!"); 240 } 241 242 /* ----------- Overridable periodic code -----------------*/ 243 244 private boolean dpFirstRun = true; 245 /** 246 * Periodic code for disabled mode should go here. 247 * 248 * Users should override this method for code which will be called periodically at a regular 249 * rate while the robot is in disabled mode. 250 */ 251 public void disabledPeriodic() { 252 if (dpFirstRun) { 253 System.out.println("Default IterativeRobot.disabledPeriodic() method... Overload me!"); 254 dpFirstRun = false; 255 } 256 Timer.delay(0.001); 257 } 258 259 private boolean apFirstRun = true; 260 261 /** 262 * Periodic code for autonomous mode should go here. 263 * 264 * Users should override this method for code which will be called periodically at a regular 265 * rate while the robot is in autonomous mode. 266 */ 267 public void autonomousPeriodic() { 268 if (apFirstRun) { 269 System.out.println("Default IterativeRobot.autonomousPeriodic() method... Overload me!"); 270 apFirstRun = false; 271 } 272 Timer.delay(0.001); 273 } 274 275 private boolean tpFirstRun = true; 276 277 /** 278 * Periodic code for teleop mode should go here. 279 * 280 * Users should override this method for code which will be called periodically at a regular 281 * rate while the robot is in teleop mode. 282 */ 283 public void teleopPeriodic() { 284 if (tpFirstRun) { 285 System.out.println("Default IterativeRobot.teleopPeriodic() method... Overload me!"); 286 tpFirstRun = false; 287 } 288 Timer.delay(0.001); 289 } 290 291 private boolean tmpFirstRun = true; 292 293 /** 294 * Periodic code for test mode should go here 295 * 296 * Users should override this method for code which will be called periodically at a regular rate 297 * while the robot is in test mode. 298 */ 299 public void testPeriodic() { 300 if (tmpFirstRun) { 301 System.out.println("Default IterativeRobot.testPeriodic() method... Overload me!"); 302 tmpFirstRun = false; 303 } 304 } 305 }