class ConsoleDashWidget(IconToolButton):
    """
    A widget which brings up the ROS console.

    :param context: The plugin context to create the monitor in.
    :type context: qt_gui.plugin_context.PluginContext
    """
    def __init__(self, context, icon_paths=None, minimal=True):
        ok_icon = ['bg-green.svg', 'ic-console.svg']
        warn_icon = ['bg-yellow.svg', 'ic-console.svg', 'ol-warn-badge.svg']
        err_icon = ['bg-red.svg', 'ic-console.svg', 'ol-err-badge.svg']
        stale_icon = ['bg-grey.svg', 'ic-console.svg', 'ol-stale-badge.svg']

        icons = [ok_icon, warn_icon, err_icon, stale_icon]

        super(ConsoleDashWidget, self).__init__('Console Widget',
                                                icons,
                                                icon_paths=icon_paths)

        self.minimal = minimal
        self.setFixedSize(self._icons[0].actualSize(QSize(50, 30)))

        self._datamodel = MessageDataModel()
        self._proxymodel = MessageProxyModel()
        self._proxymodel.setSourceModel(self._datamodel)

        self._console = None
        self._rospack = rospkg.RosPack()
        if self._console is None:
            self._console = ConsoleWidget(self._proxymodel,
                                          self._rospack,
                                          minimal=self.minimal)
            self._console.destroyed.connect(self._console_destroyed)

        self._message_queue = []
        self._mutex = QMutex()
        self._subscriber = rospy.Subscriber('/rosout_agg', Log,
                                            self._message_cb)

        self.context = context
        self.clicked.connect(self._show_console)
        self.context.add_widget(self._console)

        self.update_state(0)
        self._timer = QTimer()
        self._timer.timeout.connect(self._insert_messages)
        self._timer.start(100)

        self._console_shown = False
        self.setToolTip("Rosout")

    def _show_console(self):
        if self._console is None:
            self._console = ConsoleWidget(self._proxymodel,
                                          self._rospack,
                                          minimal=self.minimal)
            self._console.destroyed.connect(self._console_destroyed)
        try:
            if self._console_shown:
                self.context.remove_widget(self._console)
                self._console_shown = not self._console_shown
            else:
                self.context.add_widget(self._console)
                self._console_shown = not self._console_shown
        except Exception:
            self._console_shown = not self._console_shown
            self._show_console()

    def _insert_messages(self):
        with QMutexLocker(self._mutex):
            msgs = self._message_queue
            self._message_queue = []
        if msgs:
            self._datamodel.insert_rows(msgs)

        # The console may not yet be initialized or may have been closed
        # So fail silently
        try:
            self.update_rosout()
        except:
            pass

    def _message_cb(self, log_msg):
        if not self._console._paused:
            msg = Console.convert_rosgraph_log_message(log_msg)
            with QMutexLocker(self._mutex):
                self._message_queue.append(msg)

    def update_rosout(self):
        summary_dur = 30.0
        if (rospy.get_time() < 30.0):
            summary_dur = rospy.get_time() - 1.0

        if (summary_dur < 0):
            summary_dur = 0.0

        summary = self._console.get_message_summary(summary_dur)

        if (summary.fatal or summary.error):
            self.update_state(2)
        elif (summary.warn):
            self.update_state(1)
        else:
            self.update_state(0)

        tooltip = ""
        if (summary.fatal):
            tooltip += "\nFatal: %s" % (summary.fatal)
        if (summary.error):
            tooltip += "\nError: %s" % (summary.error)
        if (summary.warn):
            tooltip += "\nWarn: %s" % (summary.warn)
        if (summary.info):
            tooltip += "\nInfo: %s" % (summary.info)
        if (summary.debug):
            tooltip += "\nDebug: %s" % (summary.debug)

        if (len(tooltip) == 0):
            tooltip = "Rosout: no recent activity"
        else:
            tooltip = "Rosout: recent activity:" + tooltip

        if tooltip != self.toolTip():
            self.setToolTip(tooltip)

    def _console_destroyed(self):
        if self._console:
            self._console.cleanup_browsers_on_close()
        self._console = None

    def shutdown_widget(self):
        if self._console:
            self._console.cleanup_browsers_on_close()
        if self._subscriber:
            self._subscriber.unregister()
        self._timer.stop()

    def save_settings(self, plugin_settings, instance_settings):
        self._console.save_settings(plugin_settings, instance_settings)

    def restore_settings(self, plugin_settings, instance_settings):
        self._console.restore_settings(plugin_settings, instance_settings)
