@@ -34,8 +34,8 @@ class MagicRobot(wpilib.SampleRobot, metaclass=OrderedClass):
3434
3535 MagicRobot uses the :class:`.AutonomousModeSelector` to allow you
3636 to define multiple autonomous modes and to select one of them via
37- the SmartDashboard/SFX .
38-
37+ the SmartDashboard/Shuffleboard .
38+
3939 MagicRobot will set the following NetworkTables variables
4040 automatically:
4141
@@ -78,6 +78,8 @@ def robotInit(self):
7878 self .__nt .putBoolean ("is_simulation" , self .isSimulation ())
7979 self .__nt .putBoolean ("is_ds_attached" , self .ds .isDSAttached ())
8080
81+ self .watchdog = wpilib .Watchdog (self .control_loop_wait_time , self ._loop_overrun )
82+
8183 def createObjects (self ):
8284 """
8385 You should override this and initialize all of your wpilib
@@ -183,9 +185,13 @@ def robotPeriodic(self):
183185 The default implementation will update
184186 SmartDashboard, LiveWindow and Shuffleboard.
185187 """
188+ watchdog = self .watchdog
186189 wpilib .SmartDashboard .updateValues ()
190+ watchdog .addEpoch ("SmartDashboard" )
187191 wpilib .LiveWindow .updateValues ()
192+ watchdog .addEpoch ("LiveWindow" )
188193 Shuffleboard .update ()
194+ watchdog .addEpoch ("Shuffleboard" )
189195
190196 def onException (self , forceReport = False ):
191197 """
@@ -289,6 +295,7 @@ def autonomous(self):
289295 self .control_loop_wait_time ,
290296 (self ._execute_components , self ._update_feedback , self .robotPeriodic ),
291297 self .onException ,
298+ watchdog = self .watchdog ,
292299 )
293300
294301 self ._on_mode_disable_components ()
@@ -301,6 +308,8 @@ def disabled(self):
301308
302309 .. warning:: Internal API, don't override
303310 """
311+ watchdog = self .watchdog
312+ watchdog .reset ()
304313
305314 self .__nt .putString ("mode" , "disabled" )
306315 ds_attached = None
@@ -311,6 +320,7 @@ def disabled(self):
311320 self .disabledInit ()
312321 except :
313322 self .onException (forceReport = True )
323+ watchdog .addEpoch ("disabledInit()" )
314324
315325 with NotifierDelay (self .control_loop_wait_time ) as delay :
316326 while self .isDisabled ():
@@ -323,10 +333,18 @@ def disabled(self):
323333 self .disabledPeriodic ()
324334 except :
325335 self .onException ()
336+ watchdog .addEpoch ("disabledPeriodic()" )
326337
327338 self ._update_feedback ()
328339 self .robotPeriodic ()
340+ watchdog .addEpoch ("robotPeriodic()" )
341+ watchdog .disable ()
342+
343+ if watchdog .isExpired ():
344+ watchdog .printEpochs ()
345+
329346 delay .wait ()
347+ watchdog .reset ()
330348
331349 def operatorControl (self ):
332350 """
@@ -336,6 +354,8 @@ def operatorControl(self):
336354
337355 .. warning:: Internal API, don't override
338356 """
357+ watchdog = self .watchdog
358+ watchdog .reset ()
339359
340360 self .__nt .putString ("mode" , "teleop" )
341361 # don't need to update this during teleop -- presumably will switch
@@ -350,6 +370,7 @@ def operatorControl(self):
350370 self .teleopInit ()
351371 except :
352372 self .onException (forceReport = True )
373+ watchdog .addEpoch ("teleopInit()" )
353374
354375 with NotifierDelay (self .control_loop_wait_time ) as delay :
355376 while self .isOperatorControl () and self .isEnabled ():
@@ -358,17 +379,27 @@ def operatorControl(self):
358379 self .teleopPeriodic ()
359380 except :
360381 self .onException ()
382+ watchdog .addEpoch ("teleopPeriodic()" )
361383
362384 self ._execute_components ()
385+
363386 self ._update_feedback ()
364387 self .robotPeriodic ()
388+ watchdog .addEpoch ("robotPeriodic()" )
389+ watchdog .disable ()
390+
391+ if watchdog .isExpired ():
392+ watchdog .printEpochs ()
365393
366394 delay .wait ()
395+ watchdog .reset ()
367396
368397 self ._on_mode_disable_components ()
369398
370399 def test (self ):
371400 """Called when the robot is in test mode"""
401+ watchdog = self .watchdog
402+ watchdog .reset ()
372403
373404 self .__nt .putString ("mode" , "test" )
374405 self .__nt .putBoolean ("is_ds_attached" , self .ds .isDSAttached ())
@@ -378,6 +409,7 @@ def test(self):
378409 self .testInit ()
379410 except :
380411 self .onException (forceReport = True )
412+ watchdog .addEpoch ("testInit()" )
381413
382414 with NotifierDelay (self .control_loop_wait_time ) as delay :
383415 while self .isTest () and self .isEnabled ():
@@ -386,26 +418,36 @@ def test(self):
386418 self .testPeriodic ()
387419 except :
388420 self .onException ()
421+ watchdog .addEpoch ("testPeriodic()" )
389422
390423 self ._update_feedback ()
391424 self .robotPeriodic ()
425+ watchdog .addEpoch ("robotPeriodic()" )
426+ watchdog .disable ()
427+
428+ if watchdog .isExpired ():
429+ watchdog .printEpochs ()
430+
392431 delay .wait ()
432+ watchdog .reset ()
393433
394434 def _on_mode_enable_components (self ):
395435 # initialize things
396- for component in self ._components :
397- if hasattr (component , "on_enable" ):
436+ for _ , component in self ._components :
437+ on_enable = getattr (component , "on_enable" , None )
438+ if on_enable is not None :
398439 try :
399- component . on_enable ()
440+ on_enable ()
400441 except :
401442 self .onException (forceReport = True )
402443
403444 def _on_mode_disable_components (self ):
404445 # deinitialize things
405- for component in self ._components :
406- if hasattr (component , "on_disable" ):
446+ for _ , component in self ._components :
447+ on_disable = getattr (component , "on_disable" , None )
448+ if on_disable is not None :
407449 try :
408- component . on_disable ()
450+ on_disable ()
409451 except :
410452 self .onException (forceReport = True )
411453
@@ -495,7 +537,6 @@ def _create_components(self):
495537
496538 # For each new component, perform magic injection
497539 for cname , component in components :
498- self ._components .append (component )
499540 setup_tunables (component , cname , "components" )
500541 self ._feedbacks += collect_feedbacks (component , cname , "components" )
501542 self ._setup_vars (cname , component )
@@ -521,6 +562,8 @@ def _create_components(self):
521562 if hasattr (mode , "setup" ):
522563 mode .setup ()
523564
565+ self ._components = components
566+
524567 def _create_component (self , name , ctyp ):
525568 # Create instance, set it on self
526569 component = ctyp ()
@@ -641,13 +684,19 @@ def _update_feedback(self):
641684 self .onException ()
642685 continue
643686 entry .setValue (value )
687+ self .watchdog .addEpoch ("@magicbot.feedback" )
644688
645689 def _execute_components (self ):
646- for component in self ._components :
690+ for name , component in self ._components :
647691 try :
648692 component .execute ()
649693 except :
650694 self .onException ()
695+ self .watchdog .addEpoch (name )
651696
652697 for reset_dict , component in self ._reset_components :
653698 component .__dict__ .update (reset_dict )
699+
700+ def _loop_overrun (self ):
701+ # TODO: print something here without making it extremely annoying
702+ pass
0 commit comments