Files
allwpilib/wpilibj/src/main/java/edu/wpi/first/wpilibj/IterativeRobotBase.java

359 lines
11 KiB
Java
Raw Normal View History

// Copyright (c) FIRST and other WPILib contributors.
// Open Source Software; you can modify and/or share it under the terms of
// the WPILib BSD license file in the root directory of this project.
2017-07-08 10:50:56 -04:00
package edu.wpi.first.wpilibj;
import edu.wpi.first.hal.HAL;
import edu.wpi.first.networktables.NetworkTableInstance;
2017-07-08 10:50:56 -04:00
import edu.wpi.first.wpilibj.livewindow.LiveWindow;
import edu.wpi.first.wpilibj.shuffleboard.Shuffleboard;
import edu.wpi.first.wpilibj.smartdashboard.SmartDashboard;
2017-07-08 10:50:56 -04:00
/**
* IterativeRobotBase implements a specific type of robot program framework, extending the RobotBase
* class.
*
* <p>The IterativeRobotBase class does not implement startCompetition(), so it should not be used
* by teams directly.
*
* <p>This class provides the following functions which are called by the main loop,
* startCompetition(), at the appropriate times:
*
* <p>robotInit() -- provide for initialization at robot power-on
*
* <p>init() functions -- each of the following functions is called once when the appropriate mode
* is entered:
2017-07-08 10:50:56 -04:00
*
* <ul>
* <li>disabledInit() -- called each and every time disabled is entered from another mode
* <li>autonomousInit() -- called each and every time autonomous is entered from another mode
* <li>teleopInit() -- called each and every time teleop is entered from another mode
* <li>testInit() -- called each and every time test is entered from another mode
* </ul>
*
* <p>periodic() functions -- each of these functions is called on an interval:
*
* <ul>
* <li>robotPeriodic()
* <li>disabledPeriodic()
* <li>autonomousPeriodic()
* <li>teleopPeriodic()
* <li>testPeriodic()
* </ul>
*
* <p>exit() functions -- each of the following functions is called once when the appropriate mode
* is exited:
*
* <ul>
* <li>disabledExit() -- called each and every time disabled is exited
* <li>autonomousExit() -- called each and every time autonomous is exited
* <li>teleopExit() -- called each and every time teleop is exited
* <li>testExit() -- called each and every time test is exited
* </ul>
2017-07-08 10:50:56 -04:00
*/
public abstract class IterativeRobotBase extends RobotBase {
private enum Mode {
kNone,
kDisabled,
kAutonomous,
kTeleop,
kTest
}
private final DSControlWord m_word = new DSControlWord();
2017-07-08 10:50:56 -04:00
private Mode m_lastMode = Mode.kNone;
private final double m_period;
private final Watchdog m_watchdog;
2022-10-08 10:01:31 -07:00
private boolean m_ntFlushEnabled = true;
/**
* Constructor for IterativeRobotBase.
*
* @param period Period in seconds.
*/
protected IterativeRobotBase(double period) {
m_period = period;
m_watchdog = new Watchdog(period, this::printLoopOverrunMessage);
}
2017-07-08 10:50:56 -04:00
/** Provide an alternate "main loop" via startCompetition(). */
2018-06-03 10:00:53 -07:00
@Override
2017-07-08 10:50:56 -04:00
public abstract void startCompetition();
/* ----------- Overridable initialization code ----------------- */
/**
* Robot-wide initialization code should go here.
*
* <p>Users should override this method for default Robot-wide initialization which will be called
* when the robot is first powered on. It will be called exactly one time.
*
* <p>Warning: the Driver Station "Robot Code" light and FMS "Robot Ready" indicators will be off
* until RobotInit() exits. Code in RobotInit() that waits for enable will cause the robot to
* never indicate that the code is ready, causing the robot to be bypassed in a match.
*/
public void robotInit() {}
2017-07-08 10:50:56 -04:00
/**
* Robot-wide simulation initialization code should go here.
*
* <p>Users should override this method for default Robot-wide simulation related initialization
* which will be called when the robot is first started. It will be called exactly one time after
* RobotInit is called only when the robot is in simulation.
*/
public void simulationInit() {}
2017-07-08 10:50:56 -04:00
/**
* Initialization code for disabled mode should go here.
*
* <p>Users should override this method for initialization code which will be called each time the
* robot enters disabled mode.
*/
public void disabledInit() {}
2017-07-08 10:50:56 -04:00
/**
* Initialization code for autonomous mode should go here.
*
* <p>Users should override this method for initialization code which will be called each time the
* robot enters autonomous mode.
*/
public void autonomousInit() {}
2017-07-08 10:50:56 -04:00
/**
* Initialization code for teleop mode should go here.
*
* <p>Users should override this method for initialization code which will be called each time the
* robot enters teleop mode.
*/
public void teleopInit() {}
2017-07-08 10:50:56 -04:00
/**
* Initialization code for test mode should go here.
*
* <p>Users should override this method for initialization code which will be called each time the
* robot enters test mode.
*/
public void testInit() {}
2017-07-08 10:50:56 -04:00
/* ----------- Overridable periodic code ----------------- */
private boolean m_rpFirstRun = true;
/** Periodic code for all robot modes should go here. */
2017-07-08 10:50:56 -04:00
public void robotPeriodic() {
if (m_rpFirstRun) {
System.out.println("Default robotPeriodic() method... Override me!");
2017-07-08 10:50:56 -04:00
m_rpFirstRun = false;
}
}
private boolean m_spFirstRun = true;
/**
* Periodic simulation code should go here.
*
* <p>This function is called in a simulated robot after user code executes.
*/
public void simulationPeriodic() {
if (m_spFirstRun) {
System.out.println("Default simulationPeriodic() method... Override me!");
m_spFirstRun = false;
}
}
2017-07-08 10:50:56 -04:00
private boolean m_dpFirstRun = true;
/** Periodic code for disabled mode should go here. */
2017-07-08 10:50:56 -04:00
public void disabledPeriodic() {
if (m_dpFirstRun) {
System.out.println("Default disabledPeriodic() method... Override me!");
2017-07-08 10:50:56 -04:00
m_dpFirstRun = false;
}
}
private boolean m_apFirstRun = true;
/** Periodic code for autonomous mode should go here. */
2017-07-08 10:50:56 -04:00
public void autonomousPeriodic() {
if (m_apFirstRun) {
System.out.println("Default autonomousPeriodic() method... Override me!");
2017-07-08 10:50:56 -04:00
m_apFirstRun = false;
}
}
private boolean m_tpFirstRun = true;
/** Periodic code for teleop mode should go here. */
2017-07-08 10:50:56 -04:00
public void teleopPeriodic() {
if (m_tpFirstRun) {
System.out.println("Default teleopPeriodic() method... Override me!");
2017-07-08 10:50:56 -04:00
m_tpFirstRun = false;
}
}
private boolean m_tmpFirstRun = true;
/** Periodic code for test mode should go here. */
2017-07-08 10:50:56 -04:00
public void testPeriodic() {
if (m_tmpFirstRun) {
System.out.println("Default testPeriodic() method... Override me!");
2017-07-08 10:50:56 -04:00
m_tmpFirstRun = false;
}
}
/**
* Exit code for disabled mode should go here.
*
* <p>Users should override this method for code which will be called each time the robot exits
* disabled mode.
*/
public void disabledExit() {}
/**
* Exit code for autonomous mode should go here.
*
* <p>Users should override this method for code which will be called each time the robot exits
* autonomous mode.
*/
public void autonomousExit() {}
/**
* Exit code for teleop mode should go here.
*
* <p>Users should override this method for code which will be called each time the robot exits
* teleop mode.
*/
public void teleopExit() {}
/**
* Exit code for test mode should go here.
*
* <p>Users should override this method for code which will be called each time the robot exits
* test mode.
*/
public void testExit() {}
/**
2022-10-08 10:01:31 -07:00
* Enables or disables flushing NetworkTables every loop iteration. By default, this is enabled.
*
* @param enabled True to enable, false to disable
*/
public void setNetworkTablesFlushEnabled(boolean enabled) {
m_ntFlushEnabled = enabled;
}
/**
* Gets time period between calls to Periodic() functions.
*
* @return The time period between calls to Periodic() functions.
*/
public double getPeriod() {
return m_period;
}
2017-07-08 10:50:56 -04:00
protected void loopFunc() {
m_watchdog.reset();
// Get current mode
m_word.update();
Mode mode = Mode.kNone;
if (m_word.isDisabled()) {
mode = Mode.kDisabled;
} else if (m_word.isAutonomous()) {
mode = Mode.kAutonomous;
} else if (m_word.isTeleop()) {
mode = Mode.kTeleop;
} else if (m_word.isTest()) {
mode = Mode.kTest;
}
// If mode changed, call mode exit and entry functions
if (m_lastMode != mode) {
// Call last mode's exit function
if (m_lastMode == Mode.kDisabled) {
disabledExit();
} else if (m_lastMode == Mode.kAutonomous) {
autonomousExit();
} else if (m_lastMode == Mode.kTeleop) {
teleopExit();
} else if (m_lastMode == Mode.kTest) {
2017-07-08 10:50:56 -04:00
LiveWindow.setEnabled(false);
Shuffleboard.disableActuatorWidgets();
testExit();
2017-07-08 10:50:56 -04:00
}
// Call current mode's entry function
if (mode == Mode.kDisabled) {
disabledInit();
m_watchdog.addEpoch("disabledInit()");
} else if (mode == Mode.kAutonomous) {
2017-07-08 10:50:56 -04:00
autonomousInit();
m_watchdog.addEpoch("autonomousInit()");
} else if (mode == Mode.kTeleop) {
teleopInit();
m_watchdog.addEpoch("teleopInit()");
} else if (mode == Mode.kTest) {
LiveWindow.setEnabled(true);
Shuffleboard.enableActuatorWidgets();
testInit();
m_watchdog.addEpoch("testInit()");
2017-07-08 10:50:56 -04:00
}
m_lastMode = mode;
}
// Call the appropriate function depending upon the current robot mode
if (mode == Mode.kDisabled) {
HAL.observeUserProgramDisabled();
disabledPeriodic();
m_watchdog.addEpoch("disabledPeriodic()");
} else if (mode == Mode.kAutonomous) {
2017-07-08 10:50:56 -04:00
HAL.observeUserProgramAutonomous();
autonomousPeriodic();
m_watchdog.addEpoch("autonomousPeriodic()");
} else if (mode == Mode.kTeleop) {
2017-07-08 10:50:56 -04:00
HAL.observeUserProgramTeleop();
teleopPeriodic();
m_watchdog.addEpoch("teleopPeriodic()");
2017-07-08 10:50:56 -04:00
} else {
HAL.observeUserProgramTest();
testPeriodic();
m_watchdog.addEpoch("testPeriodic()");
2017-07-08 10:50:56 -04:00
}
2017-07-08 10:50:56 -04:00
robotPeriodic();
m_watchdog.addEpoch("robotPeriodic()");
SmartDashboard.updateValues();
m_watchdog.addEpoch("SmartDashboard.updateValues()");
LiveWindow.updateValues();
m_watchdog.addEpoch("LiveWindow.updateValues()");
Shuffleboard.update();
m_watchdog.addEpoch("Shuffleboard.update()");
if (isSimulation()) {
HAL.simPeriodicBefore();
simulationPeriodic();
HAL.simPeriodicAfter();
m_watchdog.addEpoch("simulationPeriodic()");
}
m_watchdog.disable();
// Flush NetworkTables
if (m_ntFlushEnabled) {
2022-10-08 10:01:31 -07:00
NetworkTableInstance.getDefault().flushLocal();
}
// Warn on loop time overruns
if (m_watchdog.isExpired()) {
m_watchdog.printEpochs();
}
}
private void printLoopOverrunMessage() {
DriverStation.reportWarning("Loop time of " + m_period + "s overrun\n", false);
2017-07-08 10:50:56 -04:00
}
}