blob: 0bccb0b49fb40f415778f840efe24b8c00525532 [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
Austin Schuh812d0d12021-11-04 20:16:48 -070027void IterativeRobotBase::SimulationInit() {}
Austin Schuh1e69f942020-11-14 15:06:14 -080028
Austin Schuh812d0d12021-11-04 20:16:48 -070029void IterativeRobotBase::DisabledInit() {}
Brian Silverman8fce7482020-01-05 13:18:21 -080030
Austin Schuh812d0d12021-11-04 20:16:48 -070031void IterativeRobotBase::AutonomousInit() {}
Brian Silverman8fce7482020-01-05 13:18:21 -080032
Austin Schuh812d0d12021-11-04 20:16:48 -070033void IterativeRobotBase::TeleopInit() {}
Brian Silverman8fce7482020-01-05 13:18:21 -080034
Austin Schuh812d0d12021-11-04 20:16:48 -070035void IterativeRobotBase::TestInit() {}
Brian Silverman8fce7482020-01-05 13:18:21 -080036
37void IterativeRobotBase::RobotPeriodic() {
38 static bool firstRun = true;
39 if (firstRun) {
Austin Schuh812d0d12021-11-04 20:16:48 -070040 fmt::print("Default {}() method... Override me!\n", __FUNCTION__);
Brian Silverman8fce7482020-01-05 13:18:21 -080041 firstRun = false;
42 }
43}
44
Austin Schuh1e69f942020-11-14 15:06:14 -080045void IterativeRobotBase::SimulationPeriodic() {
46 static bool firstRun = true;
47 if (firstRun) {
Austin Schuh812d0d12021-11-04 20:16:48 -070048 fmt::print("Default {}() method... Override me!\n", __FUNCTION__);
Austin Schuh1e69f942020-11-14 15:06:14 -080049 firstRun = false;
50 }
51}
52
Brian Silverman8fce7482020-01-05 13:18:21 -080053void IterativeRobotBase::DisabledPeriodic() {
54 static bool firstRun = true;
55 if (firstRun) {
Austin Schuh812d0d12021-11-04 20:16:48 -070056 fmt::print("Default {}() method... Override me!\n", __FUNCTION__);
Brian Silverman8fce7482020-01-05 13:18:21 -080057 firstRun = false;
58 }
59}
60
61void IterativeRobotBase::AutonomousPeriodic() {
62 static bool firstRun = true;
63 if (firstRun) {
Austin Schuh812d0d12021-11-04 20:16:48 -070064 fmt::print("Default {}() method... Override me!\n", __FUNCTION__);
Brian Silverman8fce7482020-01-05 13:18:21 -080065 firstRun = false;
66 }
67}
68
69void IterativeRobotBase::TeleopPeriodic() {
70 static bool firstRun = true;
71 if (firstRun) {
Austin Schuh812d0d12021-11-04 20:16:48 -070072 fmt::print("Default {}() method... Override me!\n", __FUNCTION__);
Brian Silverman8fce7482020-01-05 13:18:21 -080073 firstRun = false;
74 }
75}
76
77void IterativeRobotBase::TestPeriodic() {
78 static bool firstRun = true;
79 if (firstRun) {
Austin Schuh812d0d12021-11-04 20:16:48 -070080 fmt::print("Default {}() method... Override me!\n", __FUNCTION__);
Brian Silverman8fce7482020-01-05 13:18:21 -080081 firstRun = false;
82 }
83}
84
Austin Schuh812d0d12021-11-04 20:16:48 -070085void IterativeRobotBase::DisabledExit() {}
86
87void IterativeRobotBase::AutonomousExit() {}
88
89void IterativeRobotBase::TeleopExit() {}
90
91void IterativeRobotBase::TestExit() {}
92
93void IterativeRobotBase::SetNetworkTablesFlushEnabled(bool enabled) {
94 m_ntFlushEnabled = enabled;
95}
96
James Kuszmaulcf324122023-01-14 14:07:17 -080097void IterativeRobotBase::EnableLiveWindowInTest(bool testLW) {
98 if (IsTest()) {
99 throw FRC_MakeError(err::IncompatibleMode,
100 "Can't configure test mode while in test mode!");
101 }
102 m_lwEnabledInTest = testLW;
103}
104
105bool IterativeRobotBase::IsLiveWindowEnabledInTest() {
106 return m_lwEnabledInTest;
107}
108
Austin Schuh812d0d12021-11-04 20:16:48 -0700109units::second_t IterativeRobotBase::GetPeriod() const {
110 return m_period;
111}
112
Brian Silverman8fce7482020-01-05 13:18:21 -0800113void IterativeRobotBase::LoopFunc() {
James Kuszmaulcf324122023-01-14 14:07:17 -0800114 DriverStation::RefreshData();
Brian Silverman8fce7482020-01-05 13:18:21 -0800115 m_watchdog.Reset();
116
Austin Schuh812d0d12021-11-04 20:16:48 -0700117 // Get current mode
118 DSControlWord word;
119 Mode mode = Mode::kNone;
120 if (word.IsDisabled()) {
121 mode = Mode::kDisabled;
122 } else if (word.IsAutonomous()) {
123 mode = Mode::kAutonomous;
124 } else if (word.IsTeleop()) {
125 mode = Mode::kTeleop;
126 } else if (word.IsTest()) {
127 mode = Mode::kTest;
128 }
129
130 // If mode changed, call mode exit and entry functions
131 if (m_lastMode != mode) {
132 // Call last mode's exit function
133 if (m_lastMode == Mode::kDisabled) {
134 DisabledExit();
135 } else if (m_lastMode == Mode::kAutonomous) {
136 AutonomousExit();
137 } else if (m_lastMode == Mode::kTeleop) {
138 TeleopExit();
139 } else if (m_lastMode == Mode::kTest) {
James Kuszmaulcf324122023-01-14 14:07:17 -0800140 if (m_lwEnabledInTest) {
141 LiveWindow::SetEnabled(false);
142 Shuffleboard::DisableActuatorWidgets();
143 }
Austin Schuh812d0d12021-11-04 20:16:48 -0700144 TestExit();
145 }
146
147 // Call current mode's entry function
148 if (mode == Mode::kDisabled) {
Brian Silverman8fce7482020-01-05 13:18:21 -0800149 DisabledInit();
150 m_watchdog.AddEpoch("DisabledInit()");
Austin Schuh812d0d12021-11-04 20:16:48 -0700151 } else if (mode == Mode::kAutonomous) {
Brian Silverman8fce7482020-01-05 13:18:21 -0800152 AutonomousInit();
153 m_watchdog.AddEpoch("AutonomousInit()");
Austin Schuh812d0d12021-11-04 20:16:48 -0700154 } else if (mode == Mode::kTeleop) {
Brian Silverman8fce7482020-01-05 13:18:21 -0800155 TeleopInit();
156 m_watchdog.AddEpoch("TeleopInit()");
Austin Schuh812d0d12021-11-04 20:16:48 -0700157 } else if (mode == Mode::kTest) {
James Kuszmaulcf324122023-01-14 14:07:17 -0800158 if (m_lwEnabledInTest) {
159 LiveWindow::SetEnabled(true);
160 Shuffleboard::EnableActuatorWidgets();
161 }
Brian Silverman8fce7482020-01-05 13:18:21 -0800162 TestInit();
163 m_watchdog.AddEpoch("TestInit()");
Brian Silverman8fce7482020-01-05 13:18:21 -0800164 }
165
Austin Schuh812d0d12021-11-04 20:16:48 -0700166 m_lastMode = mode;
167 }
168
169 // Call the appropriate function depending upon the current robot mode
170 if (mode == Mode::kDisabled) {
171 HAL_ObserveUserProgramDisabled();
172 DisabledPeriodic();
173 m_watchdog.AddEpoch("DisabledPeriodic()");
174 } else if (mode == Mode::kAutonomous) {
175 HAL_ObserveUserProgramAutonomous();
176 AutonomousPeriodic();
177 m_watchdog.AddEpoch("AutonomousPeriodic()");
178 } else if (mode == Mode::kTeleop) {
179 HAL_ObserveUserProgramTeleop();
180 TeleopPeriodic();
181 m_watchdog.AddEpoch("TeleopPeriodic()");
182 } else if (mode == Mode::kTest) {
Brian Silverman8fce7482020-01-05 13:18:21 -0800183 HAL_ObserveUserProgramTest();
184 TestPeriodic();
185 m_watchdog.AddEpoch("TestPeriodic()");
186 }
187
188 RobotPeriodic();
189 m_watchdog.AddEpoch("RobotPeriodic()");
190
191 SmartDashboard::UpdateValues();
192 m_watchdog.AddEpoch("SmartDashboard::UpdateValues()");
Austin Schuh812d0d12021-11-04 20:16:48 -0700193 LiveWindow::UpdateValues();
Brian Silverman8fce7482020-01-05 13:18:21 -0800194 m_watchdog.AddEpoch("LiveWindow::UpdateValues()");
195 Shuffleboard::Update();
196 m_watchdog.AddEpoch("Shuffleboard::Update()");
Austin Schuh1e69f942020-11-14 15:06:14 -0800197
198 if constexpr (IsSimulation()) {
Austin Schuh812d0d12021-11-04 20:16:48 -0700199 HAL_SimPeriodicBefore();
Austin Schuh1e69f942020-11-14 15:06:14 -0800200 SimulationPeriodic();
Austin Schuh812d0d12021-11-04 20:16:48 -0700201 HAL_SimPeriodicAfter();
Austin Schuh1e69f942020-11-14 15:06:14 -0800202 m_watchdog.AddEpoch("SimulationPeriodic()");
203 }
204
Brian Silverman8fce7482020-01-05 13:18:21 -0800205 m_watchdog.Disable();
206
Austin Schuh812d0d12021-11-04 20:16:48 -0700207 // Flush NetworkTables
208 if (m_ntFlushEnabled) {
James Kuszmaulcf324122023-01-14 14:07:17 -0800209 nt::NetworkTableInstance::GetDefault().FlushLocal();
Austin Schuh812d0d12021-11-04 20:16:48 -0700210 }
211
Brian Silverman8fce7482020-01-05 13:18:21 -0800212 // Warn on loop time overruns
213 if (m_watchdog.IsExpired()) {
214 m_watchdog.PrintEpochs();
215 }
216}
217
218void IterativeRobotBase::PrintLoopOverrunMessage() {
Austin Schuh812d0d12021-11-04 20:16:48 -0700219 FRC_ReportError(err::Error, "Loop time of {:.6f}s overrun", m_period.value());
Brian Silverman8fce7482020-01-05 13:18:21 -0800220}