_update_functions.py
Go to the documentation of this file.
1 # Software License Agreement (BSD License)
2 #
3 # Copyright (c) 2012, Willow Garage, Inc.
4 # All rights reserved.
5 #
6 # Redistribution and use in source and binary forms, with or without
7 # modification, are permitted provided that the following conditions
8 # are met:
9 #
10 # * Redistributions of source code must retain the above copyright
11 # notice, this list of conditions and the following disclaimer.
12 # * Redistributions in binary form must reproduce the above
13 # copyright notice, this list of conditions and the following
14 # disclaimer in the documentation and/or other materials provided
15 # with the distribution.
16 # * Neither the name of Willow Garage, Inc. nor the names of its
17 # contributors may be used to endorse or promote products derived
18 # from this software without specific prior written permission.
19 #
20 # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21 # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22 # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
23 # FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
24 # COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
25 # INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
26 # BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
27 # LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
28 # CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29 # LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
30 # ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
31 # POSSIBILITY OF SUCH DAMAGE.
32 
33 # -*- coding: utf-8 -*-
34 
35 """ diagnostic_updater for Python.
36 @author Brice Rebsamen <brice [dot] rebsamen [gmail]>
37 """
38 
39 import rospy
40 from ._diagnostic_updater import *
41 
42 
44  """A structure that holds the constructor parameters for the FrequencyStatus
45  class.
46 
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'}
50 
51  :ivar dict freq_bound: Dictionary with keys `min` and `max`, containing the min
52  and max acceptable frequencies.
53 
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
58  `freq_bound['max']`.
59 
60  :ivar int window_size: The number of events to consider in the statistics.
61  """
62 
63  def __init__(self, freq_bound, tolerance = 0.1, window_size = 5):
64  """Creates a filled-out :class:`FrequencyStatusParam`.
65 
66  :param dict freq_bound: Dictionary with keys `min` and `max`, containing the min
67  and max acceptable frequencies.
68 
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
73  `freq_bound['max']`.
74 
75  :param int window_size: The number of events to consider in the statistics.
76  """
77  self.freq_bound = freq_bound
78  self.tolerance = tolerance
79  self.window_size = window_size
80 
81 
83  """A diagnostic task that monitors the frequency of an event.
84 
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.
89  """
90 
91  def __init__(self, params, name = "FrequencyStatus"):
92  """Constructs a FrequencyStatus class with the given parameters.
93 
94  :param FrequencyStatus params: parameters of the diagnostic task.
95  :param str name: name of the diagnostic task.
96  """
97  DiagnosticTask.__init__(self, name)
98  self.params = params
99  self.lock = threading.Lock()
100  self.clear()
101 
102  def clear(self):
103  """Resets the statistics."""
104  with self.lock:
105  self.count = 0
106  curtime = rospy.Time.now()
107  self.times = [curtime for i in range(self.params.window_size)]
108  self.seq_nums = [0 for i in range(self.params.window_size)]
109  self.hist_indx = 0
110 
111  def tick(self):
112  """Signals that an event has occurred."""
113  with self.lock:
114  self.count += 1
115 
116  def run(self, stat):
117  with self.lock:
118  curtime = rospy.Time.now()
119  curseq = self.count
120  events = curseq - self.seq_nums[self.hist_indx]
121  window = (curtime - self.times[self.hist_indx]).to_sec()
122  freq = events / window
123  self.seq_nums[self.hist_indx] = curseq
124  self.times[self.hist_indx] = curtime
125  self.hist_indx = (self.hist_indx + 1) % self.params.window_size
126 
127  if events == 0:
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.")
133  else:
134  stat.summary(0, "Desired frequency met")
135 
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)))
146 
147  return stat
148 
149 
151  """A structure that holds the constructor parameters for the :class:`TimeStampStatus` class.
152 
153  :ivar float max_acceptable: maximum acceptable difference between two timestamps.
154  :ivar float min_acceptable: minimum acceptable difference between two timestamps.
155  """
156 
157  def __init__(self, min_acceptable = -1, max_acceptable = 5):
158  """Creates a filled-out :class:`TimeStampStatusParam`.
159 
160  :param float min_acceptable: minimum acceptable difference between two timestamps.
161  :param float max_acceptable: maximum acceptable difference between two timestamps.
162  """
163  self.max_acceptable = max_acceptable
164  self.min_acceptable = min_acceptable
165 
166 
168  """Diagnostic task to monitor the interval between events.
169 
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.
176  """
177 
178  def __init__(self, params = TimeStampStatusParam(), name = "Timestamp Status"):
179  """Constructs the :class:`TimeStampStatus` with the given parameters.
180 
181  :param TimeStampStatus params: parameters of the diagnostic task.
182  :param str name: name of the diagnostic task.
183  """
184  DiagnosticTask.__init__(self, name)
185  self.params = params
186  self.lock = threading.Lock()
187  self.early_count = 0
188  self.late_count = 0
189  self.zero_count = 0
190  self.zero_seen = False
191  self.max_delta = 0
192  self.min_delta = 0
193  self.deltas_valid = False
194 
195  def tick(self, stamp):
196  """Signals an event.
197 
198  :param stamp: The timestamp of the event that will be used in computing intervals.
199  :type stamp: float or rospy.Time.
200  """
201  if not isinstance(stamp, float):
202  stamp = stamp.to_sec()
203 
204  with self.lock:
205  if stamp == 0:
206  self.zero_seen = True
207  else:
208  delta = rospy.Time.now().to_sec() - stamp
209  if not self.deltas_valid or delta > self.max_delta:
210  self.max_delta = delta
211  if not self.deltas_valid or delta < self.min_delta:
212  self.min_delta = delta
213  self.deltas_valid = True
214 
215  def run(self, stat):
216  with self.lock:
217 
218  stat.summary(0, "Timestamps are reasonable.")
219  if not self.deltas_valid:
220  stat.summary(1, "No data since last update.")
221  else:
222  if self.min_delta < self.params.min_acceptable:
223  stat.summary(2, "Timestamps too far in future seen.")
224  self.early_count += 1
225  if self.max_delta > self.params.max_acceptable:
226  stat.summary(2, "Timestamps too far in past seen.")
227  self.late_count += 1
228  if self.zero_seen:
229  stat.summary(2, "Zero timestamp seen.")
230  self.zero_count += 1
231 
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)
239 
240  self.deltas_valid = False
241  self.min_delta = 0
242  self.max_delta = 0
243  self.zero_seen = False
244 
245  return stat
246 
247 
249  """Diagnostic task to monitor whether a node is alive
250 
251  This diagnostic task always reports as OK and 'Alive' when it runs
252  """
253 
254  def __init__(self):
255  """Constructs a HeartBeat"""
256  DiagnosticTask.__init__(self, "Heartbeat")
257 
258  def run(self, stat):
259  stat.summary(0, "Alive")
260  return stat
diagnostic_updater._update_functions.FrequencyStatus.times
times
Definition: _update_functions.py:107
diagnostic_updater._update_functions.TimeStampStatus
Definition: _update_functions.py:167
diagnostic_updater._update_functions.TimeStampStatus.__init__
def __init__(self, params=TimeStampStatusParam(), name="Timestamp Status")
Definition: _update_functions.py:178
diagnostic_updater._diagnostic_updater.DiagnosticTask
Definition: _diagnostic_updater.py:50
diagnostic_updater._update_functions.TimeStampStatus.max_delta
max_delta
Definition: _update_functions.py:191
diagnostic_updater._update_functions.FrequencyStatusParam.freq_bound
freq_bound
Definition: _update_functions.py:77
diagnostic_updater._update_functions.FrequencyStatus
Definition: _update_functions.py:82
diagnostic_updater._update_functions.TimeStampStatus.late_count
late_count
Definition: _update_functions.py:188
diagnostic_updater._update_functions.FrequencyStatusParam
Definition: _update_functions.py:43
diagnostic_updater._update_functions.FrequencyStatus.tick
def tick(self)
Definition: _update_functions.py:111
diagnostic_updater._update_functions.TimeStampStatusParam.__init__
def __init__(self, min_acceptable=-1, max_acceptable=5)
Definition: _update_functions.py:157
diagnostic_updater._update_functions.TimeStampStatus.zero_count
zero_count
Definition: _update_functions.py:189
diagnostic_updater._update_functions.Heartbeat.run
def run(self, stat)
Definition: _update_functions.py:258
diagnostic_updater._update_functions.TimeStampStatus.run
def run(self, stat)
Definition: _update_functions.py:215
diagnostic_updater._update_functions.TimeStampStatus.lock
lock
Definition: _update_functions.py:186
diagnostic_updater._update_functions.FrequencyStatus.run
def run(self, stat)
Definition: _update_functions.py:116
diagnostic_updater._update_functions.TimeStampStatus.early_count
early_count
Definition: _update_functions.py:187
diagnostic_updater._update_functions.TimeStampStatusParam.max_acceptable
max_acceptable
Definition: _update_functions.py:163
diagnostic_updater._update_functions.TimeStampStatusParam.min_acceptable
min_acceptable
Definition: _update_functions.py:164
diagnostic_updater._update_functions.FrequencyStatus.lock
lock
Definition: _update_functions.py:99
diagnostic_updater._update_functions.FrequencyStatus.count
count
Definition: _update_functions.py:105
diagnostic_updater._update_functions.FrequencyStatus.params
params
Definition: _update_functions.py:98
diagnostic_updater._update_functions.Heartbeat.__init__
def __init__(self)
Definition: _update_functions.py:254
diagnostic_updater._update_functions.TimeStampStatus.min_delta
min_delta
Definition: _update_functions.py:192
diagnostic_updater._update_functions.Heartbeat
Definition: _update_functions.py:248
diagnostic_updater._update_functions.FrequencyStatusParam.window_size
window_size
Definition: _update_functions.py:79
diagnostic_updater._update_functions.FrequencyStatus.clear
def clear(self)
Definition: _update_functions.py:102
diagnostic_updater._update_functions.TimeStampStatus.tick
def tick(self, stamp)
Definition: _update_functions.py:195
diagnostic_updater._update_functions.FrequencyStatus.__init__
def __init__(self, params, name="FrequencyStatus")
Definition: _update_functions.py:91
diagnostic_updater._update_functions.FrequencyStatusParam.__init__
def __init__(self, freq_bound, tolerance=0.1, window_size=5)
Definition: _update_functions.py:63
diagnostic_updater._update_functions.TimeStampStatus.params
params
Definition: _update_functions.py:185
diagnostic_updater._update_functions.FrequencyStatus.seq_nums
seq_nums
Definition: _update_functions.py:108
diagnostic_updater._update_functions.FrequencyStatusParam.tolerance
tolerance
Definition: _update_functions.py:78
diagnostic_updater._update_functions.TimeStampStatusParam
Definition: _update_functions.py:150
diagnostic_updater._update_functions.FrequencyStatus.hist_indx
hist_indx
Definition: _update_functions.py:109
diagnostic_updater._update_functions.TimeStampStatus.zero_seen
zero_seen
Definition: _update_functions.py:190
diagnostic_updater._update_functions.TimeStampStatus.deltas_valid
deltas_valid
Definition: _update_functions.py:193


diagnostic_updater
Author(s): Kevin Watts, Brice Rebsamen , Jeremy Leibs, Blaise Gassend
autogenerated on Tue May 6 2025 02:17:37