@@ -58,9 +58,45 @@ def __init__(
5858
5959 self ._decoded = False # Set False on wait_for_msg, True after decoded
6060
61+ # Logging util
62+ self .logging_callback : Callable | None = None
63+ self .logging_rate = 10 # Hz
64+ self ._log_thread = threading .Thread (target = self ._log_loop , daemon = True )
65+
6166 def __del__ (self ):
6267 self .stop_callback_thread ()
6368
69+ def set_logging_callback (self , callback : Callable , rate : float = 10.0 ):
70+ """
71+ Sets a logging callback function that will be called at a fixed rate in a separate thread.
72+ The function should take no arguments.
73+
74+ callback: the function to call
75+ rate: the rate in Hz to call the function
76+ """
77+ if not callable (callback ):
78+ print ("Logging callback is not callable. Skipping." )
79+ return
80+ self .logging_callback = callback
81+ self .logging_rate = rate
82+ if not self ._log_thread .is_alive ():
83+ self ._log_thread .start ()
84+
85+ def _log_loop (self ):
86+ """
87+ Internal method for logging at a fixed rate.
88+ """
89+ while not self .end :
90+ try :
91+ start_time = time .time ()
92+ self .logging_callback ()
93+ time .sleep (
94+ max (0 , (1.0 / self .logging_rate ) - (time .time () - start_time ))
95+ )
96+ except Exception :
97+ time .sleep (0.1 )
98+ continue
99+
64100 @thread_safe
65101 def update_timestamp (self , timestamp : float ):
66102 """
@@ -104,6 +140,8 @@ def stop_callback_thread(self):
104140 Do not override this method.
105141 """
106142 self .end = True
143+ if self ._log_thread .is_alive ():
144+ self ._log_thread .join ()
107145 if self ._decodethread is not None :
108146 self ._decodethread .join ()
109147 self ._decodethread = None
0 commit comments