예제 #2
0
class Console(Plugin):

    """
    rqt_console plugin's main class. Handles communication with ros_gui and contains
    callbacks to handle incoming message
    """

    def __init__(self, context):
        """
        :param context: plugin context hook to enable adding widgets as a ROS_GUI pane,
                        ''PluginContext''
        """
        super(Console, self).__init__(context)
        self.setObjectName('Console')

        self._context = context
        self._model = MessageDataModel()
        self._proxy_model = MessageProxyModel()
        self._proxy_model.setSourceModel(self._model)

        self._widget = ConsoleWidget(self._proxy_model)
        if context.serial_number() > 1:
            self._widget.setWindowTitle(
                self._widget.windowTitle() + (' (%d)' % context.serial_number()))
        context.add_widget(self._widget)

        # queue to store incoming data which get flushed periodically to the model
        # required since QSortProxyModel can not handle a high insert rate
        self._message_queue = []
        self._mutex = QMutex()
        self._timer = QTimer()
        self._timer.timeout.connect(self.insert_messages)
        self._timer.start(100)

        self._subscriber = None
        self._topic = '/rosout'
        self._subscribe(self._topic)

    def queue_message(self, log_msg):
        """
        Callback for adding an incomming message to the queue.
        """
        if not self._widget._paused:
            msg = Console.convert_rosgraph_log_message(log_msg)
            with QMutexLocker(self._mutex):
                self._message_queue.append(msg)

    @staticmethod
    def convert_rosgraph_log_message(log_msg):
        msg = Message()
        msg.set_stamp_format('hh:mm:ss.ZZZ (yyyy-MM-dd)')
        msg.stamp = (log_msg.stamp.sec, log_msg.stamp.nanosec)
        msg.message = log_msg.msg
        msg.severity = log_msg.level
        msg.node = log_msg.name
        msg.location = log_msg.file + ':' + log_msg.function + ':' + str(log_msg.line)
        return msg

    def insert_messages(self):
        """
        Callback for flushing incoming Log messages from the queue to the model.
        """
        with QMutexLocker(self._mutex):
            msgs = self._message_queue
            self._message_queue = []
        if msgs:
            self._model.insert_rows(msgs)

    def shutdown_plugin(self):
        self._context.node.destroy_subscription(self._subscriber)
        self._timer.stop()
        self._widget.cleanup_browsers_on_close()

    def save_settings(self, plugin_settings, instance_settings):
        self._widget.save_settings(plugin_settings, instance_settings)

    def restore_settings(self, plugin_settings, instance_settings):
        self._widget.restore_settings(plugin_settings, instance_settings)

    def trigger_configuration(self):
        topics = sorted([
            topic_name for topic_name, topic_types
            in self._context.node.get_topic_names_and_types()
            if 'rcl_interfaces/msg/Log' in topic_types
        ])

        dialog = ConsoleSettingsDialog(topics)
        (topic, message_limit) = dialog.query(self._topic, self._model.get_message_limit())
        if topic != self._topic:
            self._subscribe(topic)
        if message_limit != self._model.get_message_limit():
            self._model.set_message_limit(message_limit)

    def _subscribe(self, topic):
        if self._subscriber:
            self._context.node.destroy_subscription(self._subscriber)
        self._subscriber = self._context.node.create_subscription(
            Log, topic, self.queue_message, qos_profile_system_default
        )
        self._currenttopic = topic
