util_robot_monitor.py
Go to the documentation of this file.
00001 # Software License Agreement (BSD License)
00002 #
00003 # Copyright (c) 2012, Willow Garage, Inc.
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 Willow Garage, Inc. 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 OWNER 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 # Author: Isaac Saito, Ze'ev Klapow
00034 
00035 from diagnostic_msgs.msg import DiagnosticStatus
00036 from python_qt_binding.QtGui import QColor, QIcon
00037 import rospy
00038 
00039 
00040 class Util(object):
00041     # TODO: Utils and common configs are mixed in this class.
00042 
00043     SECONDS_TIMELINE = 30
00044 
00045     # Instantiating icons that show the device status.
00046     _ERR_ICON = QIcon.fromTheme('dialog-error')
00047     _WARN_ICON = QIcon.fromTheme('dialog-warning')
00048     _OK_ICON = QIcon.fromTheme('emblem-default')
00049     # Added following this QA thread http://goo.gl/83tVZ
00050     _STALE_ICON = QIcon.fromTheme('dialog-question')
00051 
00052     IMG_DICT = {0: _OK_ICON, 1: _WARN_ICON, 2: _ERR_ICON, 3: _STALE_ICON}
00053 
00054     COLOR_DICT = {0: QColor(85, 178, 76),
00055                    1: QColor(222, 213, 17),
00056                    2: QColor(178, 23, 46),
00057                    3: QColor(40, 23, 176)
00058                    }
00059     # DiagnosticStatus dosn't have Stale status. Related QA:http://goo.gl/83tVZ
00060     # It's not ideal to add STALE to DiagnosticStatus as you see in that thread
00061     # but here this addition is only temporary for the purpose of
00062     # implementation simplicity.
00063     DiagnosticStatus.STALE = 3
00064 
00065     _DICTKEY_TIMES_ERROR = 'times_errors'
00066     _DICTKEY_TIMES_WARN = 'times_warnings'
00067     _DICTKEY_INDEX = 'index'
00068     _DICTKEY_STATITEM = 'statitem'
00069 
00070     def __init__(self):
00071         super(Util, self).__init__()
00072 
00073     @staticmethod
00074     def update_status_images(diagnostic_status, statusitem):
00075         """
00076         Taken from robot_monitor.robot_monitor_panel.py.
00077 
00078         :type status: DiagnosticStatus
00079         :type node: StatusItem
00080         :author: Isaac Saito
00081         """
00082 
00083         name = diagnostic_status.name
00084         if (name is not None):
00085             # level = diagnosis_status.level
00086             level = diagnostic_status.level
00087             if (diagnostic_status.level != statusitem.last_level):
00088                 #TODO: Apparently diagnosis_status doesn't contain last_level.
00089                 statusitem.setIcon(0, Util.IMG_DICT[level])
00090                 statusitem.last_level = level
00091                 return
00092 
00093     @staticmethod
00094     def get_grn_resource_name(status_name):
00095         """
00096         :param: status_name is a string that may consists of status names that
00097                 are delimited by slash.
00098         :rtype: str
00099         """
00100         name = status_name.split('/')[-1]
00101         rospy.logdebug(' get_grn_resource_name name = %s', name)
00102         return name
00103 
00104     @staticmethod
00105     def remove_parent_name(status_name):
00106         return ('/'.join(status_name.split('/')[2:])).strip()
00107 
00108     @staticmethod
00109     def get_parent_name(status_name):
00110         return ('/'.join(status_name.split('/')[:-1])).strip()
00111 
00112     @staticmethod
00113     def gen_headline_status_green(diagnostic_status):
00114         return "%s" % Util.get_grn_resource_name(diagnostic_status.name)
00115 
00116     @staticmethod
00117     def gen_headline_warn_or_err(diagnostic_status):
00118         return "%s : %s" % (Util.get_grn_resource_name(diagnostic_status.name),
00119                             diagnostic_status.message)
00120 
00121     @staticmethod
00122     def _get_color_for_message(msg, mode=0):
00123         """
00124         :param msg: Either DiagnosticArray or DiagnosticsStatus.
00125         :param mode: int. When 0, this func will iterate msg to find
00126                      DiagnosticsStatus.level and put it into a dict.
00127                      When 1, this func finds DiagnosticsStatus.level from msg
00128                      without iteration (thus, msg is expected to be
00129                      DiagnosticsStatus instance).
00130         """
00131 
00132         level = 0
00133         min_level = 255
00134 
00135         lookup = {}
00136         for status in msg.status:
00137             lookup[status.name] = status
00138 
00139         names = [status.name for status in msg.status]
00140         names = [name for name in names
00141                  if len(Util.get_parent_name(name)) == 0]
00142         for name in names:
00143             status = lookup[name]
00144             if (status.level > level):
00145                 level = status.level
00146             if (status.level < min_level):
00147                 min_level = status.level
00148 
00149         # Stale items should be reported as errors unless all stale
00150         if (level > 2 and min_level <= 2):
00151             level = 2
00152 
00153         # return Util.IMG_DICT[level]
00154         rospy.logdebug(' get_color_for_message color lv=%d', level)
00155         return Util.COLOR_DICT[level]
00156 
00157     @staticmethod
00158     def get_correspondent(key, list_statitem):
00159         """
00160 
00161         :type key: String.
00162         :type list_statitem: DiagnosticsStatus
00163         :rtype: StatusItem
00164         """
00165         names_from_list = [Util.get_grn_resource_name(status.name)
00166                            for status in list_statitem]
00167         key_niced = Util.get_grn_resource_name(key)
00168         index_key = -1
00169         statitem_key = None
00170         if key_niced in names_from_list:
00171             index_key = names_from_list.index(key_niced)
00172             statitem_key = list_statitem[index_key]
00173             rospy.logdebug(' get_correspondent index_key=%s statitem_key=%s',
00174                           index_key, statitem_key)
00175         return {Util._DICTKEY_INDEX: index_key,
00176                 Util._DICTKEY_STATITEM: statitem_key}
00177 
00178     @staticmethod
00179     def get_children(name, diag_array):
00180         """
00181 
00182         :type msg: DiagnosticArray
00183         :rtype: DiagnosticStatus[]
00184         """
00185 
00186         ret = []
00187         for k in diag_array.status:  # k is DiagnosticStatus.
00188             if k.name.startswith(name):  # Starting with self.name means k
00189                                         # is either top/parent node / its child
00190                 if not k.name == name:  # Child's name must be different
00191                                             # from that of the top/parent node.
00192                     ret.append(k)
00193         return ret


rqt_robot_monitor
Author(s): Isaac Saito, Ze'ev Klapow, Kevin Watts, Josh Faust
autogenerated on Mon Oct 6 2014 07:16:09