001/*----------------------------------------------------------------------------*/ 002/* Copyright (c) FIRST 2008-2017. 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 008package edu.wpi.first.wpilibj; 009 010import edu.wpi.first.wpilibj.hal.FRCNetComm.tInstances; 011import edu.wpi.first.wpilibj.hal.FRCNetComm.tResourceType; 012import edu.wpi.first.wpilibj.hal.HAL; 013import edu.wpi.first.wpilibj.livewindow.LiveWindow; 014 015/** 016 * IterativeRobot implements a specific type of Robot Program framework, extending the RobotBase 017 * class. 018 * 019 * <p>The IterativeRobot class is intended to be subclassed by a user creating a robot program. 020 * 021 * <p>This class is intended to implement the "old style" default code, by providing the following 022 * functions which are called by the main loop, startCompetition(), at the appropriate times: 023 * 024 * <p>robotInit() -- provide for initialization at robot power-on 025 * 026 * <p>init() functions -- each of the following functions is called once when the appropriate mode 027 * is entered: - DisabledInit() -- called only when first disabled - AutonomousInit() -- called each 028 * and every time autonomous is entered from another mode - TeleopInit() -- called each and every 029 * time teleop is entered from another mode - TestInit() -- called each and every time test mode is 030 * entered from anothermode 031 * 032 * <p>Periodic() functions -- each of these functions is called iteratively at the appropriate 033 * periodic rate (aka the "slow loop"). The period of the iterative robot is synced to the driver 034 * station control packets, giving a periodic frequency of about 50Hz (50 times per second). - 035 * disabledPeriodic() - autonomousPeriodic() - teleopPeriodic() - testPeriodoc() 036 */ 037public class IterativeRobot extends RobotBase { 038 private boolean m_disabledInitialized; 039 private boolean m_autonomousInitialized; 040 private boolean m_teleopInitialized; 041 private boolean m_testInitialized; 042 043 /** 044 * Constructor for RobotIterativeBase. 045 * 046 * <p>The constructor initializes the instance variables for the robot to indicate the status of 047 * initialization for disabled, autonomous, and teleop code. 048 */ 049 public IterativeRobot() { 050 // set status for initialization of disabled, autonomous, and teleop code. 051 m_disabledInitialized = false; 052 m_autonomousInitialized = false; 053 m_teleopInitialized = false; 054 m_testInitialized = false; 055 } 056 057 /** 058 * Provide an alternate "main loop" via startCompetition(). 059 */ 060 public void startCompetition() { 061 HAL.report(tResourceType.kResourceType_Framework, 062 tInstances.kFramework_Iterative); 063 064 robotInit(); 065 066 // Tell the DS that the robot is ready to be enabled 067 HAL.observeUserProgramStarting(); 068 069 // loop forever, calling the appropriate mode-dependent function 070 LiveWindow.setEnabled(false); 071 while (true) { 072 // Wait for new data to arrive 073 m_ds.waitForData(); 074 // Call the appropriate function depending upon the current robot mode 075 if (isDisabled()) { 076 // call DisabledInit() if we are now just entering disabled mode from 077 // either a different mode or from power-on 078 if (!m_disabledInitialized) { 079 LiveWindow.setEnabled(false); 080 disabledInit(); 081 m_disabledInitialized = true; 082 // reset the initialization flags for the other modes 083 m_autonomousInitialized = false; 084 m_teleopInitialized = false; 085 m_testInitialized = false; 086 } 087 HAL.observeUserProgramDisabled(); 088 disabledPeriodic(); 089 } else if (isTest()) { 090 // call TestInit() if we are now just entering test mode from either 091 // a different mode or from power-on 092 if (!m_testInitialized) { 093 LiveWindow.setEnabled(true); 094 testInit(); 095 m_testInitialized = true; 096 m_autonomousInitialized = false; 097 m_teleopInitialized = false; 098 m_disabledInitialized = false; 099 } 100 HAL.observeUserProgramTest(); 101 testPeriodic(); 102 } else if (isAutonomous()) { 103 // call Autonomous_Init() if this is the first time 104 // we've entered autonomous_mode 105 if (!m_autonomousInitialized) { 106 LiveWindow.setEnabled(false); 107 // KBS NOTE: old code reset all PWMs and relays to "safe values" 108 // whenever entering autonomous mode, before calling 109 // "Autonomous_Init()" 110 autonomousInit(); 111 m_autonomousInitialized = true; 112 m_testInitialized = false; 113 m_teleopInitialized = false; 114 m_disabledInitialized = false; 115 } 116 HAL.observeUserProgramAutonomous(); 117 autonomousPeriodic(); 118 } else { 119 // call Teleop_Init() if this is the first time 120 // we've entered teleop_mode 121 if (!m_teleopInitialized) { 122 LiveWindow.setEnabled(false); 123 teleopInit(); 124 m_teleopInitialized = true; 125 m_testInitialized = false; 126 m_autonomousInitialized = false; 127 m_disabledInitialized = false; 128 } 129 HAL.observeUserProgramTeleop(); 130 teleopPeriodic(); 131 } 132 robotPeriodic(); 133 } 134 } 135 136 /* ----------- Overridable initialization code ----------------- */ 137 138 /** 139 * Robot-wide initialization code should go here. 140 * 141 * <p>Users should override this method for default Robot-wide initialization which will be called 142 * when the robot is first powered on. It will be called exactly one time. 143 * 144 * <p>Warning: the Driver Station "Robot Code" light and FMS "Robot Ready" indicators will be off 145 * until RobotInit() exits. Code in RobotInit() that waits for enable will cause the robot to 146 * never indicate that the code is ready, causing the robot to be bypassed in a match. 147 */ 148 public void robotInit() { 149 System.out.println("Default IterativeRobot.robotInit() method... Overload me!"); 150 } 151 152 /** 153 * Initialization code for disabled mode should go here. 154 * 155 * <p>Users should override this method for initialization code which will be called each time the 156 * robot enters disabled mode. 157 */ 158 public void disabledInit() { 159 System.out.println("Default IterativeRobot.disabledInit() method... Overload me!"); 160 } 161 162 /** 163 * Initialization code for autonomous mode should go here. 164 * 165 * <p>Users should override this method for initialization code which will be called each time the 166 * robot enters autonomous mode. 167 */ 168 public void autonomousInit() { 169 System.out.println("Default IterativeRobot.autonomousInit() method... Overload me!"); 170 } 171 172 /** 173 * Initialization code for teleop mode should go here. 174 * 175 * <p>Users should override this method for initialization code which will be called each time the 176 * robot enters teleop mode. 177 */ 178 public void teleopInit() { 179 System.out.println("Default IterativeRobot.teleopInit() method... Overload me!"); 180 } 181 182 /** 183 * Initialization code for test mode should go here. 184 * 185 * <p>Users should override this method for initialization code which will be called each time the 186 * robot enters test mode. 187 */ 188 @SuppressWarnings("PMD.JUnit4TestShouldUseTestAnnotation") 189 public void testInit() { 190 System.out.println("Default IterativeRobot.testInit() method... Overload me!"); 191 } 192 193 /* ----------- Overridable periodic code ----------------- */ 194 195 private boolean m_rpFirstRun = true; 196 197 /** 198 * Periodic code for all robot modes should go here. 199 * 200 * <p>This function is called each time a new packet is received from the driver station. 201 * 202 * <p>Packets are received approximately every 20ms. Fixed loop timing is not guaranteed due to 203 * network timing variability and the function may not be called at all if the Driver Station is 204 * disconnected. For most use cases the variable timing will not be an issue. If your code does 205 * require guaranteed fixed periodic timing, consider using Notifier or PIDController instead. 206 */ 207 public void robotPeriodic() { 208 if (m_rpFirstRun) { 209 System.out.println("Default IterativeRobot.robotPeriodic() method... Overload me!"); 210 m_rpFirstRun = false; 211 } 212 } 213 214 private boolean m_dpFirstRun = true; 215 216 /** 217 * Periodic code for disabled mode should go here. 218 * 219 * <p>Users should override this method for code which will be called each time a new packet is 220 * received from the driver station and the robot is in disabled mode. 221 * 222 * <p>Packets are received approximately every 20ms. Fixed loop timing is not guaranteed due to 223 * network timing variability and the function may not be called at all if the Driver Station is 224 * disconnected. For most use cases the variable timing will not be an issue. If your code does 225 * require guaranteed fixed periodic timing, consider using Notifier or PIDController instead. 226 */ 227 public void disabledPeriodic() { 228 if (m_dpFirstRun) { 229 System.out.println("Default IterativeRobot.disabledPeriodic() method... Overload me!"); 230 m_dpFirstRun = false; 231 } 232 } 233 234 private boolean m_apFirstRun = true; 235 236 /** 237 * Periodic code for autonomous mode should go here. 238 * 239 * <p>Users should override this method for code which will be called each time a new packet is 240 * received from the driver station and the robot is in autonomous mode. 241 * 242 * <p>Packets are received approximately every 20ms. Fixed loop timing is not guaranteed due to 243 * network timing variability and the function may not be called at all if the Driver Station is 244 * disconnected. For most use cases the variable timing will not be an issue. If your code does 245 * require guaranteed fixed periodic timing, consider using Notifier or PIDController instead. 246 */ 247 public void autonomousPeriodic() { 248 if (m_apFirstRun) { 249 System.out.println("Default IterativeRobot.autonomousPeriodic() method... Overload me!"); 250 m_apFirstRun = false; 251 } 252 } 253 254 private boolean m_tpFirstRun = true; 255 256 /** 257 * Periodic code for teleop mode should go here. 258 * 259 * <p>Users should override this method for code which will be called each time a new packet is 260 * received from the driver station and the robot is in teleop mode. 261 * 262 * <p>Packets are received approximately every 20ms. Fixed loop timing is not guaranteed due to 263 * network timing variability and the function may not be called at all if the Driver Station is 264 * disconnected. For most use cases the variable timing will not be an issue. If your code does 265 * require guaranteed fixed periodic timing, consider using Notifier or PIDController instead. 266 */ 267 public void teleopPeriodic() { 268 if (m_tpFirstRun) { 269 System.out.println("Default IterativeRobot.teleopPeriodic() method... Overload me!"); 270 m_tpFirstRun = false; 271 } 272 } 273 274 private boolean m_tmpFirstRun = true; 275 276 /** 277 * Periodic code for test mode should go here. 278 * 279 * <p>Users should override this method for code which will be called each time a new packet is 280 * received from the driver station and the robot is in test mode. 281 * 282 * <p>Packets are received approximately every 20ms. Fixed loop timing is not guaranteed due to 283 * network timing variability and the function may not be called at all if the Driver Station is 284 * disconnected. For most use cases the variable timing will not be an issue. If your code does 285 * require guaranteed fixed periodic timing, consider using Notifier or PIDController instead. 286 */ 287 @SuppressWarnings("PMD.JUnit4TestShouldUseTestAnnotation") 288 public void testPeriodic() { 289 if (m_tmpFirstRun) { 290 System.out.println("Default IterativeRobot.testPeriodic() method... Overload me!"); 291 m_tmpFirstRun = false; 292 } 293 } 294}