Skip to content

Commit af0809a

Browse files
committed
magicbot: Add tunable update listener method
This adds a way to add a callback for NT updates to tunables.
1 parent 48512fc commit af0809a

File tree

1 file changed

+29
-2
lines changed

1 file changed

+29
-2
lines changed

magicbot/magic_tunable.py

+29-2
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import functools
22
import inspect
33
import warnings
4-
from typing import Generic, Optional, TypeVar
4+
from typing import Callable, Generic, Optional, TypeVar
55

66
from networktables import NetworkTables
77
from ntcore.value import Value
@@ -67,6 +67,7 @@ def execute(self):
6767
# "__doc__",
6868
"_mkv",
6969
"_nt",
70+
"_update_cb",
7071
)
7172

7273
def __init__(
@@ -87,16 +88,35 @@ def __init__(
8788

8889
self._mkv = Value.getFactory(default)
8990
self._nt = NetworkTables
91+
self._update_cb = None
9092

9193
def __get__(self, instance, owner) -> V:
9294
if instance is not None:
9395
return instance._tunables[self].value
9496
return self
9597

96-
def __set__(self, instance, value) -> None:
98+
def __set__(self, instance, value: V) -> None:
9799
v = instance._tunables[self]
98100
self._nt._api.setEntryValueById(v._local_id, self._mkv(value))
99101

102+
def set_callback(self, callback: Callable[[V], None]) -> None:
103+
"""
104+
Set a method to be called when the tunable is updated over NetworkTables.
105+
106+
This can be useful, for example, for changing PID gains on a
107+
motor controller on the fly::
108+
109+
class Component:
110+
pid: ...
111+
112+
kP = tunable(0.01)
113+
114+
@kP.set_callback
115+
def set_kP(self, value: float) -> None:
116+
self.pid.setP(value)
117+
"""
118+
self._update_cb = lambda inst, notif: callback(inst, notif.value.value)
119+
100120

101121
def setup_tunables(component, cname: str, prefix: Optional[str] = "components") -> None:
102122
"""
@@ -137,6 +157,13 @@ def setup_tunables(component, cname: str, prefix: Optional[str] = "components")
137157
)
138158
tunables[prop] = ntvalue
139159

160+
if prop._update_cb:
161+
prop._nt._api.addEntryListenerById(
162+
ntvalue._local_id,
163+
functools.partial(prop._update_cb, component),
164+
NetworkTables.NotifyFlags.UPDATE,
165+
)
166+
140167
component._tunables = tunables
141168

142169

0 commit comments

Comments
 (0)