35 """ diagnostic_updater for Python.
36 @author Brice Rebsamen <brice [dot] rebsamen [gmail]>
40 from ._diagnostic_updater
import *
44 """A structure that holds the constructor parameters for the FrequencyStatus
47 Implementation note: the `min_freq` and `max_freq` parameters in the C++ code
48 are stored as pointers, so that if they are updated, the new values are used.
49 To emulate this behavior, we here use a dictionary to hold them: {'min','max'}
51 :ivar dict freq_bound: Dictionary with keys `min` and `max`, containing the min
52 and max acceptable frequencies.
54 :ivar float tolerance: The tolerance with which bounds must be satisfied. Acceptable
55 values are from `freq_bound['min'] * (1 - torelance)` to
56 `freq_bound['max'] * (1 + tolerance)`. Common use cases are to set
57 tolerance to zero, or to assign the same value to `freq_bound['min']` and
60 :ivar int window_size: The number of events to consider in the statistics.
63 def __init__(self, freq_bound, tolerance = 0.1, window_size = 5):
64 """Creates a filled-out :class:`FrequencyStatusParam`.
66 :param dict freq_bound: Dictionary with keys `min` and `max`, containing the min
67 and max acceptable frequencies.
69 :param float tolerance: The tolerance with which bounds must be satisfied. Acceptable
70 values are from `freq_bound['min'] * (1 - torelance)` to
71 `freq_bound['max'] * (1 + tolerance)`. Common use cases are to set
72 tolerance to zero, or to assign the same value to `freq_bound['min']` and
75 :param int window_size: The number of events to consider in the statistics.
83 """A diagnostic task that monitors the frequency of an event.
85 This diagnostic task monitors the frequency of calls to its tick method,
86 and creates corresponding diagnostics. It will report a warning if the
87 frequency is outside acceptable bounds, and report an error if there have
88 been no events in the latest window.
91 def __init__(self, params, name = "FrequencyStatus"):
92 """Constructs a FrequencyStatus class with the given parameters.
94 :param FrequencyStatus params: parameters of the diagnostic task.
95 :param str name: name of the diagnostic task.
97 DiagnosticTask.__init__(self, name)
99 self.
lock = threading.Lock()
103 """Resets the statistics."""
106 curtime = rospy.Time.now()
112 """Signals that an event has occurred."""
118 curtime = rospy.Time.now()
122 freq = events / window
128 stat.summary(2,
"No events recorded.")
129 elif freq < self.
params.freq_bound[
'min'] * (1 - self.
params.tolerance):
130 stat.summary(1,
"Frequency too low.")
131 elif 'max' in self.
params.freq_bound
and freq > self.
params.freq_bound[
'max'] * (1 + self.
params.tolerance):
132 stat.summary(1,
"Frequency too high.")
134 stat.summary(0,
"Desired frequency met")
136 stat.add(
"Events in window",
"%d" % events)
137 stat.add(
"Events since startup",
"%d" % self.
count)
138 stat.add(
"Duration of window (s)",
"%f" % window)
139 stat.add(
"Actual frequency (Hz)",
"%f" % freq)
140 if 'max' in self.
params.freq_bound
and self.
params.freq_bound[
'min'] == self.
params.freq_bound[
'max']:
141 stat.add(
"Target frequency (Hz)",
"%f" % self.
params.freq_bound[
'min'])
142 if self.
params.freq_bound[
'min'] > 0:
143 stat.add(
"Minimum acceptable frequency (Hz)",
"%f" % (self.
params.freq_bound[
'min'] * (1 - self.
params.tolerance)))
144 if 'max' in self.
params.freq_bound:
145 stat.add(
"Maximum acceptable frequency (Hz)",
"%f" % (self.
params.freq_bound[
'max'] * (1 + self.
params.tolerance)))
151 """A structure that holds the constructor parameters for the :class:`TimeStampStatus` class.
153 :ivar float max_acceptable: maximum acceptable difference between two timestamps.
154 :ivar float min_acceptable: minimum acceptable difference between two timestamps.
157 def __init__(self, min_acceptable = -1, max_acceptable = 5):
158 """Creates a filled-out :class:`TimeStampStatusParam`.
160 :param float min_acceptable: minimum acceptable difference between two timestamps.
161 :param float max_acceptable: maximum acceptable difference between two timestamps.
168 """Diagnostic task to monitor the interval between events.
170 This diagnostic task monitors the difference between consecutive events,
171 and creates corresponding diagnostics. An error occurs if the interval
172 between consecutive events is too large or too small. An error condition
173 will only be reported during a single diagnostic report unless it
174 persists. Tallies of errors are also maintained to keep track of errors
175 in a more persistent way.
178 def __init__(self, params = TimeStampStatusParam(), name =
"Timestamp Status"):
179 """Constructs the :class:`TimeStampStatus` with the given parameters.
181 :param TimeStampStatus params: parameters of the diagnostic task.
182 :param str name: name of the diagnostic task.
184 DiagnosticTask.__init__(self, name)
198 :param stamp: The timestamp of the event that will be used in computing intervals.
199 :type stamp: float or rospy.Time.
201 if not isinstance(stamp, float):
202 stamp = stamp.to_sec()
208 delta = rospy.Time.now().to_sec() - stamp
218 stat.summary(0,
"Timestamps are reasonable.")
220 stat.summary(1,
"No data since last update.")
223 stat.summary(2,
"Timestamps too far in future seen.")
226 stat.summary(2,
"Timestamps too far in past seen.")
229 stat.summary(2,
"Zero timestamp seen.")
232 stat.add(
"Earliest timestamp delay:",
"%f" % self.
min_delta)
233 stat.add(
"Latest timestamp delay:",
"%f" % self.
max_delta)
234 stat.add(
"Earliest acceptable timestamp delay:",
"%f" % self.
params.min_acceptable)
235 stat.add(
"Latest acceptable timestamp delay:",
"%f" % self.
params.max_acceptable)
236 stat.add(
"Late diagnostic update count:",
"%i" % self.
late_count)
237 stat.add(
"Early diagnostic update count:",
"%i" % self.
early_count)
238 stat.add(
"Zero seen diagnostic update count:",
"%i" % self.
zero_count)
249 """Diagnostic task to monitor whether a node is alive
251 This diagnostic task always reports as OK and 'Alive' when it runs
255 """Constructs a HeartBeat"""
256 DiagnosticTask.__init__(self,
"Heartbeat")
259 stat.summary(0,
"Alive")