WUT Velma robot API
topic_info.py
Go to the documentation of this file.
1 # Copyright (c) 2014, Robot Control and Pattern Recognition Group, Warsaw University of Technology
2 # All rights reserved.
3 #
4 # Redistribution and use in source and binary forms, with or without
5 # modification, are permitted provided that the following conditions are met:
6 # * Redistributions of source code must retain the above copyright
7 # notice, this list of conditions and the following disclaimer.
8 # * Redistributions in binary form must reproduce the above copyright
9 # notice, this list of conditions and the following disclaimer in the
10 # documentation and/or other materials provided with the distribution.
11 # * Neither the name of the Warsaw University of Technology nor the
12 # names of its contributors may be used to endorse or promote products
13 # derived from this software without specific prior written permission.
14 #
15 # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
16 # ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
17 # WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
18 # DISCLAIMED. IN NO EVENT SHALL <COPYright HOLDER> BE LIABLE FOR ANY
19 # DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
20 # (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
21 # LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
22 # ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23 # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
24 # SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25 
26 # this file is modification of ros-visualization/rqt_common_plugins/rqt_topic/src/rqt_topic/topic_info.py
27 
28 from __future__ import division, with_statement
29 try:
30  from cStringIO import StringIO
31 except ImportError:
32  from io import StringIO
33 
34 from python_qt_binding.QtCore import qWarning
35 
36 import roslib
37 import rospy
38 from rostopic import ROSTopicHz
39 
40 # patch begin
41 import os
42 # patch end
43 
44 class TopicInfo(ROSTopicHz):
45 
46  def __init__(self, topic_name, topic_type):
47  super(TopicInfo, self).__init__(100)
48  self._topic_name = topic_name
49  self.error = None
50  self._subscriber = None
51  self.monitoring = False
52  self._reset_data()
53  self.message_class = None
54  try:
55  self.message_class = roslib.message.get_message_class(topic_type)
56  except Exception as e:
57  self.message_class = None
58  qWarning('TopicInfo.__init__(): %s' % (e))
59 
60  if self.message_class is None:
61  self.error = 'can not get message class for type "%s"' % topic_type
62  qWarning('TopicInfo.__init__(): topic "%s": %s' % (topic_name, self.error))
63 
64  def _reset_data(self):
65  self.last_message = None
66  self.times = []
67  self.timestamps = []
68  self.sizes = []
69 
70  def toggle_monitoring(self):
71  if self.monitoring:
72  self.stop_monitoring()
73  else:
74  self.start_monitoring()
75 
76  def start_monitoring(self):
77  if self.message_class is not None:
78  self.monitoring = True
79  # FIXME: subscribing to class AnyMsg breaks other subscribers on same node
80  self._subscriber = rospy.Subscriber(self._topic_name, self.message_class, self.message_callback)
81 
82  def stop_monitoring(self):
83  self.monitoring = False
84  self._reset_data()
85  if self._subscriber is not None:
86  self._subscriber.unregister()
87 
88  def message_callback(self, message):
89  ROSTopicHz.callback_hz(self, message)
90  with self.lock:
91  self.timestamps.append(rospy.get_time())
92 
93  # FIXME: this only works for message of class AnyMsg
94  #self.sizes.append(len(message._buff))
95  # time consuming workaround...
96  buff = StringIO()
97  message.serialize(buff)
98 
99  # patch begin
100  pos = buff.tell()
101  buff.seek(0, os.SEEK_END)
102  self.sizes.append(buff.tell())
103  buff.seek(pos)
104  # patch end
105 
106  if len(self.timestamps) > self.window_size - 1:
107  self.timestamps.pop(0)
108  self.sizes.pop(0)
109  assert(len(self.timestamps) == len(self.sizes))
110 
111  self.last_message = message
112 
113  def get_bw(self):
114  if len(self.timestamps) < 2:
115  return None, None, None, None
116  current_time = rospy.get_time()
117  if current_time <= self.timestamps[0]:
118  return None, None, None, None
119 
120  with self.lock:
121  total = sum(self.sizes)
122  bytes_per_s = total / (current_time - self.timestamps[0])
123  mean_size = total / len(self.timestamps)
124  max_size = max(self.sizes)
125  min_size = min(self.sizes)
126  return bytes_per_s, mean_size, min_size, max_size
127 
128  def get_hz(self):
129  if not self.times:
130  return None, None, None, None
131  with self.lock:
132  n = len(self.times)
133  mean = sum(self.times) / n
134  rate = 1. / mean if mean > 0. else 0
135  min_delta = min(self.times)
136  max_delta = max(self.times)
137  return rate, mean, min_delta, max_delta
def message_callback(self, message)
Definition: topic_info.py:88
def __init__(self, topic_name, topic_type)
Definition: topic_info.py:46