blob: 2997234f11ae9c56d6f291a02934cfc90a237145 [file] [log] [blame]
Brian Silverman8fce7482020-01-05 13:18:21 -08001/*----------------------------------------------------------------------------*/
2/* Copyright (c) 2017-2019 FIRST. All Rights Reserved. */
3/* Open Source Software - may be modified and shared by FRC teams. The code */
4/* must be accompanied by the FIRST BSD license file in the root directory of */
5/* the project. */
6/*----------------------------------------------------------------------------*/
7
8#include "frc/IterativeRobotBase.h"
9
10#include <cstdio>
11
12#include <hal/DriverStation.h>
13#include <hal/FRCUsageReporting.h>
14#include <wpi/Format.h>
15#include <wpi/SmallString.h>
16#include <wpi/raw_ostream.h>
17
18#include "frc/DriverStation.h"
19#include "frc/Timer.h"
20#include "frc/livewindow/LiveWindow.h"
21#include "frc/shuffleboard/Shuffleboard.h"
22#include "frc/smartdashboard/SmartDashboard.h"
23
24using namespace frc;
25
26IterativeRobotBase::IterativeRobotBase(double period)
27 : IterativeRobotBase(units::second_t(period)) {}
28
29IterativeRobotBase::IterativeRobotBase(units::second_t period)
30 : m_period(period),
31 m_watchdog(period, [this] { PrintLoopOverrunMessage(); }) {}
32
33void IterativeRobotBase::RobotInit() {
34 wpi::outs() << "Default " << __FUNCTION__ << "() method... Override me!\n";
35}
36
37void IterativeRobotBase::DisabledInit() {
38 wpi::outs() << "Default " << __FUNCTION__ << "() method... Override me!\n";
39}
40
41void IterativeRobotBase::AutonomousInit() {
42 wpi::outs() << "Default " << __FUNCTION__ << "() method... Override me!\n";
43}
44
45void IterativeRobotBase::TeleopInit() {
46 wpi::outs() << "Default " << __FUNCTION__ << "() method... Override me!\n";
47}
48
49void IterativeRobotBase::TestInit() {
50 wpi::outs() << "Default " << __FUNCTION__ << "() method... Override me!\n";
51}
52
53void IterativeRobotBase::RobotPeriodic() {
54 static bool firstRun = true;
55 if (firstRun) {
56 wpi::outs() << "Default " << __FUNCTION__ << "() method... Override me!\n";
57 firstRun = false;
58 }
59}
60
61void IterativeRobotBase::DisabledPeriodic() {
62 static bool firstRun = true;
63 if (firstRun) {
64 wpi::outs() << "Default " << __FUNCTION__ << "() method... Override me!\n";
65 firstRun = false;
66 }
67}
68
69void IterativeRobotBase::AutonomousPeriodic() {
70 static bool firstRun = true;
71 if (firstRun) {
72 wpi::outs() << "Default " << __FUNCTION__ << "() method... Override me!\n";
73 firstRun = false;
74 }
75}
76
77void IterativeRobotBase::TeleopPeriodic() {
78 static bool firstRun = true;
79 if (firstRun) {
80 wpi::outs() << "Default " << __FUNCTION__ << "() method... Override me!\n";
81 firstRun = false;
82 }
83}
84
85void IterativeRobotBase::TestPeriodic() {
86 static bool firstRun = true;
87 if (firstRun) {
88 wpi::outs() << "Default " << __FUNCTION__ << "() method... Override me!\n";
89 firstRun = false;
90 }
91}
92
93void IterativeRobotBase::LoopFunc() {
94 m_watchdog.Reset();
95
96 // Call the appropriate function depending upon the current robot mode
97 if (IsDisabled()) {
98 // Call DisabledInit() if we are now just entering disabled mode from
99 // either a different mode or from power-on.
100 if (m_lastMode != Mode::kDisabled) {
101 LiveWindow::GetInstance()->SetEnabled(false);
102 Shuffleboard::DisableActuatorWidgets();
103 DisabledInit();
104 m_watchdog.AddEpoch("DisabledInit()");
105 m_lastMode = Mode::kDisabled;
106 }
107
108 HAL_ObserveUserProgramDisabled();
109 DisabledPeriodic();
110 m_watchdog.AddEpoch("DisabledPeriodic()");
111 } else if (IsAutonomous()) {
112 // Call AutonomousInit() if we are now just entering autonomous mode from
113 // either a different mode or from power-on.
114 if (m_lastMode != Mode::kAutonomous) {
115 LiveWindow::GetInstance()->SetEnabled(false);
116 Shuffleboard::DisableActuatorWidgets();
117 AutonomousInit();
118 m_watchdog.AddEpoch("AutonomousInit()");
119 m_lastMode = Mode::kAutonomous;
120 }
121
122 HAL_ObserveUserProgramAutonomous();
123 AutonomousPeriodic();
124 m_watchdog.AddEpoch("AutonomousPeriodic()");
125 } else if (IsOperatorControl()) {
126 // Call TeleopInit() if we are now just entering teleop mode from
127 // either a different mode or from power-on.
128 if (m_lastMode != Mode::kTeleop) {
129 LiveWindow::GetInstance()->SetEnabled(false);
130 Shuffleboard::DisableActuatorWidgets();
131 TeleopInit();
132 m_watchdog.AddEpoch("TeleopInit()");
133 m_lastMode = Mode::kTeleop;
134 }
135
136 HAL_ObserveUserProgramTeleop();
137 TeleopPeriodic();
138 m_watchdog.AddEpoch("TeleopPeriodic()");
139 } else {
140 // Call TestInit() if we are now just entering test mode from
141 // either a different mode or from power-on.
142 if (m_lastMode != Mode::kTest) {
143 LiveWindow::GetInstance()->SetEnabled(true);
144 Shuffleboard::EnableActuatorWidgets();
145 TestInit();
146 m_watchdog.AddEpoch("TestInit()");
147 m_lastMode = Mode::kTest;
148 }
149
150 HAL_ObserveUserProgramTest();
151 TestPeriodic();
152 m_watchdog.AddEpoch("TestPeriodic()");
153 }
154
155 RobotPeriodic();
156 m_watchdog.AddEpoch("RobotPeriodic()");
157
158 SmartDashboard::UpdateValues();
159 m_watchdog.AddEpoch("SmartDashboard::UpdateValues()");
160 LiveWindow::GetInstance()->UpdateValues();
161 m_watchdog.AddEpoch("LiveWindow::UpdateValues()");
162 Shuffleboard::Update();
163 m_watchdog.AddEpoch("Shuffleboard::Update()");
164 m_watchdog.Disable();
165
166 // Warn on loop time overruns
167 if (m_watchdog.IsExpired()) {
168 m_watchdog.PrintEpochs();
169 }
170}
171
172void IterativeRobotBase::PrintLoopOverrunMessage() {
173 wpi::SmallString<128> str;
174 wpi::raw_svector_ostream buf(str);
175
176 buf << "Loop time of " << wpi::format("%.6f", m_period.to<double>())
177 << "s overrun\n";
178
179 DriverStation::ReportWarning(str);
180}