blob: ee941b61cc0c96589da46398fd5f3938c58b7a2c [file] [log] [blame]
Austin Schuh812d0d12021-11-04 20:16:48 -07001// Copyright (c) FIRST and other WPILib contributors.
2// Open Source Software; you can modify and/or share it under the terms of
3// the WPILib BSD license file in the root directory of this project.
Brian Silverman8fce7482020-01-05 13:18:21 -08004
5#include "frc/IterativeRobotBase.h"
6
James Kuszmaulcf324122023-01-14 14:07:17 -08007#include <frc/DriverStation.h>
8
Austin Schuh812d0d12021-11-04 20:16:48 -07009#include <fmt/format.h>
Brian Silverman8fce7482020-01-05 13:18:21 -080010#include <hal/DriverStation.h>
Austin Schuh812d0d12021-11-04 20:16:48 -070011#include <networktables/NetworkTableInstance.h>
Brian Silverman8fce7482020-01-05 13:18:21 -080012
Austin Schuh812d0d12021-11-04 20:16:48 -070013#include "frc/DSControlWord.h"
14#include "frc/Errors.h"
Brian Silverman8fce7482020-01-05 13:18:21 -080015#include "frc/livewindow/LiveWindow.h"
16#include "frc/shuffleboard/Shuffleboard.h"
17#include "frc/smartdashboard/SmartDashboard.h"
18
19using namespace frc;
20
Brian Silverman8fce7482020-01-05 13:18:21 -080021IterativeRobotBase::IterativeRobotBase(units::second_t period)
22 : m_period(period),
23 m_watchdog(period, [this] { PrintLoopOverrunMessage(); }) {}
24
Austin Schuh812d0d12021-11-04 20:16:48 -070025void IterativeRobotBase::RobotInit() {}
Brian Silverman8fce7482020-01-05 13:18:21 -080026
James Kuszmaulb13e13f2023-11-22 20:44:04 -080027void IterativeRobotBase::DriverStationConnected() {}
28
Austin Schuh812d0d12021-11-04 20:16:48 -070029void IterativeRobotBase::SimulationInit() {}
Austin Schuh1e69f942020-11-14 15:06:14 -080030
Austin Schuh812d0d12021-11-04 20:16:48 -070031void IterativeRobotBase::DisabledInit() {}
Brian Silverman8fce7482020-01-05 13:18:21 -080032
Austin Schuh812d0d12021-11-04 20:16:48 -070033void IterativeRobotBase::AutonomousInit() {}
Brian Silverman8fce7482020-01-05 13:18:21 -080034
Austin Schuh812d0d12021-11-04 20:16:48 -070035void IterativeRobotBase::TeleopInit() {}
Brian Silverman8fce7482020-01-05 13:18:21 -080036
Austin Schuh812d0d12021-11-04 20:16:48 -070037void IterativeRobotBase::TestInit() {}
Brian Silverman8fce7482020-01-05 13:18:21 -080038
39void IterativeRobotBase::RobotPeriodic() {
40 static bool firstRun = true;
41 if (firstRun) {
Austin Schuh812d0d12021-11-04 20:16:48 -070042 fmt::print("Default {}() method... Override me!\n", __FUNCTION__);
Brian Silverman8fce7482020-01-05 13:18:21 -080043 firstRun = false;
44 }
45}
46
Austin Schuh1e69f942020-11-14 15:06:14 -080047void IterativeRobotBase::SimulationPeriodic() {
48 static bool firstRun = true;
49 if (firstRun) {
Austin Schuh812d0d12021-11-04 20:16:48 -070050 fmt::print("Default {}() method... Override me!\n", __FUNCTION__);
Austin Schuh1e69f942020-11-14 15:06:14 -080051 firstRun = false;
52 }
53}
54
Brian Silverman8fce7482020-01-05 13:18:21 -080055void IterativeRobotBase::DisabledPeriodic() {
56 static bool firstRun = true;
57 if (firstRun) {
Austin Schuh812d0d12021-11-04 20:16:48 -070058 fmt::print("Default {}() method... Override me!\n", __FUNCTION__);
Brian Silverman8fce7482020-01-05 13:18:21 -080059 firstRun = false;
60 }
61}
62
63void IterativeRobotBase::AutonomousPeriodic() {
64 static bool firstRun = true;
65 if (firstRun) {
Austin Schuh812d0d12021-11-04 20:16:48 -070066 fmt::print("Default {}() method... Override me!\n", __FUNCTION__);
Brian Silverman8fce7482020-01-05 13:18:21 -080067 firstRun = false;
68 }
69}
70
71void IterativeRobotBase::TeleopPeriodic() {
72 static bool firstRun = true;
73 if (firstRun) {
Austin Schuh812d0d12021-11-04 20:16:48 -070074 fmt::print("Default {}() method... Override me!\n", __FUNCTION__);
Brian Silverman8fce7482020-01-05 13:18:21 -080075 firstRun = false;
76 }
77}
78
79void IterativeRobotBase::TestPeriodic() {
80 static bool firstRun = true;
81 if (firstRun) {
Austin Schuh812d0d12021-11-04 20:16:48 -070082 fmt::print("Default {}() method... Override me!\n", __FUNCTION__);
Brian Silverman8fce7482020-01-05 13:18:21 -080083 firstRun = false;
84 }
85}
86
Austin Schuh812d0d12021-11-04 20:16:48 -070087void IterativeRobotBase::DisabledExit() {}
88
89void IterativeRobotBase::AutonomousExit() {}
90
91void IterativeRobotBase::TeleopExit() {}
92
93void IterativeRobotBase::TestExit() {}
94
95void IterativeRobotBase::SetNetworkTablesFlushEnabled(bool enabled) {
96 m_ntFlushEnabled = enabled;
97}
98
James Kuszmaulcf324122023-01-14 14:07:17 -080099void IterativeRobotBase::EnableLiveWindowInTest(bool testLW) {
James Kuszmaulb13e13f2023-11-22 20:44:04 -0800100 if (IsTestEnabled()) {
James Kuszmaulcf324122023-01-14 14:07:17 -0800101 throw FRC_MakeError(err::IncompatibleMode,
102 "Can't configure test mode while in test mode!");
103 }
104 m_lwEnabledInTest = testLW;
105}
106
107bool IterativeRobotBase::IsLiveWindowEnabledInTest() {
108 return m_lwEnabledInTest;
109}
110
Austin Schuh812d0d12021-11-04 20:16:48 -0700111units::second_t IterativeRobotBase::GetPeriod() const {
112 return m_period;
113}
114
Brian Silverman8fce7482020-01-05 13:18:21 -0800115void IterativeRobotBase::LoopFunc() {
James Kuszmaulcf324122023-01-14 14:07:17 -0800116 DriverStation::RefreshData();
Brian Silverman8fce7482020-01-05 13:18:21 -0800117 m_watchdog.Reset();
118
Austin Schuh812d0d12021-11-04 20:16:48 -0700119 // Get current mode
120 DSControlWord word;
121 Mode mode = Mode::kNone;
122 if (word.IsDisabled()) {
123 mode = Mode::kDisabled;
124 } else if (word.IsAutonomous()) {
125 mode = Mode::kAutonomous;
126 } else if (word.IsTeleop()) {
127 mode = Mode::kTeleop;
128 } else if (word.IsTest()) {
129 mode = Mode::kTest;
130 }
131
James Kuszmaulb13e13f2023-11-22 20:44:04 -0800132 if (!m_calledDsConnected && word.IsDSAttached()) {
133 m_calledDsConnected = true;
134 DriverStationConnected();
135 }
136
Austin Schuh812d0d12021-11-04 20:16:48 -0700137 // If mode changed, call mode exit and entry functions
138 if (m_lastMode != mode) {
139 // Call last mode's exit function
140 if (m_lastMode == Mode::kDisabled) {
141 DisabledExit();
142 } else if (m_lastMode == Mode::kAutonomous) {
143 AutonomousExit();
144 } else if (m_lastMode == Mode::kTeleop) {
145 TeleopExit();
146 } else if (m_lastMode == Mode::kTest) {
James Kuszmaulcf324122023-01-14 14:07:17 -0800147 if (m_lwEnabledInTest) {
148 LiveWindow::SetEnabled(false);
149 Shuffleboard::DisableActuatorWidgets();
150 }
Austin Schuh812d0d12021-11-04 20:16:48 -0700151 TestExit();
152 }
153
154 // Call current mode's entry function
155 if (mode == Mode::kDisabled) {
Brian Silverman8fce7482020-01-05 13:18:21 -0800156 DisabledInit();
157 m_watchdog.AddEpoch("DisabledInit()");
Austin Schuh812d0d12021-11-04 20:16:48 -0700158 } else if (mode == Mode::kAutonomous) {
Brian Silverman8fce7482020-01-05 13:18:21 -0800159 AutonomousInit();
160 m_watchdog.AddEpoch("AutonomousInit()");
Austin Schuh812d0d12021-11-04 20:16:48 -0700161 } else if (mode == Mode::kTeleop) {
Brian Silverman8fce7482020-01-05 13:18:21 -0800162 TeleopInit();
163 m_watchdog.AddEpoch("TeleopInit()");
Austin Schuh812d0d12021-11-04 20:16:48 -0700164 } else if (mode == Mode::kTest) {
James Kuszmaulcf324122023-01-14 14:07:17 -0800165 if (m_lwEnabledInTest) {
166 LiveWindow::SetEnabled(true);
167 Shuffleboard::EnableActuatorWidgets();
168 }
Brian Silverman8fce7482020-01-05 13:18:21 -0800169 TestInit();
170 m_watchdog.AddEpoch("TestInit()");
Brian Silverman8fce7482020-01-05 13:18:21 -0800171 }
172
Austin Schuh812d0d12021-11-04 20:16:48 -0700173 m_lastMode = mode;
174 }
175
176 // Call the appropriate function depending upon the current robot mode
177 if (mode == Mode::kDisabled) {
178 HAL_ObserveUserProgramDisabled();
179 DisabledPeriodic();
180 m_watchdog.AddEpoch("DisabledPeriodic()");
181 } else if (mode == Mode::kAutonomous) {
182 HAL_ObserveUserProgramAutonomous();
183 AutonomousPeriodic();
184 m_watchdog.AddEpoch("AutonomousPeriodic()");
185 } else if (mode == Mode::kTeleop) {
186 HAL_ObserveUserProgramTeleop();
187 TeleopPeriodic();
188 m_watchdog.AddEpoch("TeleopPeriodic()");
189 } else if (mode == Mode::kTest) {
Brian Silverman8fce7482020-01-05 13:18:21 -0800190 HAL_ObserveUserProgramTest();
191 TestPeriodic();
192 m_watchdog.AddEpoch("TestPeriodic()");
193 }
194
195 RobotPeriodic();
196 m_watchdog.AddEpoch("RobotPeriodic()");
197
198 SmartDashboard::UpdateValues();
199 m_watchdog.AddEpoch("SmartDashboard::UpdateValues()");
Austin Schuh812d0d12021-11-04 20:16:48 -0700200 LiveWindow::UpdateValues();
Brian Silverman8fce7482020-01-05 13:18:21 -0800201 m_watchdog.AddEpoch("LiveWindow::UpdateValues()");
202 Shuffleboard::Update();
203 m_watchdog.AddEpoch("Shuffleboard::Update()");
Austin Schuh1e69f942020-11-14 15:06:14 -0800204
205 if constexpr (IsSimulation()) {
Austin Schuh812d0d12021-11-04 20:16:48 -0700206 HAL_SimPeriodicBefore();
Austin Schuh1e69f942020-11-14 15:06:14 -0800207 SimulationPeriodic();
Austin Schuh812d0d12021-11-04 20:16:48 -0700208 HAL_SimPeriodicAfter();
Austin Schuh1e69f942020-11-14 15:06:14 -0800209 m_watchdog.AddEpoch("SimulationPeriodic()");
210 }
211
Brian Silverman8fce7482020-01-05 13:18:21 -0800212 m_watchdog.Disable();
213
Austin Schuh812d0d12021-11-04 20:16:48 -0700214 // Flush NetworkTables
215 if (m_ntFlushEnabled) {
James Kuszmaulcf324122023-01-14 14:07:17 -0800216 nt::NetworkTableInstance::GetDefault().FlushLocal();
Austin Schuh812d0d12021-11-04 20:16:48 -0700217 }
218
Brian Silverman8fce7482020-01-05 13:18:21 -0800219 // Warn on loop time overruns
220 if (m_watchdog.IsExpired()) {
221 m_watchdog.PrintEpochs();
222 }
223}
224
225void IterativeRobotBase::PrintLoopOverrunMessage() {
Austin Schuh812d0d12021-11-04 20:16:48 -0700226 FRC_ReportError(err::Error, "Loop time of {:.6f}s overrun", m_period.value());
Brian Silverman8fce7482020-01-05 13:18:21 -0800227}