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/*----------------------------------------------------------------------------*/
007package edu.wpi.first.wpilibj;
008
009import edu.wpi.first.wpilibj.communication.FRCNetworkCommunicationsLibrary;
010import edu.wpi.first.wpilibj.communication.FRCNetworkCommunicationsLibrary.tInstances;
011import edu.wpi.first.wpilibj.communication.FRCNetworkCommunicationsLibrary.tResourceType;
012import edu.wpi.first.wpilibj.communication.UsageReporting;
013import edu.wpi.first.wpilibj.Timer;
014import edu.wpi.first.wpilibj.livewindow.LiveWindow;
015
016/**
017 * IterativeRobot implements a specific type of Robot Program framework, extending the RobotBase class.
018 *
019 * The IterativeRobot class is intended to be subclassed by a user creating a robot program.
020 *
021 * This class is intended to implement the "old style" default code, by providing
022 * the following functions which are called by the main loop, startCompetition(), at the appropriate times:
023 *
024 * robotInit() -- provide for initialization at robot power-on
025 *
026 * init() functions -- each of the following functions is called once when the
027 *                     appropriate mode is entered:
028 *  - DisabledInit()   -- called only when first disabled
029 *  - AutonomousInit() -- called each and every time autonomous is entered from another mode
030 *  - TeleopInit()     -- called each and every time teleop is entered from another mode
031 *  - TestInit()       -- called each and every time test mode is entered from anothermode
032 *
033 * Periodic() functions -- each of these functions is called iteratively at the
034 *                         appropriate periodic rate (aka the "slow loop").  The period of
035 *                         the iterative robot is synced to the driver station control packets,
036 *                         giving a periodic frequency of about 50Hz (50 times per second).
037 *   - disabledPeriodic()
038 *   - autonomousPeriodic()
039 *   - teleopPeriodic()
040 *   - testPeriodoc()
041 *
042 */
043public class IterativeRobot extends RobotBase {
044    private boolean m_disabledInitialized;
045    private boolean m_autonomousInitialized;
046    private boolean m_teleopInitialized;
047    private boolean m_testInitialized;
048
049    /**
050     * Constructor for RobotIterativeBase
051     *
052     * The constructor initializes the instance variables for the robot to indicate
053     * the status of initialization for disabled, autonomous, and teleop code.
054     */
055    public IterativeRobot() {
056        // set status for initialization of disabled, autonomous, and teleop code.
057        m_disabledInitialized = false;
058        m_autonomousInitialized = false;
059        m_teleopInitialized = false;
060        m_testInitialized = false;
061    }
062    
063    @Override
064    protected void prestart() {
065        // Don't immediately say that the robot's ready to be enabled.
066        // See below.
067    }
068
069    /**
070     * Provide an alternate "main loop" via startCompetition().
071     *
072     */
073    public void startCompetition() {
074        UsageReporting.report(tResourceType.kResourceType_Framework, tInstances.kFramework_Iterative);
075
076        robotInit();
077        
078        // We call this now (not in prestart like default) so that the robot
079        // won't enable until the initialization has finished. This is useful
080        // because otherwise it's sometimes possible to enable the robot
081        // before the code is ready. 
082        FRCNetworkCommunicationsLibrary.FRCNetworkCommunicationObserveUserProgramStarting();
083
084        // loop forever, calling the appropriate mode-dependent function
085        LiveWindow.setEnabled(false);
086        while (true) {
087            // Call the appropriate function depending upon the current robot mode
088            if (isDisabled()) {
089                // call DisabledInit() if we are now just entering disabled mode from
090                // either a different mode or from power-on
091                if (!m_disabledInitialized) {
092                    LiveWindow.setEnabled(false);
093                    disabledInit();
094                    m_disabledInitialized = true;
095                    // reset the initialization flags for the other modes
096                    m_autonomousInitialized = false;
097                    m_teleopInitialized = false;
098                    m_testInitialized = false;
099                }
100                if (nextPeriodReady()) {
101                        FRCNetworkCommunicationsLibrary.FRCNetworkCommunicationObserveUserProgramDisabled();
102                    disabledPeriodic();
103                }
104            } else if (isTest()) {
105                // call TestInit() if we are now just entering test mode from either
106                // a different mode or from power-on
107                if (!m_testInitialized) {
108                    LiveWindow.setEnabled(true);
109                    testInit();
110                    m_testInitialized = true;
111                    m_autonomousInitialized = false;
112                    m_teleopInitialized = false;
113                    m_disabledInitialized = false;
114                }
115                if (nextPeriodReady()) {
116                        FRCNetworkCommunicationsLibrary.FRCNetworkCommunicationObserveUserProgramTest();
117                    testPeriodic();
118                }
119            } else if (isAutonomous()) {
120                // call Autonomous_Init() if this is the first time
121                // we've entered autonomous_mode
122                if (!m_autonomousInitialized) {
123                    LiveWindow.setEnabled(false);
124                    // KBS NOTE: old code reset all PWMs and relays to "safe values"
125                    // whenever entering autonomous mode, before calling
126                    // "Autonomous_Init()"
127                    autonomousInit();
128                    m_autonomousInitialized = true;
129                    m_testInitialized = false;
130                    m_teleopInitialized = false;
131                    m_disabledInitialized = false;
132                }
133                if (nextPeriodReady()) {
134                    FRCNetworkCommunicationsLibrary.FRCNetworkCommunicationObserveUserProgramAutonomous();
135                    autonomousPeriodic();
136                }
137            } else {
138                // call Teleop_Init() if this is the first time
139                // we've entered teleop_mode
140                if (!m_teleopInitialized) {
141                    LiveWindow.setEnabled(false);
142                    teleopInit();
143                    m_teleopInitialized = true;
144                    m_testInitialized = false;
145                    m_autonomousInitialized = false;
146                    m_disabledInitialized = false;
147                }
148                if (nextPeriodReady()) {
149                    FRCNetworkCommunicationsLibrary.FRCNetworkCommunicationObserveUserProgramTeleop();
150                    teleopPeriodic();
151                }
152            }
153            m_ds.waitForData();
154        }
155    }
156
157    /**
158     * Determine if the appropriate next periodic function should be called.
159     * Call the periodic functions whenever a packet is received from the Driver Station, or about every 20ms.
160     */
161    private boolean nextPeriodReady() {
162        return m_ds.isNewControlData();
163    }
164
165    /* ----------- Overridable initialization code -----------------*/
166
167    /**
168     * Robot-wide initialization code should go here.
169     *
170     * Users should override this method for default Robot-wide initialization which will
171     * be called when the robot is first powered on.  It will be called exactly 1 time.
172     */
173    public void robotInit() {
174        System.out.println("Default IterativeRobot.robotInit() method... Overload me!");
175    }
176
177    /**
178     * Initialization code for disabled mode should go here.
179     *
180     * Users should override this method for initialization code which will be called each time
181     * the robot enters disabled mode.
182     */
183    public void disabledInit() {
184        System.out.println("Default IterativeRobot.disabledInit() method... Overload me!");
185    }
186
187    /**
188     * Initialization code for autonomous mode should go here.
189     *
190     * Users should override this method for initialization code which will be called each time
191     * the robot enters autonomous mode.
192     */
193    public void autonomousInit() {
194        System.out.println("Default IterativeRobot.autonomousInit() method... Overload me!");
195    }
196
197    /**
198     * Initialization code for teleop mode should go here.
199     *
200     * Users should override this method for initialization code which will be called each time
201     * the robot enters teleop mode.
202     */
203    public void teleopInit() {
204        System.out.println("Default IterativeRobot.teleopInit() method... Overload me!");
205    }
206
207    /**
208     * Initialization code for test mode should go here.
209     *
210     * Users should override this method for initialization code which will be called each time
211     * the robot enters test mode.
212     */
213    public void testInit() {
214        System.out.println("Default IterativeRobot.testInit() method... Overload me!");
215    }
216
217    /* ----------- Overridable periodic code -----------------*/
218
219    private boolean dpFirstRun = true;
220    /**
221     * Periodic code for disabled mode should go here.
222     *
223     * Users should override this method for code which will be called periodically at a regular
224     * rate while the robot is in disabled mode.
225     */
226    public void disabledPeriodic() {
227        if (dpFirstRun) {
228            System.out.println("Default IterativeRobot.disabledPeriodic() method... Overload me!");
229            dpFirstRun = false;
230        }
231        Timer.delay(0.001);
232    }
233
234    private boolean apFirstRun = true;
235
236    /**
237     * Periodic code for autonomous mode should go here.
238     *
239     * Users should override this method for code which will be called periodically at a regular
240     * rate while the robot is in autonomous mode.
241     */
242    public void autonomousPeriodic() {
243        if (apFirstRun) {
244            System.out.println("Default IterativeRobot.autonomousPeriodic() method... Overload me!");
245            apFirstRun = false;
246        }
247        Timer.delay(0.001);
248    }
249
250    private boolean tpFirstRun = true;
251
252    /**
253     * Periodic code for teleop mode should go here.
254     *
255     * Users should override this method for code which will be called periodically at a regular
256     * rate while the robot is in teleop mode.
257     */
258    public void teleopPeriodic() {
259        if (tpFirstRun) {
260            System.out.println("Default IterativeRobot.teleopPeriodic() method... Overload me!");
261            tpFirstRun = false;
262        }
263        Timer.delay(0.001);
264    }
265
266    private boolean tmpFirstRun = true;
267
268    /**
269     * Periodic code for test mode should go here
270     *
271     * Users should override this method for code which will be called periodically at a regular rate
272     * while the robot is in test mode.
273     */
274    public void testPeriodic() {
275        if (tmpFirstRun) {
276            System.out.println("Default IterativeRobot.testPeriodic() method... Overload me!");
277            tmpFirstRun = false;
278        }
279    }
280}