13
13
14
14
from networktables import NetworkTables
15
15
16
- from .magic_tunable import setup_tunables , _TunableProperty
16
+ from .magic_tunable import setup_tunables , _TunableProperty , collect_feedbacks
17
17
from .magic_reset import will_reset_to
18
18
19
19
__all__ = ['MagicRobot' ]
20
20
21
- def feedback (key = None ):
22
- """
23
- If this decorator is applied to a function,
24
- its return value will automatically be sent
25
- to NetworkTables at key ``/robot/components/component/key``.
26
-
27
- ``key`` is an optional parameter, and if it is not supplied,
28
- the key will default to the method name with 'get_' removed.
29
- If the method does not start with 'get_', the key will be the full
30
- name of the method.
31
-
32
- .. note:: The function will automatically be called in disabled,
33
- autonomous, and teleop.
34
-
35
- .. warning:: The function should only act as a getter, and accept
36
- no arguments.
37
-
38
- Example::
39
-
40
- class Component1:
41
-
42
- @feedback()
43
- def get_angle(self):
44
- return self.navx.getYaw()
45
-
46
- In this example, the NetworkTable key is stored at
47
- ``/robot/components/component1/angle``.
48
- """
49
- def decorator (func ):
50
- if not callable (func ):
51
- raise ValueError ('Illegal use of feedback decorator on non-callable {!r}' .format (func ))
52
- sig = inspect .signature (func )
53
- name = func .__name__
54
-
55
- if len (sig .parameters ) != 1 :
56
- raise ValueError ("{} may not take arguments other than 'self' (must be a simple getter method)" .format (name ))
57
-
58
- nt_key = key
59
- if nt_key is None :
60
- # If no key is passed, get key from method name.
61
- # -1 instead of 1 in case 'get_' is not present,
62
- # in which case the key will be the method name
63
-
64
- if name .startswith ('get_' ):
65
- nt_key = name [4 :]
66
- else :
67
- nt_key = name
68
- # Set '__feedback__ attribute to be checked during injection
69
- func .__feedback__ = True
70
- # Store key within the function to avoid using class dictionary
71
- func .__key__ = nt_key
72
- return func
73
- return decorator
74
21
75
22
class MagicRobot (wpilib .SampleRobot ,
76
23
metaclass = OrderedClass ):
@@ -380,8 +327,6 @@ def operatorControl(self):
380
327
381
328
while self .isOperatorControl () and self .isEnabled ():
382
329
383
- #self._update_autosend()
384
-
385
330
try :
386
331
self .teleopPeriodic ()
387
332
except :
@@ -504,6 +449,7 @@ def _create_components(self):
504
449
for cname , component in components :
505
450
self ._components .append (component )
506
451
setup_tunables (component , cname , 'components' )
452
+ self ._feedbacks += collect_feedbacks (component , cname , 'components' )
507
453
self ._setup_vars (cname , component )
508
454
self ._setup_reset_vars (component )
509
455
@@ -515,6 +461,7 @@ def _create_components(self):
515
461
516
462
# And for self too
517
463
setup_tunables (self , 'robot' , None )
464
+ self ._feedbacks += collect_feedbacks (self , 'robot' , None )
518
465
519
466
# Call setup functions for components
520
467
for cname , component in components :
@@ -532,7 +479,6 @@ def _create_component(self, name, ctyp):
532
479
533
480
# Automatically inject a logger object
534
481
component .logger = logging .getLogger (name )
535
- component ._Magicbot__autosend = {}
536
482
537
483
self .logger .info ("-> %s (class: %s)" , name , ctyp .__name__ )
538
484
@@ -585,10 +531,6 @@ def _setup_vars(self, cname, component):
585
531
586
532
self ._inject (n , inject_type , cname , component )
587
533
588
- for (name , method ) in inspect .getmembers (component , predicate = inspect .ismethod ):
589
- if getattr (method , '__feedback__' , False ):
590
- self ._feedbacks .append ((component , cname , name ))
591
-
592
534
def _inject (self , n , inject_type , cname , component ):
593
535
# Retrieve injectable object
594
536
injectable = self ._injectables .get (n )
@@ -610,11 +552,6 @@ def _inject(self, n, inject_type, cname, component):
610
552
setattr (component , n , injectable )
611
553
self .logger .debug ("-> %s as %s.%s" , injectable , cname , n )
612
554
613
- # XXX
614
- #if is_autosend:
615
- # where to store the nt key?
616
- # component._Magicbot__autosend[prop.f] = None
617
-
618
555
def _setup_reset_vars (self , component ):
619
556
reset_dict = {}
620
557
@@ -629,22 +566,15 @@ def _setup_reset_vars(self, component):
629
566
if reset_dict :
630
567
component .__dict__ .update (reset_dict )
631
568
self ._reset_components .append ((reset_dict , component ))
632
-
633
- #def _update_autosend(self):
634
- # # seems like this should just be a giant list instead
635
- # for component in self._components:
636
- # d = component._Magicbot__autosend
637
- # for f in d.keys():
638
- # d[f] = f(component)
639
569
640
570
def _update_feedback (self ):
641
- for ( component , cname , name ) in self ._feedbacks :
571
+ for method , entry in self ._feedbacks :
642
572
try :
643
- func = getattr ( component , name )
573
+ value = method ( )
644
574
except :
575
+ self .onException ()
645
576
continue
646
- # Put ntvalue at /robot/components/component/key
647
- self .__nt .putValue ('/components/{0}/{1}' .format (cname , func .__key__ ), func ())
577
+ entry .setValue (value )
648
578
649
579
def _execute_components (self ):
650
580
for component in self ._components :
0 commit comments