topic_info.py
Go to the documentation of this file.
00001 #!/usr/bin/env python
00002 
00003 # Copyright (c) 2011, Dorian Scholz, TU Darmstadt
00004 # All rights reserved.
00005 #
00006 # Redistribution and use in source and binary forms, with or without
00007 # modification, are permitted provided that the following conditions
00008 # are met:
00009 #
00010 #   * Redistributions of source code must retain the above copyright
00011 #     notice, this list of conditions and the following disclaimer.
00012 #   * Redistributions in binary form must reproduce the above
00013 #     copyright notice, this list of conditions and the following
00014 #     disclaimer in the documentation and/or other materials provided
00015 #     with the distribution.
00016 #   * Neither the name of the TU Darmstadt nor the names of its
00017 #     contributors may be used to endorse or promote products derived
00018 #     from this software without specific prior written permission.
00019 #
00020 # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
00021 # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
00022 # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
00023 # FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
00024 # COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
00025 # INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
00026 # BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
00027 # LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
00028 # CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
00029 # LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
00030 # ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
00031 # POSSIBILITY OF SUCH DAMAGE.
00032 
00033 from __future__ import division, with_statement
00034 from StringIO import StringIO
00035 
00036 from python_qt_binding.QtCore import qWarning
00037 
00038 import roslib
00039 import rospy
00040 from rostopic import ROSTopicHz
00041 
00042 
00043 class TopicInfo(ROSTopicHz):
00044 
00045     def __init__(self, topic_name, topic_type):
00046         super(TopicInfo, self).__init__(100)
00047         self._topic_name = topic_name
00048         self.error = None
00049         self._subscriber = None
00050         self.monitoring = False
00051         self._reset_data()
00052         self.message_class = None
00053         try:
00054             self.message_class = roslib.message.get_message_class(topic_type)
00055         except Exception as e:
00056             self.message_class = None
00057             qWarning('TopicInfo.__init__(): %s' % (e))
00058 
00059         if self.message_class is None:
00060             self.error = 'can not get message class for type "%s"' % topic_type
00061             qWarning('TopicInfo.__init__(): topic "%s": %s' % (topic_name, self.error))
00062 
00063     def _reset_data(self):
00064         self.last_message = None
00065         self.times = []
00066         self.timestamps = []
00067         self.sizes = []
00068 
00069     def toggle_monitoring(self):
00070         if self.monitoring:
00071             self.stop_monitoring()
00072         else:
00073             self.start_monitoring()
00074 
00075     def start_monitoring(self):
00076         if self.message_class is not None:
00077             self.monitoring = True
00078             # FIXME: subscribing to class AnyMsg breaks other subscribers on same node
00079             self._subscriber = rospy.Subscriber(self._topic_name, self.message_class, self.message_callback)
00080 
00081     def stop_monitoring(self):
00082         self.monitoring = False
00083         self._reset_data()
00084         if self._subscriber is not None:
00085             self._subscriber.unregister()
00086 
00087     def message_callback(self, message):
00088         ROSTopicHz.callback_hz(self, message)
00089         with self.lock:
00090             self.timestamps.append(rospy.get_time())
00091 
00092             # FIXME: this only works for message of class AnyMsg
00093             #self.sizes.append(len(message._buff))
00094             # time consuming workaround...
00095             buff = StringIO()
00096             message.serialize(buff)
00097             self.sizes.append(buff.len)
00098 
00099             if len(self.timestamps) > self.window_size - 1:
00100                 self.timestamps.pop(0)
00101                 self.sizes.pop(0)
00102             assert(len(self.timestamps) == len(self.sizes))
00103 
00104             self.last_message = message
00105 
00106     def get_bw(self):
00107         if len(self.timestamps) < 2:
00108             return None, None, None, None
00109         with self.lock:
00110             total = sum(self.sizes)
00111             bytes_per_s = total / (rospy.get_time() - self.timestamps[0])
00112             mean_size = total / len(self.timestamps)
00113             max_size = max(self.sizes)
00114             min_size = min(self.sizes)
00115             return bytes_per_s, mean_size, min_size, max_size
00116 
00117     def get_hz(self):
00118         if not self.times:
00119             return None, None, None, None
00120         with self.lock:
00121             n = len(self.times)
00122             mean = sum(self.times) / n
00123             rate = 1. / mean if mean > 0. else 0
00124             min_delta = min(self.times)
00125             max_delta = max(self.times)
00126         return rate, mean, min_delta, max_delta


rqt_topic
Author(s): Dorian Scholz
autogenerated on Mon Oct 6 2014 07:15:42