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 += 1 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 freq_bound is a dictionary with keys 'min' and 'max', containing the min
52 and max acceptable frequencies.
54 tolerance is 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 window_size is 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 FrequencyStatusParam."""
71 """A diagnostic task that monitors the frequency of an event.
73 This diagnostic task monitors the frequency of calls to its tick method,
74 and creates corresponding diagnostics. It will report a warning if the
75 frequency is outside acceptable bounds, and report an error if there have
76 been no events in the latest window.
79 def __init__(self, params, name = "FrequencyStatus"):
80 """Constructs a FrequencyStatus class with the given parameters."""
81 DiagnosticTask.__init__(self, name)
83 self.
lock = threading.Lock()
87 """Resets the statistics."""
90 curtime = rospy.Time.now()
91 self.
times = [curtime
for i
in range(self.
params.window_size)]
96 """Signals that an event has occurred."""
102 curtime = rospy.Time.now()
106 freq = events / window
112 stat.summary(2,
"No events recorded.")
113 elif freq < self.
params.freq_bound[
'min'] * (1 - self.
params.tolerance):
114 stat.summary(1,
"Frequency too low.")
115 elif 'max' in self.
params.freq_bound
and freq > self.
params.freq_bound[
'max'] * (1 + self.
params.tolerance):
116 stat.summary(1,
"Frequency too high.")
118 stat.summary(0,
"Desired frequency met")
120 stat.add(
"Events in window",
"%d" % events)
121 stat.add(
"Events since startup",
"%d" % self.
count)
122 stat.add(
"Duration of window (s)",
"%f" % window)
123 stat.add(
"Actual frequency (Hz)",
"%f" % freq)
124 if 'max' in self.
params.freq_bound
and self.
params.freq_bound[
'min'] == self.
params.freq_bound[
'max']:
125 stat.add(
"Target frequency (Hz)",
"%f" % self.
params.freq_bound[
'min'])
126 if self.
params.freq_bound[
'min'] > 0:
127 stat.add(
"Minimum acceptable frequency (Hz)",
"%f" % (self.
params.freq_bound[
'min'] * (1 - self.
params.tolerance)))
128 if 'max' in self.
params.freq_bound:
129 stat.add(
"Maximum acceptable frequency (Hz)",
"%f" % (self.
params.freq_bound[
'max'] * (1 + self.
params.tolerance)))
135 """A structure that holds the constructor parameters for the TimeStampStatus class.
137 max_acceptable: maximum acceptable difference between two timestamps.
138 min_acceptable: minimum acceptable difference between two timestamps.
141 def __init__(self, min_acceptable = -1, max_acceptable = 5):
142 """Creates a filled-out TimeStampStatusParam."""
148 """Diagnostic task to monitor the interval between events.
150 This diagnostic task monitors the difference between consecutive events,
151 and creates corresponding diagnostics. An error occurs if the interval
152 between consecutive events is too large or too small. An error condition
153 will only be reported during a single diagnostic report unless it
154 persists. Tallies of errors are also maintained to keep track of errors
155 in a more persistent way.
158 def __init__(self, params = TimeStampStatusParam(), name =
"Timestamp Status"):
159 """Constructs the TimeStampStatus with the given parameters."""
160 DiagnosticTask.__init__(self, name)
173 @param stamp The timestamp of the event that will be used in computing
174 intervals. Can be either a double or a ros::Time.
176 if not isinstance(stamp, float):
177 stamp = stamp.to_sec()
183 delta = rospy.Time.now().to_sec() - stamp
193 stat.summary(0,
"Timestamps are reasonable.")
195 stat.summary(1,
"No data since last update.")
198 stat.summary(2,
"Timestamps too far in future seen.")
201 stat.summary(2,
"Timestamps too far in past seen.")
204 stat.summary(2,
"Zero timestamp seen.")
207 stat.add(
"Earliest timestamp delay:",
"%f" % self.
min_delta)
208 stat.add(
"Latest timestamp delay:",
"%f" % self.
max_delta)
209 stat.add(
"Earliest acceptable timestamp delay:",
"%f" % self.
params.min_acceptable)
210 stat.add(
"Latest acceptable timestamp delay:",
"%f" % self.
params.max_acceptable)
211 stat.add(
"Late diagnostic update count:",
"%i" % self.
late_count)
212 stat.add(
"Early diagnostic update count:",
"%i" % self.
early_count)
213 stat.add(
"Zero seen diagnostic update count:",
"%i" % self.
zero_count)
224 """Diagnostic task to monitor whether a node is alive
226 This diagnostic task always reports as OK and 'Alive' when it runs
230 """Constructs a HeartBeat"""
231 DiagnosticTask.__init__(self,
"Heartbeat")
234 stat.summary(0,
"Alive")