Skip to content

Commit c454e6d

Browse files
committed
First version of iterativerobotpy.py
Signed-off-by: Mike Stitt <mikestitt@peas.local>
1 parent 5f63797 commit c454e6d

File tree

1 file changed

+237
-0
lines changed

1 file changed

+237
-0
lines changed
Lines changed: 237 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,237 @@
1+
import hal
2+
import ntcore
3+
import wpilib
4+
import wpilib._impl
5+
import wpilib._impl.report_error
6+
7+
8+
from enum import IntEnum
9+
10+
11+
class IterativeRobotMode(IntEnum):
12+
kNone = 0
13+
kDisabled = 1
14+
kAutonomous = 2
15+
kTeleop = 3
16+
kTest = 4
17+
18+
19+
class IterativeRobotPy(wpilib.RobotBase):
20+
21+
def __init__(self, period: float):
22+
super().__init__()
23+
self._m_word = wpilib.DSControlWord()
24+
self._m_period = period
25+
self._m_watchdog = wpilib.Watchdog(self._m_period, self.printLoopOverrunMessage)
26+
self._mode: IterativeRobotMode = IterativeRobotMode.kNone
27+
self._m_lastMode: IterativeRobotMode = IterativeRobotMode.kNone
28+
self._m_ntFlushEnabled: bool = True
29+
self._m_lwEnabledInTest: bool = False
30+
self._m_calledDsConnected: bool = False
31+
self._m_reportedLw: bool = False
32+
self._robotPeriodicHasRun: bool = False
33+
self._simulationPeriodicHasRun: bool = False
34+
self._disabledPeriodicHasRun: bool = False
35+
self._autonomousPeriodicHasRun: bool = False
36+
self._teleopPeriodicHasRun: bool = False
37+
self._testPeriodicHasRun: bool = False
38+
39+
def printLoopOverrunMessage(self):
40+
pass
41+
42+
def robotInit(self):
43+
pass
44+
45+
def driverStationConnected(self):
46+
pass
47+
48+
def simulationInit(self):
49+
pass
50+
51+
def disabledInit(self):
52+
pass
53+
54+
def autonomousInit(self):
55+
pass
56+
57+
def teleopInit(self):
58+
pass
59+
60+
def testInit(self):
61+
pass
62+
63+
def robotPeriodic(self):
64+
if not self._robotPeriodicHasRun:
65+
print(f"Default RobotPeriodic() method...Override me!")
66+
self._robotPeriodicHasRun = True
67+
68+
def simulationPeriodic(self):
69+
if not self._simulationPeriodicHasRun:
70+
print(f"Default simulationPeriodic() method...Override me!")
71+
self._simulationPeriodicHasRun = True
72+
73+
def disabledPeriodic(self):
74+
if not self._disabledPeriodicHasRun:
75+
print(f"Default disabledPeriodic() method...Override me!")
76+
self._disabledPeriodicHasRun = True
77+
78+
def autonomousPeriodic(self):
79+
if not self._autonomousPeriodicHasRun:
80+
print(f"Default autonomousPeriodic() method...Override me!")
81+
self._autonomousPeriodicHasRun = True
82+
83+
def teleopPeriodic(self):
84+
if not self._teleopPeriodicHasRun:
85+
print(f"Default teleopPeriodic() method...Override me!")
86+
self._teleopPeriodicHasRun = True
87+
88+
def testPeriodic(self):
89+
if not self._testPeriodicHasRun:
90+
print(f"Default testPeriodic() method...Override me!")
91+
self._teleopPeriodicHasRun = True
92+
93+
def disabledExit(self):
94+
pass
95+
96+
def autonomousExit(self):
97+
pass
98+
99+
def teleopExit(self):
100+
pass
101+
102+
def testExit(self):
103+
pass
104+
105+
# todo @Deprecated(forRemoval=true, since="2025")
106+
def setNetworkTablesFlushEnabled(self, enabled: bool):
107+
self._m_ntFlushEnabled = enabled
108+
109+
def enableLiveWindowInTest(self, testLW: bool):
110+
if self.isTestEnabled():
111+
pass
112+
# todo throw
113+
# throw FRC_MakeError(err::IncompatibleMode,
114+
# "Can't configure test mode while in test mode!")
115+
if not self._m_reportedLw and testLW:
116+
hal.report(
117+
hal.tResourceType.kResourceType_SmartDashboard,
118+
hal.tInstances.kSmartDashboard_LiveWindow,
119+
)
120+
self._m_reportedLw = True
121+
self._m_lwEnabledInTest = testLW
122+
123+
def isLiveWindowEnabledInTest(self) -> bool:
124+
return self._m_lwEnabledInTest
125+
126+
def getPeriod(self) -> float:
127+
return self._m_period
128+
129+
def loopFunc(self):
130+
wpilib.DriverStation.refreshData()
131+
self._m_watchdog.reset()
132+
133+
self._m_word.refresh() # todo from Java implementation
134+
135+
mode = IterativeRobotMode.kNone
136+
if self._m_word.IsDisabled():
137+
mode = IterativeRobotMode.kDisabled
138+
elif self._m_word.IsAutonomous():
139+
mode = IterativeRobotMode.kAutonomous
140+
elif self._m_word.IsTeleop():
141+
mode = IterativeRobotMode.kTeleop
142+
elif self._m_word.IsTest():
143+
mode = IterativeRobotMode.kTest
144+
145+
if not self._m_calledDsConnected and self._m_word.IsDSAttached():
146+
self._m_calledDsConnected = True
147+
self.driverStationConnected()
148+
149+
# If mode changed, call mode exit and entry functions
150+
if self._m_lastMode != mode:
151+
if self._m_lastMode == IterativeRobotMode.kDisabled:
152+
self.disabledExit()
153+
elif self._m_lastMode == IterativeRobotMode.kAutonomous:
154+
self.autonomousExit()
155+
elif self._m_lastMode == IterativeRobotMode.kTeleop:
156+
self.teleopExit()
157+
elif self._m_lastMode == IterativeRobotMode.kTest:
158+
if self._m_lwEnabledInTest:
159+
wpilib.LiveWindow.setEnabled(False)
160+
# todo Shuffleboard::DisableActuatorWidgets()
161+
self.testExit()
162+
163+
if mode == IterativeRobotMode.kDisabled:
164+
self.disabledInit()
165+
self._m_watchdog.addEpoch("DisabledInit()")
166+
elif mode == IterativeRobotMode.kAutonomous:
167+
self.autonomousInit()
168+
self._m_watchdog.addEpoch("AutonomousInit()")
169+
elif mode == IterativeRobotMode.kTeleop:
170+
self.teleopInit()
171+
self._m_watchdog.addEpoch("TeleopInit()")
172+
elif mode == IterativeRobotMode.kTest:
173+
if self._m_lwEnabledInTest:
174+
wpilib.LiveWindow.setEnabled(True)
175+
# todo Shuffleboard::EnableActuatorWidgets()
176+
self.testInit()
177+
self._m_watchdog.addEpoch("TestInit()")
178+
self._m_lastMode = mode
179+
180+
# Call the appropriate function depending upon the current robot mode
181+
if mode == IterativeRobotMode.kDisabled:
182+
hal.observeUserProgramDisabled()
183+
self.disabledPeriodic()
184+
self._m_watchdog.addEpoch("DisabledPeriodic()")
185+
elif mode == IterativeRobotMode.kAutonomous:
186+
hal.observeUserProgramAutonomous()
187+
self.autonomousPeriodic()
188+
self._m_watchdog.addEpoch("AutonomousPeriodic()")
189+
elif mode == IterativeRobotMode.kTeleop:
190+
hal.observeUserProgramTeleop()
191+
self.teleopPeriodic()
192+
self._m_watchdog.addEpoch("TeleopPeriodic()")
193+
elif mode == IterativeRobotMode.kTest:
194+
hal.observeUserProgramTest()
195+
self.testPeriodic()
196+
self._m_watchdog.addEpoch("TestPeriodic()")
197+
198+
self.robotPeriodic()
199+
self._m_watchdog.addEpoch("RobotPeriodic()")
200+
#
201+
wpilib.SmartDashboard.updateValues()
202+
self._m_watchdog.addEpoch("SmartDashboard::UpdateValues()")
203+
wpilib.LiveWindow.updateValues()
204+
self._m_watchdog.addEpoch("LiveWindow::UpdateValues()")
205+
# todo Shuffleboard::Update()
206+
self._m_watchdog.addEpoch("Shuffleboard::Update()")
207+
if self.isSimulation():
208+
hal.simPeriodicBefore()
209+
self.simulationPeriodic()
210+
hal.simPeriodicAfter()
211+
self._m_watchdog.addEpoch("SimulationPeriodic()")
212+
213+
self._m_watchdog.Disable()
214+
215+
# // Flush NetworkTables
216+
if self._m_ntFlushEnabled:
217+
ntcore.NetworkTableInstance.getDefault().flushLocal()
218+
219+
# Warn on loop time overruns
220+
if self._m_watchdog.IsExpired():
221+
self._m_watchdog.PrintEpochs()
222+
223+
def printLoopOverrunMessages(self):
224+
# todo ask about this
225+
# cpp has this as a error, java as a warning, is this the right way to call?
226+
# void IterativeRobotBase::PrintLoopOverrunMessage() {
227+
# FRC_ReportError(err::Error, "Loop time of {:.6f}s overrun", m_period.value())
228+
# }
229+
# private void printLoopOverrunMessage() {
230+
# DriverStation.reportWarning("Loop time of " + m_period + "s overrun\n", false);
231+
# }
232+
wpilib._impl.report_error.reportWarning(
233+
f"Loop time of {self._m_period}s overrun\n", False
234+
)
235+
236+
def printWatchdogEpochs(self):
237+
self._m_watchdog.printEpochs()

0 commit comments

Comments
 (0)