예제 #3
0
class PluginLogManager(Plugin):
    """
    rqt_console plugin's main class. Handles communication with ros_gui and contains
    callbacks to handle incoming message
    """
    def __init__(self, context):
        Plugin.__init__(self, context)

    def onCreate(self, param):

        layout = QGridLayout(self)
        layout.setContentsMargins(2, 2, 2, 2)

        self._rospack = rospkg.RosPack()

        self._model = MessageDataModel()
        self._proxy_model = MessageProxyModel()
        self._proxy_model.setSourceModel(self._model)

        self.__widget = ConsoleWidget(self._proxy_model, self._rospack)

        layout.addWidget(self.__widget, 0, 0, 0, 0)

        # queue to store incoming data which get flushed periodically to the model
        # required since QSortProxyModel can not handle a high insert rate
        self._message_queue = []
        self._mutex = QMutex()
        self._timer = QTimer()
        self._timer.timeout.connect(self.insert_messages)
        self._timer.start(100)

        self._subscriber = None
        self._topic = '/rosout_agg'
        self._subscribe(self._topic)

    def queue_message(self, log_msg):
        """
        Callback for adding an incomming message to the queue.
        """
        if not self.__widget._paused:
            msg = PluginLogManager.convert_rosgraph_log_message(log_msg)
            with QMutexLocker(self._mutex):
                self._message_queue.append(msg)

    @staticmethod
    def convert_rosgraph_log_message(log_msg):
        msg = Message()
        msg.set_stamp_format('hh:mm:ss.ZZZ (yyyy-MM-dd)')
        msg.message = log_msg.msg
        msg.severity = log_msg.level
        msg.node = log_msg.name
        msg.stamp = (log_msg.header.stamp.secs, log_msg.header.stamp.nsecs)
        msg.topics = sorted(log_msg.topics)
        msg.location = log_msg.file + ':' + log_msg.function + ':' + str(
            log_msg.line)
        return msg

    def insert_messages(self):
        """
        Callback for flushing incoming Log messages from the queue to the model.
        """
        with QMutexLocker(self._mutex):
            msgs = self._message_queue
            self._message_queue = []
        if msgs:
            self._model.insert_rows(msgs)

    def shutdown_plugin(self):
        self._subscriber.unregister()
        self._timer.stop()
        self.__widget.cleanup_browsers_on_close()

    def save_settings(self, plugin_settings, instance_settings):
        self.__widget.save_settings(plugin_settings, instance_settings)

    def restore_settings(self, plugin_settings, instance_settings):
        self.__widget.restore_settings(plugin_settings, instance_settings)

    def trigger_configuration(self):
        topics = [
            t for t in rospy.get_published_topics()
            if t[1] == 'rosgraph_msgs/Log'
        ]
        topics.sort(key=lambda tup: tup[0])
        dialog = ConsoleSettingsDialog(topics, self._rospack)
        (topic, message_limit) = dialog.query(self._topic,
                                              self._model.get_message_limit())
        if topic != self._topic:
            self._subscribe(topic)
        if message_limit != self._model.get_message_limit():
            self._model.set_message_limit(message_limit)

    def _subscribe(self, topic):
        if self._subscriber:
            self._subscriber.unregister()
        self._subscriber = rospy.Subscriber(topic, Log, self.queue_message)
        self._currenttopic = topic

    def onStart(self):
        pass

    def onPause(self):
        pass

    def onResume(self):
        pass

    def onControlModeChanged(self, mode):

        if mode == ControlMode.AUTOMATIC:
            self.setEnabled(False)
        else:
            self.setEnabled(True)

    def onUserChanged(self, user_info):
        pass

    def onTranslate(self, lng):
        pass

    def onEmergencyStop(self, state):
        pass

    def onDestroy(self):
        self.shutdown_plugin()
