| /*----------------------------------------------------------------------------*/ |
| /* Copyright (c) 2017-2019 FIRST. All Rights Reserved. */ |
| /* Open Source Software - may be modified and shared by FRC teams. The code */ |
| /* must be accompanied by the FIRST BSD license file in the root directory of */ |
| /* the project. */ |
| /*----------------------------------------------------------------------------*/ |
| |
| #include "frc/IterativeRobotBase.h" |
| |
| #include <cstdio> |
| |
| #include <hal/HAL.h> |
| #include <wpi/Format.h> |
| #include <wpi/SmallString.h> |
| #include <wpi/raw_ostream.h> |
| |
| #include "frc/DriverStation.h" |
| #include "frc/Timer.h" |
| #include "frc/commands/Scheduler.h" |
| #include "frc/livewindow/LiveWindow.h" |
| #include "frc/shuffleboard/Shuffleboard.h" |
| #include "frc/smartdashboard/SmartDashboard.h" |
| |
| using namespace frc; |
| |
| IterativeRobotBase::IterativeRobotBase(double period) |
| : IterativeRobotBase(units::second_t(period)) {} |
| |
| IterativeRobotBase::IterativeRobotBase(units::second_t period) |
| : m_period(period), |
| m_watchdog(period, [this] { PrintLoopOverrunMessage(); }) {} |
| |
| void IterativeRobotBase::RobotInit() { |
| wpi::outs() << "Default " << __FUNCTION__ << "() method... Override me!\n"; |
| } |
| |
| void IterativeRobotBase::DisabledInit() { |
| wpi::outs() << "Default " << __FUNCTION__ << "() method... Override me!\n"; |
| } |
| |
| void IterativeRobotBase::AutonomousInit() { |
| wpi::outs() << "Default " << __FUNCTION__ << "() method... Override me!\n"; |
| } |
| |
| void IterativeRobotBase::TeleopInit() { |
| wpi::outs() << "Default " << __FUNCTION__ << "() method... Override me!\n"; |
| } |
| |
| void IterativeRobotBase::TestInit() { |
| wpi::outs() << "Default " << __FUNCTION__ << "() method... Override me!\n"; |
| } |
| |
| void IterativeRobotBase::RobotPeriodic() { |
| static bool firstRun = true; |
| if (firstRun) { |
| wpi::outs() << "Default " << __FUNCTION__ << "() method... Override me!\n"; |
| firstRun = false; |
| } |
| } |
| |
| void IterativeRobotBase::DisabledPeriodic() { |
| static bool firstRun = true; |
| if (firstRun) { |
| wpi::outs() << "Default " << __FUNCTION__ << "() method... Override me!\n"; |
| firstRun = false; |
| } |
| } |
| |
| void IterativeRobotBase::AutonomousPeriodic() { |
| static bool firstRun = true; |
| if (firstRun) { |
| wpi::outs() << "Default " << __FUNCTION__ << "() method... Override me!\n"; |
| firstRun = false; |
| } |
| } |
| |
| void IterativeRobotBase::TeleopPeriodic() { |
| static bool firstRun = true; |
| if (firstRun) { |
| wpi::outs() << "Default " << __FUNCTION__ << "() method... Override me!\n"; |
| firstRun = false; |
| } |
| } |
| |
| void IterativeRobotBase::TestPeriodic() { |
| static bool firstRun = true; |
| if (firstRun) { |
| wpi::outs() << "Default " << __FUNCTION__ << "() method... Override me!\n"; |
| firstRun = false; |
| } |
| } |
| |
| void IterativeRobotBase::LoopFunc() { |
| m_watchdog.Reset(); |
| |
| // Call the appropriate function depending upon the current robot mode |
| if (IsDisabled()) { |
| // Call DisabledInit() if we are now just entering disabled mode from |
| // either a different mode or from power-on. |
| if (m_lastMode != Mode::kDisabled) { |
| LiveWindow::GetInstance()->SetEnabled(false); |
| Shuffleboard::DisableActuatorWidgets(); |
| DisabledInit(); |
| m_watchdog.AddEpoch("DisabledInit()"); |
| m_lastMode = Mode::kDisabled; |
| } |
| |
| HAL_ObserveUserProgramDisabled(); |
| DisabledPeriodic(); |
| m_watchdog.AddEpoch("DisabledPeriodic()"); |
| } else if (IsAutonomous()) { |
| // Call AutonomousInit() if we are now just entering autonomous mode from |
| // either a different mode or from power-on. |
| if (m_lastMode != Mode::kAutonomous) { |
| LiveWindow::GetInstance()->SetEnabled(false); |
| Shuffleboard::DisableActuatorWidgets(); |
| AutonomousInit(); |
| m_watchdog.AddEpoch("AutonomousInit()"); |
| m_lastMode = Mode::kAutonomous; |
| } |
| |
| HAL_ObserveUserProgramAutonomous(); |
| AutonomousPeriodic(); |
| m_watchdog.AddEpoch("AutonomousPeriodic()"); |
| } else if (IsOperatorControl()) { |
| // Call TeleopInit() if we are now just entering teleop mode from |
| // either a different mode or from power-on. |
| if (m_lastMode != Mode::kTeleop) { |
| LiveWindow::GetInstance()->SetEnabled(false); |
| Shuffleboard::DisableActuatorWidgets(); |
| TeleopInit(); |
| m_watchdog.AddEpoch("TeleopInit()"); |
| m_lastMode = Mode::kTeleop; |
| Scheduler::GetInstance()->SetEnabled(true); |
| } |
| |
| HAL_ObserveUserProgramTeleop(); |
| TeleopPeriodic(); |
| m_watchdog.AddEpoch("TeleopPeriodic()"); |
| } else { |
| // Call TestInit() if we are now just entering test mode from |
| // either a different mode or from power-on. |
| if (m_lastMode != Mode::kTest) { |
| LiveWindow::GetInstance()->SetEnabled(true); |
| Shuffleboard::EnableActuatorWidgets(); |
| TestInit(); |
| m_watchdog.AddEpoch("TestInit()"); |
| m_lastMode = Mode::kTest; |
| } |
| |
| HAL_ObserveUserProgramTest(); |
| TestPeriodic(); |
| m_watchdog.AddEpoch("TestPeriodic()"); |
| } |
| |
| RobotPeriodic(); |
| m_watchdog.AddEpoch("RobotPeriodic()"); |
| |
| SmartDashboard::UpdateValues(); |
| m_watchdog.AddEpoch("SmartDashboard::UpdateValues()"); |
| LiveWindow::GetInstance()->UpdateValues(); |
| m_watchdog.AddEpoch("LiveWindow::UpdateValues()"); |
| Shuffleboard::Update(); |
| m_watchdog.AddEpoch("Shuffleboard::Update()"); |
| m_watchdog.Disable(); |
| |
| // Warn on loop time overruns |
| if (m_watchdog.IsExpired()) { |
| m_watchdog.PrintEpochs(); |
| } |
| } |
| |
| void IterativeRobotBase::PrintLoopOverrunMessage() { |
| wpi::SmallString<128> str; |
| wpi::raw_svector_ostream buf(str); |
| |
| buf << "Loop time of " << wpi::format("%.6f", m_period.to<double>()) |
| << "s overrun\n"; |
| |
| DriverStation::ReportWarning(str); |
| } |