class ConsoleDashWidget(IconToolButton):
    """
    A widget which brings up the ROS console.

    :param context: The plugin context to create the monitor in.
    :type context: qt_gui.plugin_context.PluginContext
    """
    def __init__(self, context, icon_paths=None, minimal=True):
        ok_icon = ['bg-green.svg', 'ic-console.svg']
        warn_icon = ['bg-yellow.svg', 'ic-console.svg', 'ol-warn-badge.svg']
        err_icon = ['bg-red.svg', 'ic-console.svg', 'ol-err-badge.svg']
        stale_icon = ['bg-grey.svg', 'ic-console.svg', 'ol-stale-badge.svg']

        icons = [ok_icon, warn_icon, err_icon, stale_icon]

        super(ConsoleDashWidget, self).__init__('Console Widget', icons, icon_paths=icon_paths)

        self.minimal = minimal
        self.setFixedSize(self._icons[0].actualSize(QSize(50, 30)))

        self._datamodel = MessageDataModel()
        self._proxymodel = MessageProxyModel()
        self._proxymodel.setSourceModel(self._datamodel)

        self._message_queue = []
        self._mutex = QMutex()
        self._subscriber = rospy.Subscriber('/rosout_agg', Log, self._message_cb)

        self._console = None
        self.context = context
        self.clicked.connect(self._show_console)

        self.update_state(0)
        self._timer = QTimer()
        self._timer.timeout.connect(self._insert_messages)
        self._timer.start(100)

        self._rospack = rospkg.RosPack()
        if self._console is None:
            self._console = ConsoleWidget(self._proxymodel, self._rospack, minimal=self.minimal)
            self._console.destroyed.connect(self._console_destroyed)
        self._console_shown = False
        self.setToolTip("Rosout")

    def _show_console(self):
        if self._console is None:
            self._console = ConsoleWidget(self._proxymodel, self._rospack, minimal=self.minimal)
            self._console.destroyed.connect(self._console_destroyed)
        try:
            if self._console_shown:
                self.context.remove_widget(self._console)
                self._console_shown = not self._console_shown
            else:
                self.context.add_widget(self._console)
                self._console_shown = not self._console_shown
        except Exception:
            self._console_shown = not self._console_shown
            self._show_console()

    def _insert_messages(self):
        with QMutexLocker(self._mutex):
            msgs = self._message_queue
            self._message_queue = []
        if msgs:
            self._datamodel.insert_rows(msgs)

        # The console may not yet be initialized or may have been closed
        # So fail silently
        try:
            self.update_rosout()
        except:
            pass

    def _message_cb(self, log_msg):
        if not self._console._paused:
            msg = Console.convert_rosgraph_log_message(log_msg)
            with QMutexLocker(self._mutex):
                self._message_queue.append(msg)

    def update_rosout(self):
        summary_dur = 30.0
        if (rospy.get_time() < 30.0):
            summary_dur = rospy.get_time() - 1.0

        if (summary_dur < 0):
            summary_dur = 0.0

        summary = self._console.get_message_summary(summary_dur)

        if (summary.fatal or summary.error):
            self.update_state(2)
        elif (summary.warn):
            self.update_state(1)
        else:
            self.update_state(0)

        tooltip = ""
        if (summary.fatal):
            tooltip += "\nFatal: %s" % (summary.fatal)
        if (summary.error):
            tooltip += "\nError: %s" % (summary.error)
        if (summary.warn):
            tooltip += "\nWarn: %s" % (summary.warn)
        if (summary.info):
            tooltip += "\nInfo: %s" % (summary.info)
        if (summary.debug):
            tooltip += "\nDebug: %s" % (summary.debug)

        if (len(tooltip) == 0):
            tooltip = "Rosout: no recent activity"
        else:
            tooltip = "Rosout: recent activity:" + tooltip

        if tooltip != self.toolTip():
            self.setToolTip(tooltip)

    def _console_destroyed(self):
        if self._console:
            self._console.cleanup_browsers_on_close()
        self._console = None

    def shutdown_widget(self):
        if self._console:
            self._console.cleanup_browsers_on_close()
        if self._subscriber:
            self._subscriber.unregister()
        self._timer.stop()

    def save_settings(self, plugin_settings, instance_settings):
        self._console.save_settings(plugin_settings, instance_settings)

    def restore_settings(self, plugin_settings, instance_settings):
        self._console.restore_settings(plugin_settings, instance_settings)