def __init__(self, parent=None, logger=Logger()):
        QWidgetWithLogger.__init__(self, parent, logger)

        # start widget
        hbox = QHBoxLayout()
        hbox.setMargin(0)
        hbox.setContentsMargins(0, 0, 0, 0)

        # get system icon
        icon = QIcon.fromTheme("view-refresh")
        size = icon.actualSize(QSize(32, 32))

        # add combo box
        self.parameter_set_names_combo_box = QComboBox()
        self.parameter_set_names_combo_box.currentIndexChanged[str].connect(
            self.param_changed)
        hbox.addWidget(self.parameter_set_names_combo_box)

        # add refresh button
        self.get_all_parameter_set_names_button = QPushButton()
        self.get_all_parameter_set_names_button.clicked.connect(
            self._get_all_parameter_set_names)

        self.get_all_parameter_set_names_button.setIcon(icon)
        self.get_all_parameter_set_names_button.setFixedSize(
            size.width() + 2,
            size.height() + 2)

        hbox.addWidget(self.get_all_parameter_set_names_button)

        # end widget
        self.setLayout(hbox)

        # init widget
        self.reset_parameter_set_selection()
Example #2
0
    def create_button(self):
        # self.data is a dictionary name-->array[positions]
        if self.side == PoseLoader.LEFT:
            self.data = self.arm_db.getAllLeftPos()
        else:  # self.side == PoseLoader.RIGHT:
            self.data = self.arm_db.getAllRightPos()

        combo_box = QComboBox()
        for key in self.data.keys():
            combo_box.addItem(key, self.data.get(key))
        return combo_box
Example #3
0
 def create_button(self):
     # self.data is a dictionary name-->array[positions]
     if self.side == PoseLoader.LEFT:
         self.data = self.arm_db.getAllLeftPos()
     else: # self.side == PoseLoader.RIGHT:
         self.data = self.arm_db.getAllRightPos()
     
     combo_box = QComboBox()
     for key in self.data.keys():
         combo_box.addItem(key, self.data.get(key))
     return combo_box
    def __init__(self, parent=None):
        QDialog.__init__(self, parent)
        self.setWindowTitle('Select Binary')
        self.verticalLayout = QVBoxLayout(self)
        self.verticalLayout.setObjectName("verticalLayout")

        self.content = QWidget()
        self.contentLayout = QFormLayout(self.content)
        self.contentLayout.setVerticalSpacing(0)
        self.verticalLayout.addWidget(self.content)

        self.packages = None

        package_label = QLabel("Package:", self.content)
        self.package_field = QComboBox(self.content)
        self.package_field.setInsertPolicy(QComboBox.InsertAlphabetically)
        self.package_field.setSizePolicy(QSizePolicy(QSizePolicy.Expanding, QSizePolicy.Fixed))
        self.package_field.setEditable(True)
        self.contentLayout.addRow(package_label, self.package_field)
        binary_label = QLabel("Binary:", self.content)
        self.binary_field = QComboBox(self.content)
#    self.binary_field.setSizeAdjustPolicy(QComboBox.AdjustToContents)
        self.binary_field.setSizePolicy(QSizePolicy(QSizePolicy.Expanding, QSizePolicy.Fixed))
        self.binary_field.setEditable(True)
        self.contentLayout.addRow(binary_label, self.binary_field)

        self.buttonBox = QDialogButtonBox(self)
        self.buttonBox.setStandardButtons(QDialogButtonBox.Ok | QDialogButtonBox.Cancel)
        self.buttonBox.setOrientation(Qt.Horizontal)
        self.buttonBox.setObjectName("buttonBox")
        self.verticalLayout.addWidget(self.buttonBox)

        self.package_field.setFocus(Qt.TabFocusReason)
        self.package = ''
        self.binary = ''

        if self.packages is None:
            self.package_field.addItems(['packages searching...'])
            self.package_field.setCurrentIndex(0)
            self._fill_packages_thread = PackagesThread()
            self._fill_packages_thread.packages.connect(self._fill_packages)
            self._fill_packages_thread.start()

        self.buttonBox.accepted.connect(self.accept)
        self.buttonBox.rejected.connect(self.reject)
        QMetaObject.connectSlotsByName(self)
        self.package_field.activated[str].connect(self.on_package_selected)
        if hasattr(self.package_field, "textChanged"):  # qt compatibility
            self.package_field.textChanged.connect(self.on_package_selected)
            self.binary_field.textChanged.connect(self.on_binary_selected)
        else:
            self.package_field.editTextChanged.connect(self.on_package_selected)
            self.binary_field.editTextChanged.connect(self.on_binary_selected)
    def __init__(self, host, masteruri=None, parent=None):
        PackageDialog.__init__(self, parent)
        self.host = host
        self.setWindowTitle('Run')

        ns_name_label = QLabel("NS/Name:", self.content)
        self.ns_field = QComboBox(self.content)
        self.ns_field.setSizePolicy(QSizePolicy(QSizePolicy.Expanding, QSizePolicy.Fixed))
        self.ns_field.setEditable(True)
        ns_history = nm.history().cachedParamValues('run_dialog/NS')
        ns_history.insert(0, '/')
        self.ns_field.addItems(ns_history)
        self.name_field = QLineEdit(self.content)
        self.name_field.setEnabled(False)
        horizontalLayout = QHBoxLayout()
        horizontalLayout.addWidget(self.ns_field)
        horizontalLayout.addWidget(self.name_field)
        self.contentLayout.addRow(ns_name_label, horizontalLayout)
        args_label = QLabel("Args:", self.content)
        self.args_field = QComboBox(self.content)
        self.args_field.setSizeAdjustPolicy(QComboBox.AdjustToMinimumContentsLength)
        self.args_field.setSizePolicy(QSizePolicy(QSizePolicy.Expanding, QSizePolicy.Fixed))
        self.args_field.setEditable(True)
        self.contentLayout.addRow(args_label, self.args_field)
        args_history = nm.history().cachedParamValues('run_dialog/Args')
        args_history.insert(0, '')
        self.args_field.addItems(args_history)

        host_label = QLabel("Host:", self.content)
        self.host_field = QComboBox(self.content)
#    self.host_field.setSizeAdjustPolicy(QComboBox.AdjustToContents)
        self.host_field.setSizePolicy(QSizePolicy(QSizePolicy.Expanding, QSizePolicy.Fixed))
        self.host_field.setEditable(True)
        host_label.setBuddy(self.host_field)
        self.contentLayout.addRow(host_label, self.host_field)
        self.host_history = host_history = nm.history().cachedParamValues('/Host')
        if self.host in host_history:
            host_history.remove(self.host)
        host_history.insert(0, self.host)
        self.host_field.addItems(host_history)

        master_label = QLabel("ROS Master URI:", self.content)
        self.master_field = QComboBox(self.content)
        self.master_field.setSizePolicy(QSizePolicy(QSizePolicy.Expanding, QSizePolicy.Fixed))
        self.master_field.setEditable(True)
        master_label.setBuddy(self.host_field)
        self.contentLayout.addRow(master_label, self.master_field)
        self.master_history = master_history = nm.history().cachedParamValues('/Optional Parameter/ROS Master URI')
        self.masteruri = "ROS_MASTER_URI" if masteruri is None else masteruri
        if self.masteruri in master_history:
            master_history.remove(self.masteruri)
        master_history.insert(0, self.masteruri)
        self.master_field.addItems(master_history)

#    self.package_field.setFocus(QtCore.Qt.TabFocusReason)
        if hasattr(self.package_field, "textChanged"):  # qt compatibility
            self.package_field.textChanged.connect(self.on_package_selected)
        else:
            self.package_field.editTextChanged.connect(self.on_package_selected)
        self.binary_field.activated[str].connect(self.on_binary_selected)
 def _handle_operator_name_change(self, operatorName, combo):
     self.operatorView.clear()
     root = self.operatorView.invisibleRootItem()
     for i in range(len(self._parameter_label_list[operatorName])):
         # fetch types for combo box
         cmb = QComboBox()
         instance_client = rospy.ServiceProxy('/kcl_rosplan/get_current_instances', GetInstanceService)
         resp = instance_client(self._parameter_type_list[operatorName][i])
         for instancename in resp.instances:
             cmb.addItem(instancename,instancename)
         # create row
         item = QTreeWidgetItem(self.operatorView)
         item.setText(0, self._parameter_label_list[operatorName][i])
         item.setText(1, self._parameter_type_list[operatorName][i])
         self.operatorView.setItemWidget(item, 2, cmb)
 def _handle_operator_name_change(self, operatorName, combo):
     self.operatorView.clear()
     root = self.operatorView.invisibleRootItem()
     for i in range(len(self._parameter_label_list[operatorName])):
         # fetch types for combo box
         cmb = QComboBox()
         instance_client = rospy.ServiceProxy('/kcl_rosplan/get_current_instances', GetInstanceService)
         resp = instance_client(self._parameter_type_list[operatorName][i])
         for instancename in resp.instances:
             cmb.addItem(instancename,instancename)
         # create row
         item = QTreeWidgetItem(self.operatorView)
         item.setText(0, self._parameter_label_list[operatorName][i])
         item.setText(1, self._parameter_type_list[operatorName][i])
         self.operatorView.setItemWidget(item, 2, cmb)
Example #8
0
 def createEditor(self, parent, option, index):
     '''
     Creates a editor in the TreeView depending on type of the settings data.
     '''
     item = self._itemFromIndex(index)
     if item.edit_type() == SettingsValueItem.EDIT_TYPE_AUTODETECT:
         if isinstance(item.value(), bool):
             box = QCheckBox(parent)
             box.setFocusPolicy(Qt.StrongFocus)
             box.setAutoFillBackground(True)
             box.stateChanged.connect(self.edit_finished)
             return box
         elif isinstance(item.value(), int):
             box = QSpinBox(parent)
             box.setValue(item.value())
             if not item.value_min() is None:
                 box.setMinimum(item.value_min())
             if not item.value_max() is None:
                 box.setMaximum(item.value_max())
             return box
     elif item.edit_type() == SettingsValueItem.EDIT_TYPE_FOLDER:
         editor = PathEditor(item.value(), parent)
         editor.editing_finished_signal.connect(self.edit_finished)
         return editor
     elif item.edit_type() == SettingsValueItem.EDIT_TYPE_LIST:
         box = QComboBox(parent)
         box.addItems(item.value_list())
         index = box.findText(item.value())
         if index >= 0:
             box.setCurrentIndex(index)
         box.setEditable(False)
         return box
     return QStyledItemDelegate.createEditor(self, parent, option, index)
    def __init__(self, parent = None, logger = Logger()):
        QWidgetWithLogger.__init__(self, parent, logger)

        # start widget
        hbox = QHBoxLayout()
        hbox.setMargin(0)
        hbox.setContentsMargins(0, 0, 0, 0)

        # get system icon
        icon = QIcon.fromTheme("view-refresh")
        size = icon.actualSize(QSize(32, 32))

        # add combo box
        self.parameter_set_names_combo_box = QComboBox()
        self.parameter_set_names_combo_box.currentIndexChanged[str].connect(self.param_changed)
        hbox.addWidget(self.parameter_set_names_combo_box)

        # add refresh button
        self.get_all_parameter_set_names_button = QPushButton()
        self.get_all_parameter_set_names_button.clicked.connect(self._get_all_parameter_set_names)

        self.get_all_parameter_set_names_button.setIcon(icon)
        self.get_all_parameter_set_names_button.setFixedSize(size.width()+2, size.height()+2)

        hbox.addWidget(self.get_all_parameter_set_names_button)

        # end widget
        self.setLayout(hbox)

        # init widget
        self.reset_parameter_set_selection()
Example #10
0
    def __init__(self, context):
        super(RoomDialogPlugin, self).__init__(context)
        # Give QObjects reasonable names
        self.setObjectName('RoomDialogPlugin')

        font_size = rospy.get_param("~font_size", 30)

        # Create QWidget
        self._widget = QWidget()
        self._widget.setFont(QFont("Times", font_size, QFont.Bold))
        self._layout = QVBoxLayout(self._widget)
        self._text_browser = QTextBrowser(self._widget)
        self._layout.addWidget(self._text_browser)
        self._button_layout = QGridLayout()
        self._layout.addLayout(self._button_layout)
        #        rospy.loginfo("Hello world")

        # Add combobox
        self._cb_layout = QHBoxLayout()
        self._cb = QComboBox()
        self._layout.addLayout(self._cb_layout)

        #layout = QVBoxLayout(self._widget)
        #layout.addWidget(self._button)
        self._widget.setObjectName('RoomDialogPluginUI')
        if context.serial_number() > 1:
            self._widget.setWindowTitle(self._widget.windowTitle() +
                                        (' (%d)' % context.serial_number()))
        context.add_widget(self._widget)

        # Setup service provider
        self.service = rospy.Service('room_dialog', RoomDialog,
                                     self.service_callback)
        self.response_ready = False
        self.response = None
        self.buttons = []
        self.text_label = None
        self.text_input = None

        # Add combo options

        self.connect(self._widget, SIGNAL("update"), self.update)
        self.connect(self._widget, SIGNAL("timeout"), self.timeout)
 def __init__(self, parent=None):
     super(ComboBoxDialog, self).__init__()
     self.number = 0
     vbox = QtGui.QVBoxLayout(self)
     self.combo_box = QComboBox(self)
     self.combo_box.activated.connect(self.onActivated)
     vbox.addWidget(self.combo_box)
     button = QPushButton()
     button.setText("Done")
     button.clicked.connect(self.buttonCallback)
     vbox.addWidget(button)
     self.setLayout(vbox)
    def __init__(self, parent=None, topic_type=str(), is_action_topic=False):
        QWidget.__init__(self, parent)

        if is_action_topic:
            self.topic_type = topic_type + "Goal"
        else:
            self.topic_type = topic_type
        self.is_action_topic = is_action_topic

        # start widget
        hbox = QHBoxLayout()
        hbox.setMargin(0)
        hbox.setContentsMargins(0, 0, 0, 0)

        # topic combo box
        self.topic_combo_box = QComboBox()
        self.topic_combo_box.setEnabled(False)
        self.topic_combo_box.blockSignals(True)
        self.topic_combo_box.setValidator(
            QRegExpValidator(QRegExp('((\d|\w|/)(?!//))*'), self))
        self.topic_combo_box.currentIndexChanged[str].connect(
            self.topic_changed)
        hbox.addWidget(self.topic_combo_box)

        # get system icon
        icon = QIcon.fromTheme("view-refresh")
        size = icon.actualSize(QSize(32, 32))

        # add refresh button
        refresh_topics_button = QPushButton()
        refresh_topics_button.clicked.connect(self.update_topic_list)
        refresh_topics_button.setIcon(icon)
        refresh_topics_button.setFixedSize(size.width() + 2, size.height() + 2)
        hbox.addWidget(refresh_topics_button)

        # end widget
        self.setLayout(hbox)

        # init widget
        self.update_topic_list()
Example #13
0
    def setup(self, context):
        self.name = 'NAO Dashboard (%s)'%rosenv.get_master_uri()
        self.max_icon_size = QSize(50, 30)
        self.message = None

        self._dashboard_message = None
        self._last_dashboard_message_time = 0.0

        self._raw_byte = None
        self.digital_outs = [0, 0, 0]

        icons_path = path.join(roslib.packages.get_pkg_dir('nao_dashboard'), "icons/")

        self._robot_combobox = QComboBox()
        self._robot_combobox.setSizeAdjustPolicy(QComboBox.AdjustToContents)
        self._robot_combobox.setInsertPolicy(QComboBox.InsertAlphabetically)
        self._robot_combobox.setEditable(True)

        gobject.threads_init()
        dbus.glib.threads_init()
        self.robots = []
        self.sys_bus = dbus.SystemBus()
        self.avahi_server = dbus.Interface(self.sys_bus.get_object(avahi.DBUS_NAME, '/'), avahi.DBUS_INTERFACE_SERVER)

        self.sbrowser = dbus.Interface(self.sys_bus.get_object(avahi.DBUS_NAME, self.avahi_server.ServiceBrowserNew(avahi.IF_UNSPEC,
            avahi.PROTO_INET, '_naoqi._tcp', 'local', dbus.UInt32(0))), avahi.DBUS_INTERFACE_SERVICE_BROWSER)

        self.sbrowser.connect_to_signal("ItemNew", self.avahiNewItem)
        self.sbrowser.connect_to_signal("ItemRemove", self.avahiItemRemove)

        # Diagnostics
        self._monitor = MonitorDashWidget(self.context)

        # Rosout
        self._console = ConsoleDashWidget(self.context, minimal=False)

        ## Joint temperature
        self._temp_joint_button = StatusControl('Joint temperature', 'temperature_joints')

        ## CPU temperature
        self._temp_head_button = StatusControl('CPU temperature', 'temperature_head')

        ## Motors
        self._motors_button = Motors(self.context)

        ## Battery State
        self._power_state_ctrl = PowerStateControl('NAO Battery')

        self._agg_sub = rospy.Subscriber('diagnostics_agg', DiagnosticArray, self.new_diagnostic_message)
        self._last_dashboard_message_time = 0.0
Example #14
0
    def _update_item(self):
        widget_layout = self.arg_ver_layout
        item_list = self.params_list

        widget_list = widget_layout.parentWidget().children()
        while len(widget_list) > 2:
            added_arg_widget = widget_list.pop()
            widget_layout.removeWidget(added_arg_widget)
            added_arg_widget.setParent(None)
            added_arg_widget.deleteLater()

        #resize
        dialog_widget = widget_layout.parentWidget().parentWidget()
        dialog_widget.resize(dialog_widget.minimumSize())
        for l in item_list:
            params_hor_sub_widget = QWidget()
            params_hor_layout = QHBoxLayout(params_hor_sub_widget)
            for k in l:
                param_name = k[0]
                param_type = k[2]
                name_widget = QLabel(param_name + ": ")
                if param_type == 'string' or param_type == 'int':
                    k[1] = QTextEdit()
                    k[1].setSizePolicy(QSizePolicy.MinimumExpanding,
                                       QSizePolicy.Ignored)
                    k[1].setMinimumSize(0, 30)
                    k[1].append("")
                elif param_type == 'bool':
                    k[1] = QTextEdit()
                    k[1] = QComboBox()
                    k[1].setSizePolicy(QSizePolicy.MinimumExpanding,
                                       QSizePolicy.Ignored)
                    k[1].setMinimumSize(0, 30)

                    k[1].addItem("True", True)
                    k[1].addItem("False", False)

                params_hor_layout.addWidget(name_widget)
                params_hor_layout.addWidget(k[1])
            widget_layout.addWidget(params_hor_sub_widget)
    def __init__(self, parent = None, topic_type = str(), is_action_topic = False):
        QWidget.__init__(self, parent)

        if is_action_topic:
            self.topic_type = topic_type + "Goal"
        else:
            self.topic_type = topic_type
        self.is_action_topic = is_action_topic

        # start widget
        hbox = QHBoxLayout()
        hbox.setMargin(0)
        hbox.setContentsMargins(0, 0, 0, 0)

        # topic combo box
        self.topic_combo_box = QComboBox()
        self.topic_combo_box.setEnabled(False)
        self.topic_combo_box.blockSignals(True)
        self.topic_combo_box.setValidator(QRegExpValidator(QRegExp('((\d|\w|/)(?!//))*'), self))
        self.topic_combo_box.currentIndexChanged[str].connect(self.topic_changed)
        hbox.addWidget(self.topic_combo_box)

        # get system icon
        icon = QIcon.fromTheme("view-refresh")
        size = icon.actualSize(QSize(32, 32))

        # add refresh button
        refresh_topics_button = QPushButton()
        refresh_topics_button.clicked.connect(self.update_topic_list)
        refresh_topics_button.setIcon(icon)
        refresh_topics_button.setFixedSize(size.width()+2, size.height()+2)
        hbox.addWidget(refresh_topics_button)

        # end widget
        self.setLayout(hbox)

        # init widget
        self.update_topic_list()
Example #16
0
class RoomDialogPlugin(Plugin):
    def __init__(self, context):
        super(RoomDialogPlugin, self).__init__(context)
        # Give QObjects reasonable names
        self.setObjectName('RoomDialogPlugin')

        font_size = rospy.get_param("~font_size", 30)

        # Create QWidget
        self._widget = QWidget()
        self._widget.setFont(QFont("Times", font_size, QFont.Bold))
        self._layout = QVBoxLayout(self._widget)
        self._text_browser = QTextBrowser(self._widget)
        self._layout.addWidget(self._text_browser)
        self._button_layout = QGridLayout()
        self._layout.addLayout(self._button_layout)
        #        rospy.loginfo("Hello world")

        # Add combobox
        self._cb_layout = QHBoxLayout()
        self._cb = QComboBox()
        self._layout.addLayout(self._cb_layout)

        #layout = QVBoxLayout(self._widget)
        #layout.addWidget(self._button)
        self._widget.setObjectName('RoomDialogPluginUI')
        if context.serial_number() > 1:
            self._widget.setWindowTitle(self._widget.windowTitle() +
                                        (' (%d)' % context.serial_number()))
        context.add_widget(self._widget)

        # Setup service provider
        self.service = rospy.Service('room_dialog', RoomDialog,
                                     self.service_callback)
        self.response_ready = False
        self.response = None
        self.buttons = []
        self.text_label = None
        self.text_input = None

        # Add combo options

        self.connect(self._widget, SIGNAL("update"), self.update)
        self.connect(self._widget, SIGNAL("timeout"), self.timeout)

    def shutdown_plugin(self):
        self.service.shutdown()

    def service_callback(self, req):
        self.response_ready = False
        self.request = req
        self._widget.emit(SIGNAL("update"))
        # Start timer against wall clock here instead of the ros clock.
        start_time = time.time()
        while not self.response_ready:
            if self.request != req:
                # The request got preempted by a new request.
                return RoomDialogResponse(RoomDialogRequest.PREEMPTED, "")
            if req.timeout != RoomDialogRequest.NO_TIMEOUT:
                current_time = time.time()
                if current_time - start_time > req.timeout:
                    self._widget.emit(SIGNAL("timeout"))
                    return RoomDialogResponse(RoomDialogRequest.TIMED_OUT, "")
            time.sleep(0.2)
        return self.response

    def update(self):
        self.clean()
        req = self.request
        self._text_browser.setText(req.message)
        if req.type == RoomDialogRequest.DISPLAY:
            # All done, nothing more too see here.
            self.response = RoomDialogResponse(RoomDialogRequest.NO_RESPONSE,
                                               "")
            self.response_ready = True
        elif req.type == RoomDialogRequest.CHOICE_QUESTION:
            for index, options in enumerate(req.options):
                button = QPushButton(options, self._widget)
                button.clicked.connect(partial(self.handle_button, index))
                row = index / 3
                col = index % 3
                self._button_layout.addWidget(button, row, col)
                self.buttons.append(button)
        elif req.type == RoomDialogRequest.TEXT_QUESTION:
            self.text_label = QLabel("Enter here: ", self._widget)
            self._button_layout.addWidget(self.text_label, 0, 0)
            self.text_input = QLineEdit(self._widget)
            self.text_input.editingFinished.connect(self.handle_text)
            self._button_layout.addWidget(self.text_input, 0, 1)

        # add handling of combobox
        elif req.type == RoomDialogRequest.COMBOBOX_QUESTION:
            #  self.clean()
            rospy.loginfo("Combobox selected")

            #self._cb.duplicatesEnabled = False
            if self._cb.count() == 0:
                for index, options in enumerate(req.options):
                    self._cb.addItem(options)
                    rospy.loginfo(options)
                #self.buttons.append(options)
            # NOTE COULD INTRODUCE BUG
            self._cb.currentIndexChanged.connect(self.handle_cb)
            self._cb_layout.addWidget(self._cb)

    def timeout(self):
        self._text_browser.setText("Oh no! The request timed out.")
        self.clean()

    def clean(self):
        while self._button_layout.count():
            item = self._button_layout.takeAt(0)
            item.widget().deleteLater()

    # while self._cb_layout.count():
    #     item = self._cb_layout.takeAt(0)
    #     item.widget().deleteLater()

        self.buttons = []
        self.text_input = None
        self.text_label = None

    def handle_button(self, index):
        self.response = RoomDialogResponse(index, "")
        self.clean()
        self.response_ready = True

    def handle_text(self):
        self.response = RoomDialogResponse(RoomDialogRequest.TEXT_RESPONSE,
                                           self.text_input.text())
        self.clean()
        self.response_ready = True

    def handle_cb(self, index):
        # This will be the sign format seen around building ex: 3.404
        rospy.loginfo("handling cb")
        roomHuman = self._cb.currentText()
        # modify string into robot format ex: d3_404
        splitHuman = roomHuman.split('.', 1)
        roomRobot = 'd' + splitHuman[0] + '_' + splitHuman[1]
        roomRobot = str(roomRobot)
        self.response = RoomDialogResponse(RoomDialogRequest.CB_RESPONSE,
                                           roomRobot)
        self.clean()
        self.response_ready = True

    def save_settings(self, plugin_settings, instance_settings):
        # TODO save intrinsic configuration, usually using:
        # instance_settings.set_value(k, v)
        pass

    def restore_settings(self, plugin_settings, instance_settings):
        # TODO restore intrinsic configuration, usually using:
        # v = instance_settings.value(k)
        pass

if __name__ == '__main__':
    import sys
    from python_qt_binding.QtGui import QApplication, QComboBox, QLineEdit, QMainWindow, QTreeView, QVBoxLayout, QWidget
    app = QApplication(sys.argv)
    mw = QMainWindow()
    widget = QWidget(mw)
    layout = QVBoxLayout(widget)

    edit = QLineEdit()
    edit_completer = TopicCompleter(edit)
    #edit_completer.setCompletionMode(QCompleter.InlineCompletion)
    edit.setCompleter(edit_completer)

    combo = QComboBox()
    combo.setEditable(True)
    combo_completer = TopicCompleter(combo)
    #combo_completer.setCompletionMode(QCompleter.InlineCompletion)
    combo.lineEdit().setCompleter(combo_completer)

    model_tree = QTreeView()
    model_tree.setModel(combo_completer.model())
    model_tree.expandAll()
    for column in range(combo_completer.model().columnCount()):
        model_tree.resizeColumnToContents(column)

    completion_tree = QTreeView()
    completion_tree.setModel(combo_completer.completionModel())
    completion_tree.expandAll()
    for column in range(combo_completer.completionModel().columnCount()):
Example #18
0
    def __init__(self, masteruri, parent=None):
        QDialog.__init__(self, parent)
        self.setWindowTitle('Select Binary')
        self.verticalLayout = QVBoxLayout(self)
        self.verticalLayout.setObjectName("verticalLayout")

        self.content = QWidget()
        self.contentLayout = QFormLayout(self.content)
        self.contentLayout.setVerticalSpacing(0)
        self.verticalLayout.addWidget(self.content)

        self.packages = None
        self.masteruri = "ROS_MASTER_URI" if masteruri is None else masteruri
        package_label = QLabel("Package:", self.content)
        self.package_field = QComboBox(self.content)
        self.package_field.setInsertPolicy(QComboBox.InsertAlphabetically)
        self.package_field.setSizePolicy(
            QSizePolicy(QSizePolicy.Expanding, QSizePolicy.Fixed))
        self.package_field.setEditable(True)
        self.contentLayout.addRow(package_label, self.package_field)
        binary_label = QLabel("Binary:", self.content)
        self.binary_field = QComboBox(self.content)
        self.binary_field.setSizePolicy(
            QSizePolicy(QSizePolicy.Expanding, QSizePolicy.Fixed))
        self.binary_field.setEditable(True)
        self.contentLayout.addRow(binary_label, self.binary_field)

        self.buttonBox = QDialogButtonBox(self)
        self.buttonBox.setStandardButtons(QDialogButtonBox.Ok
                                          | QDialogButtonBox.Cancel)
        self.buttonBox.setOrientation(Qt.Horizontal)
        self.buttonBox.setObjectName("buttonBox")
        self.verticalLayout.addWidget(self.buttonBox)

        self.package_field.setFocus(Qt.TabFocusReason)
        self.package = ''
        self.binary = ''
        self._request_bin_thread = None

        if self.packages is None:
            self.package_field.addItems(['packages searching...'])
            self.package_field.setCurrentIndex(0)
        # fill the input fields
        self.packages = {
            name: path
            for path, name in nm.nmd().file.get_packages(
                nmdurl.nmduri(masteruri)).items()
        }
        packages = self.packages.keys()
        packages.sort()
        self.package_field.clear()
        self.package_field.clearEditText()
        self.package_field.addItems(packages)
        self.buttonBox.accepted.connect(self.accept)
        self.buttonBox.rejected.connect(self.reject)
        QMetaObject.connectSlotsByName(self)
        self.package_field.activated[str].connect(self.on_package_selected)
        if hasattr(self.package_field, "textChanged"):  # qt compatibility
            self.package_field.textChanged.connect(self.on_package_selected)
            self.binary_field.textChanged.connect(self.on_binary_selected)
        else:
            self.package_field.editTextChanged.connect(
                self.on_package_selected)
            self.binary_field.editTextChanged.connect(self.on_binary_selected)
Example #19
0
class PackageDialog(QDialog):
    def __init__(self, masteruri, parent=None):
        QDialog.__init__(self, parent)
        self.setWindowTitle('Select Binary')
        self.verticalLayout = QVBoxLayout(self)
        self.verticalLayout.setObjectName("verticalLayout")

        self.content = QWidget()
        self.contentLayout = QFormLayout(self.content)
        self.contentLayout.setVerticalSpacing(0)
        self.verticalLayout.addWidget(self.content)

        self.packages = None
        self.masteruri = "ROS_MASTER_URI" if masteruri is None else masteruri
        package_label = QLabel("Package:", self.content)
        self.package_field = QComboBox(self.content)
        self.package_field.setInsertPolicy(QComboBox.InsertAlphabetically)
        self.package_field.setSizePolicy(
            QSizePolicy(QSizePolicy.Expanding, QSizePolicy.Fixed))
        self.package_field.setEditable(True)
        self.contentLayout.addRow(package_label, self.package_field)
        binary_label = QLabel("Binary:", self.content)
        self.binary_field = QComboBox(self.content)
        self.binary_field.setSizePolicy(
            QSizePolicy(QSizePolicy.Expanding, QSizePolicy.Fixed))
        self.binary_field.setEditable(True)
        self.contentLayout.addRow(binary_label, self.binary_field)

        self.buttonBox = QDialogButtonBox(self)
        self.buttonBox.setStandardButtons(QDialogButtonBox.Ok
                                          | QDialogButtonBox.Cancel)
        self.buttonBox.setOrientation(Qt.Horizontal)
        self.buttonBox.setObjectName("buttonBox")
        self.verticalLayout.addWidget(self.buttonBox)

        self.package_field.setFocus(Qt.TabFocusReason)
        self.package = ''
        self.binary = ''
        self._request_bin_thread = None

        if self.packages is None:
            self.package_field.addItems(['packages searching...'])
            self.package_field.setCurrentIndex(0)
        # fill the input fields
        self.packages = {
            name: path
            for path, name in nm.nmd().file.get_packages(
                nmdurl.nmduri(masteruri)).items()
        }
        packages = self.packages.keys()
        packages.sort()
        self.package_field.clear()
        self.package_field.clearEditText()
        self.package_field.addItems(packages)
        self.buttonBox.accepted.connect(self.accept)
        self.buttonBox.rejected.connect(self.reject)
        QMetaObject.connectSlotsByName(self)
        self.package_field.activated[str].connect(self.on_package_selected)
        if hasattr(self.package_field, "textChanged"):  # qt compatibility
            self.package_field.textChanged.connect(self.on_package_selected)
            self.binary_field.textChanged.connect(self.on_binary_selected)
        else:
            self.package_field.editTextChanged.connect(
                self.on_package_selected)
            self.binary_field.editTextChanged.connect(self.on_binary_selected)

    def on_package_selected(self, package):
        getnew = False
        if self._request_bin_thread is None:
            getnew = True
        else:
            if self._request_bin_thread.pkgname != package:
                self._request_bin_thread.cancel()
                getnew = True
        if self._request_bin_thread is not None and self._request_bin_thread.pkgname == package:
            # use already got data
            self._request_bin_thread.reemit()
        elif getnew:
            self.binary_field.clear()
            if self.packages and package in self.packages:
                self.binary_field.setEnabled(True)
                self._request_bin_thread = RequestBinariesThread(
                    package, nmdurl.nmduri(self.masteruri))
                self._request_bin_thread.binaries_signal.connect(
                    self._on_new_binaries)
                self._request_bin_thread.start()

    def _on_new_binaries(self, pkgname, binaries):
        # update the binaries
        binaries = [os.path.basename(item) for item in binaries.keys()]
        binaries = list(set(binaries))
        binaries.sort()
        self.binary_field.addItems(binaries)
        self.package = pkgname
        self.binary = self.binary_field.currentText()

    def on_binary_selected(self, binary):
        self.binary = binary
Example #20
0
class RunDialog(PackageDialog):
    '''
    A dialog to run a ROS node without configuration
    '''
    def __init__(self, host, masteruri=None, parent=None):
        PackageDialog.__init__(self, masteruri, parent)
        self.host = host
        self.setWindowTitle('Run')

        ns_name_label = QLabel("NS/Name:", self.content)
        self.ns_field = QComboBox(self.content)
        self.ns_field.setSizePolicy(
            QSizePolicy(QSizePolicy.Expanding, QSizePolicy.Fixed))
        self.ns_field.setEditable(True)
        ns_history = nm.history().cachedParamValues('run_dialog/NS')
        ns_history.insert(0, '/')
        self.ns_field.addItems(ns_history)
        self.name_field = QLineEdit(self.content)
        self.name_field.setEnabled(False)
        horizontalLayout = QHBoxLayout()
        horizontalLayout.addWidget(self.ns_field)
        horizontalLayout.addWidget(self.name_field)
        self.contentLayout.addRow(ns_name_label, horizontalLayout)
        args_label = QLabel("Args:", self.content)
        self.args_field = QComboBox(self.content)
        self.args_field.setSizeAdjustPolicy(
            QComboBox.AdjustToMinimumContentsLength)
        self.args_field.setSizePolicy(
            QSizePolicy(QSizePolicy.Expanding, QSizePolicy.Fixed))
        self.args_field.setEditable(True)
        self.contentLayout.addRow(args_label, self.args_field)
        args_history = nm.history().cachedParamValues('run_dialog/Args')
        args_history.insert(0, '')
        self.args_field.addItems(args_history)

        host_label = QLabel("Host:", self.content)
        self.host_field = QComboBox(self.content)
        self.host_field.setSizePolicy(
            QSizePolicy(QSizePolicy.Expanding, QSizePolicy.Fixed))
        self.host_field.setEditable(True)
        host_label.setBuddy(self.host_field)
        self.contentLayout.addRow(host_label, self.host_field)
        self.host_history = host_history = nm.history().cachedParamValues(
            '/Host')
        if self.host in host_history:
            host_history.remove(self.host)
        host_history.insert(0, self.host)
        self.host_field.addItems(host_history)

        master_label = QLabel("ROS Master URI:", self.content)
        self.master_field = QComboBox(self.content)
        self.master_field.setSizePolicy(
            QSizePolicy(QSizePolicy.Expanding, QSizePolicy.Fixed))
        self.master_field.setEditable(True)
        master_label.setBuddy(self.host_field)
        self.contentLayout.addRow(master_label, self.master_field)
        self.master_history = master_history = nm.history().cachedParamValues(
            '/Optional Parameter/ROS Master URI')
        if self.masteruri in master_history:
            master_history.remove(self.masteruri)
        master_history.insert(0, self.masteruri)
        self.master_field.addItems(master_history)
        self.binary_field.activated[str].connect(self.on_binary_selected)

    def run_params(self):
        '''
        Runs the selected node, or do nothing.
        :return: a tuple with host, package, binary, name, args, maseruri or empty tuple on errors
        '''
        self.binary = self.binary_field.currentText()
        self.host = self.host_field.currentText(
        ) if self.host_field.currentText() else self.host
        self.masteruri = self.master_field.currentText(
        ) if self.master_field.currentText() else self.masteruri
        if self.host not in self.host_history and self.host != 'localhost' and self.host != '127.0.0.1':
            nm.history().add2HostHistory(self.host)
        ns = self.ns_field.currentText()
        if ns and ns != '/':
            nm.history().addParamCache('run_dialog/NS', ns)
        args = self.args_field.currentText()
        if args:
            nm.history().addParamCache('run_dialog/Args', args)
        if self.package and self.binary:
            nm.history().addParamCache('/Host', self.host)
            return (self.host, self.package, self.binary,
                    self.name_field.text(),
                    ('__ns:=%s %s' % (ns, args)).split(' '), None
                    if self.masteruri == 'ROS_MASTER_URI' else self.masteruri)
        return ()

    def on_package_selected(self, package):
        PackageDialog.on_package_selected(self, package)
        if self.packages and package in self.packages:
            self.args_field.setEnabled(True)
            self.ns_field.setEnabled(True)
            self.name_field.setEnabled(True)
            root, _ext = os.path.splitext(
                os.path.basename(self.binary_field.currentText()))
            self.name_field.setText(root)

    def on_binary_selected(self, binary):
        root, _ext = os.path.splitext(os.path.basename(binary))
        self.name_field.setText(root)
class QTopicWidget(QWidget):

    topic_changed_signal = Signal(str)

    def __init__(self, parent = None, topic_type = str(), is_action_topic = False):
        QWidget.__init__(self, parent)

        if is_action_topic:
            self.topic_type = topic_type + "Goal"
        else:
            self.topic_type = topic_type
        self.is_action_topic = is_action_topic

        # start widget
        hbox = QHBoxLayout()
        hbox.setMargin(0)
        hbox.setContentsMargins(0, 0, 0, 0)

        # topic combo box
        self.topic_combo_box = QComboBox()
        self.topic_combo_box.setEnabled(False)
        self.topic_combo_box.blockSignals(True)
        self.topic_combo_box.setValidator(QRegExpValidator(QRegExp('((\d|\w|/)(?!//))*'), self))
        self.topic_combo_box.currentIndexChanged[str].connect(self.topic_changed)
        hbox.addWidget(self.topic_combo_box)

        # get system icon
        icon = QIcon.fromTheme("view-refresh")
        size = icon.actualSize(QSize(32, 32))

        # add refresh button
        refresh_topics_button = QPushButton()
        refresh_topics_button.clicked.connect(self.update_topic_list)
        refresh_topics_button.setIcon(icon)
        refresh_topics_button.setFixedSize(size.width()+2, size.height()+2)
        hbox.addWidget(refresh_topics_button)

        # end widget
        self.setLayout(hbox)

        # init widget
        self.update_topic_list()

    def emit_topic_name(self):
        self.topic_changed_signal.emit(self.current_topic())

    def set_editable(self, enable):
        self.topic_combo_box.setEditable(enable)

    def current_topic(self):
        if self.topic_combo_box.isEnabled():
            return self.topic_combo_box.currentText()
        else:
            return ""        

    @Slot(str)
    def topic_changed(self, topic_name):
        self.topic_changed_signal.emit(topic_name)

    @Slot()
    def update_topic_list(self):
        self.topic_combo_box.clear()
        self.topic_combo_box.setEnabled(False)
        self.topic_combo_box.blockSignals(True)
        self.topic_combo_box.addItem('Updating...')

        # get topic list
        _, _, topic_type = rospy.get_master().getTopicTypes()
        topic_dict = dict(topic_type)
        # filter list
        topic_dict_filtered = dict()
        for k, v in topic_dict.items():
            if (len(topic_type) == 0) or (v == self.topic_type):
                if (self.is_action_topic):
                    topic_dict_filtered[k[:-5]] = v
                else:
                    topic_dict_filtered[k] = v

        self.topic_combo_box.clear()
        self.topic_combo_box.addItems(sorted(topic_dict_filtered.keys()))

        if (self.topic_combo_box.count() > 0):
            self.topic_combo_box.setEnabled(True)
            self.topic_combo_box.blockSignals(False)
            self.topic_changed(self.topic_combo_box.currentText())
        else:
            self.topic_combo_box.addItem('No topics available!')   
class PackageDialog(QDialog):

    def __init__(self, parent=None):
        QDialog.__init__(self, parent)
        self.setWindowTitle('Select Binary')
        self.verticalLayout = QVBoxLayout(self)
        self.verticalLayout.setObjectName("verticalLayout")

        self.content = QWidget()
        self.contentLayout = QFormLayout(self.content)
        self.contentLayout.setVerticalSpacing(0)
        self.verticalLayout.addWidget(self.content)

        self.packages = None

        package_label = QLabel("Package:", self.content)
        self.package_field = QComboBox(self.content)
        self.package_field.setInsertPolicy(QComboBox.InsertAlphabetically)
        self.package_field.setSizePolicy(QSizePolicy(QSizePolicy.Expanding, QSizePolicy.Fixed))
        self.package_field.setEditable(True)
        self.contentLayout.addRow(package_label, self.package_field)
        binary_label = QLabel("Binary:", self.content)
        self.binary_field = QComboBox(self.content)
#    self.binary_field.setSizeAdjustPolicy(QComboBox.AdjustToContents)
        self.binary_field.setSizePolicy(QSizePolicy(QSizePolicy.Expanding, QSizePolicy.Fixed))
        self.binary_field.setEditable(True)
        self.contentLayout.addRow(binary_label, self.binary_field)

        self.buttonBox = QDialogButtonBox(self)
        self.buttonBox.setStandardButtons(QDialogButtonBox.Ok | QDialogButtonBox.Cancel)
        self.buttonBox.setOrientation(Qt.Horizontal)
        self.buttonBox.setObjectName("buttonBox")
        self.verticalLayout.addWidget(self.buttonBox)

        self.package_field.setFocus(Qt.TabFocusReason)
        self.package = ''
        self.binary = ''

        if self.packages is None:
            self.package_field.addItems(['packages searching...'])
            self.package_field.setCurrentIndex(0)
            self._fill_packages_thread = PackagesThread()
            self._fill_packages_thread.packages.connect(self._fill_packages)
            self._fill_packages_thread.start()

        self.buttonBox.accepted.connect(self.accept)
        self.buttonBox.rejected.connect(self.reject)
        QMetaObject.connectSlotsByName(self)
        self.package_field.activated[str].connect(self.on_package_selected)
        if hasattr(self.package_field, "textChanged"):  # qt compatibility
            self.package_field.textChanged.connect(self.on_package_selected)
            self.binary_field.textChanged.connect(self.on_binary_selected)
        else:
            self.package_field.editTextChanged.connect(self.on_package_selected)
            self.binary_field.editTextChanged.connect(self.on_binary_selected)

    def _fill_packages(self, packages):
        # fill the input fields
        self.packages = packages
        packages = packages.keys()
        packages.sort()
        self.package_field.clear()
        self.package_field.clearEditText()
        self.package_field.addItems(packages)

    def _getBinaries(self, path):
        result = {}
        if os.path.isdir(path):
            fileList = os.listdir(path)
            for f in fileList:
                if f and f[0] != '.' and f not in ['build'] and not f.endswith('.cfg') and not f.endswith('.so'):
                    ret = self._getBinaries(os.path.join(path, f))
                    result = dict(ret.items() + result.items())
        elif os.path.isfile(path) and os.access(path, os.X_OK):
            # create a selection for binaries
            return {os.path.basename(path): path}
        return result

    def on_package_selected(self, package):
        self.binary_field.clear()
        if self.packages and package in self.packages:
            self.binary_field.setEnabled(True)
            path = self.packages[package]
            binaries = self._getBinaries(path).keys()
            try:
                # find binaries in catkin workspace
                from catkin.find_in_workspaces import find_in_workspaces as catkin_find
                search_paths = catkin_find(search_dirs=['libexec', 'share'], project=package, first_matching_workspace_only=True)
                for p in search_paths:
                    binaries += self._getBinaries(p).keys()
            except:
                pass
            binaries = list(set(binaries))
            binaries.sort()
            self.binary_field.addItems(binaries)
            self.package = package
            self.binary = self.binary_field.currentText()

    def on_binary_selected(self, binary):
        self.binary = binary
class SyncDialog(QDialog):
    '''
    A dialog to set the sync options.
    '''

    def __init__(self, parent=None):
        QDialog.__init__(self, parent)
#    self.host = host
        self.setWindowIcon(QIcon(":/icons/irondevil_sync.png"))
        self.setWindowTitle('Sync')
        self.verticalLayout = QVBoxLayout(self)
        self.verticalLayout.setObjectName("verticalLayout")
        self.resize(350, 190)

        self.toolButton_SyncAll = QToolButton(self)
        sizePolicy = QSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding)
        sizePolicy.setHorizontalStretch(0)
        sizePolicy.setVerticalStretch(2)
        sizePolicy.setHeightForWidth(self.toolButton_SyncAll.sizePolicy().hasHeightForWidth())
        self.toolButton_SyncAll.setSizePolicy(sizePolicy)
        self.toolButton_SyncAll.setObjectName("toolButton_SyncAll")
        self.verticalLayout.addWidget(self.toolButton_SyncAll)
        self.toolButton_SyncAll.setText(self._translate("Sync All"))
        self.toolButton_SyncAll.clicked.connect(self._on_sync_all_clicked)

#     self.toolButton_SyncAllAnyMsg = QToolButton(self)
#     sizePolicy = QSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding)
#     sizePolicy.setHorizontalStretch(0)
#     sizePolicy.setVerticalStretch(1)
#     sizePolicy.setHeightForWidth(self.toolButton_SyncAllAnyMsg.sizePolicy().hasHeightForWidth())
#     self.toolButton_SyncAllAnyMsg.setSizePolicy(sizePolicy)
#     self.toolButton_SyncAllAnyMsg.setObjectName("toolButton_SyncAllAnyMsg")
#     self.verticalLayout.addWidget(self.toolButton_SyncAllAnyMsg)
#     self.toolButton_SyncAllAnyMsg.setText(self._translate("Sync all (+AnyMsg)"))
#     self.toolButton_SyncAllAnyMsg.clicked.connect(self._on_sync_all_anymsg_clicked)

        self.toolButton_SyncTopicOnDemand = QToolButton(self)
        sizePolicy = QSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding)
        sizePolicy.setHorizontalStretch(0)
        sizePolicy.setVerticalStretch(1)
        sizePolicy.setHeightForWidth(self.toolButton_SyncTopicOnDemand.sizePolicy().hasHeightForWidth())
        self.toolButton_SyncTopicOnDemand.setSizePolicy(sizePolicy)
        self.toolButton_SyncTopicOnDemand.setObjectName("toolButton_SyncTopicOnDemand")
        self.verticalLayout.addWidget(self.toolButton_SyncTopicOnDemand)
        self.toolButton_SyncTopicOnDemand.setText(self._translate("Sync only topics on demand"))
        self.toolButton_SyncTopicOnDemand.clicked.connect(self._on_sync_topics_on_demand_clicked)

        self.toolButton_SelectInterface = QToolButton(self)
        sizePolicy = QSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding)
        sizePolicy.setHorizontalStretch(0)
        sizePolicy.setVerticalStretch(1)
        sizePolicy.setHeightForWidth(self.toolButton_SelectInterface.sizePolicy().hasHeightForWidth())
        self.toolButton_SelectInterface.setSizePolicy(sizePolicy)
        self.toolButton_SelectInterface.setObjectName("toolButton_SelectInterface")
        self.verticalLayout.addWidget(self.toolButton_SelectInterface)
        self.toolButton_SelectInterface.setText(self._translate("Select an interface"))
        self.toolButton_SelectInterface.clicked.connect(self._on_select_interface_clicked)

        self.interface_field = QComboBox(self)
        self.interface_field.setInsertPolicy(QComboBox.InsertAlphabetically)
        self.interface_field.setSizePolicy(QSizePolicy(QSizePolicy.Expanding, QSizePolicy.Fixed))
        self.interface_field.setEditable(True)
        self.interface_field.setVisible(False)
        self.interface_field.setObjectName("interface_field")
        self.verticalLayout.addWidget(self.interface_field)
        self.interface_field.currentIndexChanged[str].connect(self._on_interface_selected)

        self.toolButton_EditInterface = QToolButton(self)
        sizePolicy = QSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding)
        sizePolicy.setHorizontalStretch(0)
        sizePolicy.setVerticalStretch(1)
        sizePolicy.setHeightForWidth(self.toolButton_EditInterface.sizePolicy().hasHeightForWidth())
        self.toolButton_EditInterface.setSizePolicy(sizePolicy)
        self.toolButton_EditInterface.setObjectName("toolButton_EditInterface")
        self.verticalLayout.addWidget(self.toolButton_EditInterface)
        self.toolButton_EditInterface.setText(self._translate("Edit selected interface"))
        self.toolButton_EditInterface.clicked.connect(self._on_edit_interface_clicked)
        self.toolButton_EditInterface.setVisible(False)

        self.toolButton_CreateInterface = QToolButton(self)
        sizePolicy = QSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding)
        sizePolicy.setHorizontalStretch(0)
        sizePolicy.setVerticalStretch(1)
        sizePolicy.setHeightForWidth(self.toolButton_CreateInterface.sizePolicy().hasHeightForWidth())
        self.toolButton_CreateInterface.setSizePolicy(sizePolicy)
        self.toolButton_CreateInterface.setObjectName("toolButton_CreateInterface")
        self.verticalLayout.addWidget(self.toolButton_CreateInterface)
        self.toolButton_CreateInterface.setText(self._translate("Create an interface"))
        self.toolButton_CreateInterface.clicked.connect(self._on_create_interface_clicked)
        self.toolButton_CreateInterface.setVisible(False)

        self.textedit = TextEdit('', self)
        self.hl = SyncHighlighter(self.textedit.document())
        sizePolicy = QSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding)
        self.textedit.setSizePolicy(sizePolicy)
        self.textedit.setObjectName("syncedit")
        self.verticalLayout.addWidget(self.textedit)
        self.textedit.setVisible(False)

        self._fill_interface_thread = None
        self._interfaces_files = None
        self._sync_args = []
        self._interface_filename = None

        self.buttonBox = QDialogButtonBox(self)
        self.buttonBox.setStandardButtons(QDialogButtonBox.Cancel)
        self.buttonBox.setOrientation(Qt.Horizontal)
        self.buttonBox.setObjectName("buttonBox")
        self.verticalLayout.addWidget(self.buttonBox)
        self.buttonBox.accepted.connect(self.accept)
        self.buttonBox.rejected.connect(self.reject)
        self._new_iface = True

    def _translate(self, text):
        if hasattr(QApplication, "UnicodeUTF8"):
            return QApplication.translate("Form", text, None, QApplication.UnicodeUTF8)
        else:
            return QApplication.translate("Form", text, None)

    @property
    def sync_args(self):
        return self._sync_args

    @property
    def interface_filename(self):
        return self._interface_filename

    def _on_sync_all_clicked(self):
        self.setResult(QDialog.Accepted)
        self._sync_args = []
        self._sync_args.append(''.join(['_interface_url:=', "'.'"]))
        self._sync_args.append(''.join(['_sync_topics_on_demand:=', 'False']))
        self._sync_args.append(''.join(['_ignore_hosts:=', '[]']))
        self._sync_args.append(''.join(['_sync_hosts:=', '[]']))
        self._sync_args.append(''.join(['_ignore_nodes:=', '[]']))
        self._sync_args.append(''.join(['_sync_nodes:=', '[]']))
        self._sync_args.append(''.join(['_ignore_topics:=', '[]']))
        self._sync_args.append(''.join(['_ignore_publishers:=', '[]']))
        self._sync_args.append(''.join(['_ignore_subscribers:=', '[]']))
        self._sync_args.append(''.join(['_sync_topics:=', '[]']))
        self._sync_args.append(''.join(['_ignore_services:=', '[]']))
        self._sync_args.append(''.join(['_sync_services:=', '[]']))
        self._sync_args.append(''.join(['_sync_remote_nodes:=', 'False']))
        self._interface_filename = None
        self.accept()

#   def _on_sync_all_anymsg_clicked(self):
#     self._sync_args = []
#     self._sync_args.append(''.join(['_interface_url:=', "'.'"]))
#     self._sync_args.append(''.join(['_sync_topics_on_demand:=', 'True']))
#     self._sync_args.append(''.join(['_ignore_hosts:=', '[]']))
#     self._sync_args.append(''.join(['_sync_hosts:=', '[]']))
#     self._sync_args.append(''.join(['_ignore_nodes:=', '[]']))
#     self._sync_args.append(''.join(['_sync_nodes:=', '[]']))
#     self._sync_args.append(''.join(['_ignore_topics:=', '[]']))
#     self._sync_args.append(''.join(['_sync_topics:=', '[/*]']))
#     self._sync_args.append(''.join(['_ignore_services:=', '[]']))
#     self._sync_args.append(''.join(['_sync_services:=', '[]']))
#     self._sync_args.append(''.join(['_sync_remote_nodes:=', 'False']))
#     self._interface_filename = None
#     self.accept()

    def _on_sync_topics_on_demand_clicked(self):
        self._sync_args = []
        self._sync_args.append(''.join(['_interface_url:=', "'.'"]))
        self._sync_args.append(''.join(['_sync_topics_on_demand:=', 'True']))
        self._sync_args.append(''.join(['_ignore_hosts:=', '[]']))
        self._sync_args.append(''.join(['_sync_hosts:=', '[]']))
        self._sync_args.append(''.join(['_ignore_nodes:=', '[]']))
        self._sync_args.append(''.join(['_sync_nodes:=', '[]']))
        self._sync_args.append(''.join(['_ignore_topics:=', '[]']))
        self._sync_args.append(''.join(['_ignore_publishers:=', '[]']))
        self._sync_args.append(''.join(['_ignore_subscribers:=', '[]']))
        self._sync_args.append(''.join(['_sync_topics:=', '[/only_on_demand]']))
        self._sync_args.append(''.join(['_ignore_services:=', '[/*]']))
        self._sync_args.append(''.join(['_sync_services:=', '[]']))
        self._sync_args.append(''.join(['_sync_remote_nodes:=', 'False']))
        self._interface_filename = None
        self.accept()

    def _on_select_interface_clicked(self):
        self.toolButton_SyncAll.setVisible(False)
#    self.toolButton_SyncAllAnyMsg.setVisible(False)
        self.toolButton_SyncTopicOnDemand.setVisible(False)
        self.toolButton_SelectInterface.setVisible(False)
        self.interface_field.setVisible(True)
        self.toolButton_CreateInterface.setVisible(True)
        self.toolButton_EditInterface.setVisible(True)
        self.toolButton_EditInterface.setEnabled(False)
        self.textedit.setVisible(False)
#    # fill the interfaces
        if self._interfaces_files is None:
            self.interface_field.addItems(['interface searching...'])
            self.interface_field.setCurrentIndex(0)
            self._fill_interface_thread = InterfacesThread()
            self._fill_interface_thread.interfaces.connect(self._fill_interfaces)
            self._fill_interface_thread.start()
        else:
            self.toolButton_EditInterface.setEnabled(self.interface_field.currentText() in self._interfaces_files)
        self.buttonBox.clear()
        self.buttonBox.setStandardButtons(QDialogButtonBox.Ok | QDialogButtonBox.Cancel)
        self.interface_field.setFocus(Qt.TabFocusReason)
        self.resize(350, 80)

    def _fill_interfaces(self, interfaces_files):
        self._interfaces_files = interfaces_files
        self.interface_field.clear()
        self.interface_field.clearEditText()
        self.interface_field.addItems(self._interfaces_files.keys())

    def _on_interface_selected(self, interface):
        if self._interfaces_files and interface in self._interfaces_files:
            self._sync_args = []
            self._sync_args.append(''.join(['_interface_url:=', interface]))
            self.toolButton_EditInterface.setEnabled(True)
        else:
            self.toolButton_EditInterface.setEnabled(False)

    def accept(self):
        if self.textedit.isVisible():
            try:
                tmp_file = os.path.join(nm.screen().LOG_PATH, 'tmp_sync_interface.sync')
                with open(tmp_file, 'w+') as f:
                    f.write(self.textedit.toPlainText())
                from master_discovery_fkie.common import read_interface
                read_interface(tmp_file)
                if not self._new_iface and self.interface_field.currentText() in self._interfaces_files:
                    fileName = self._interfaces_files[self.interface_field.currentText()]
                else:
                    fileName, _ = QFileDialog.getSaveFileName(self, 'Save sync interface', '/home', "Sync Files (*.sync)")
                if fileName:
                    with open(fileName, 'w+') as f:
                        self._interface_filename = fileName
                        f.write(self.textedit.toPlainText())
                        if self._new_iface:
                            self.interface_field.clear()
                            self._interfaces_files = None
                        self._on_select_interface_clicked()
#        QDialog.accept(self)
#        self.resetView()
            except Exception as e:
                MessageBox.warning(self, "Create sync interface",
                                   "Error while create interface",
                                   utf8(e))
        elif self.interface_field.isVisible():
            interface = self.interface_field.currentText()
            if self._interfaces_files and interface in self._interfaces_files:
                self._interface_filename = self._interfaces_files[interface]
                self._sync_args = []
                self._sync_args.append(''.join(['_interface_url:=', interface]))
                QDialog.accept(self)
                self.resetView()
        else:
            QDialog.accept(self)
            self.resetView()

    def reject(self):
        if self.textedit.isVisible():
            self._on_select_interface_clicked()
        else:
            QDialog.reject(self)
            self.resetView()

    def _on_create_interface_clicked(self):
        self._new_iface = True
        self.interface_field.setVisible(False)
        self.toolButton_CreateInterface.setVisible(False)
        self.toolButton_EditInterface.setVisible(False)
        self.textedit.setVisible(True)
        self.textedit.setText("# The ignore_* lists will be processed first.\n"
                              "# For ignore/sync nodes, topics or services\n"
                              "# use follow declaration:\n"
                              "#{param name}: \n"
                              "#   - {ros name}\n"
                              "# or for selected hosts:\n"
                              "#   - {host name}:\n"
                              "#     - {ros name}\n\n"
                              "# you can use follow wildcard: '*', but not as a first character\n"
                              "ignore_hosts:\n"
                              "sync_hosts:\n\n"
                              "ignore_nodes:\n"
                              "sync_nodes:\n\n"
                              "ignore_topics:\n"
                              "ignore_publishers:\n"
                              "ignore_subscribers:\n"
                              "sync_topics:\n\n"
                              "ignore_services:\n"
                              "  - /*get_loggers\n"
                              "  - /*set_logger_level\n"
                              "sync_services:\n\n"
                              "# If sync_topics_on_demand is True the local subscribed and published topics\n"
                              "# are synchronized with remote even if they are not in the sync_* list.\n"
                              "sync_topics_on_demand: False\n\n"
                              "# The nodes which are running not at the same host as the ROS master are not\n"
                              "# synchronized by default. Use sync_remote_nodes to sync these nodes also.\n"
                              "sync_remote_nodes: False\n\n"
                              )
        self.resize(350, 300)

    def _on_edit_interface_clicked(self):
        self._new_iface = False
        self.interface_field.setVisible(False)
        self.toolButton_CreateInterface.setVisible(False)
        self.toolButton_EditInterface.setVisible(False)
        self.textedit.setVisible(True)
        if self.interface_field.currentText() in self._interfaces_files:
            try:
                with open(self._interfaces_files[self.interface_field.currentText()], 'rw') as f:
                    iface = f.read()
                    self.textedit.setText(iface)
            except Exception as e:
                MessageBox.warning(self, "Edit sync interface",
                                   "Error while open interface",
                                   utf8(e))
        self.resize(350, 300)

    def resetView(self):
        self.toolButton_SyncAll.setVisible(True)
#     self.toolButton_SyncAllAnyMsg.setVisible(True)
        self.toolButton_SyncTopicOnDemand.setVisible(True)
        self.toolButton_SelectInterface.setVisible(True)
        self.interface_field.setVisible(False)
        self.toolButton_CreateInterface.setVisible(False)
        self.toolButton_EditInterface.setVisible(False)
        self.textedit.setVisible(False)
        self.buttonBox.clear()
        self.buttonBox.setStandardButtons(QDialogButtonBox.Cancel)
        self.resize(350, 160)
Example #24
0
class RunDialog(PackageDialog):
    '''
    A dialog to run a ROS node without configuration
    '''

    def __init__(self, host, masteruri=None, parent=None):
        PackageDialog.__init__(self, parent)
        self.host = host
        self.setWindowTitle('Run')

        ns_name_label = QLabel("NS/Name:", self.content)
        self.ns_field = QComboBox(self.content)
        self.ns_field.setSizePolicy(QSizePolicy(QSizePolicy.Expanding, QSizePolicy.Fixed))
        self.ns_field.setEditable(True)
        ns_history = nm.history().cachedParamValues('run_dialog/NS')
        ns_history.insert(0, '/')
        self.ns_field.addItems(ns_history)
        self.name_field = QLineEdit(self.content)
        self.name_field.setEnabled(False)
        horizontalLayout = QHBoxLayout()
        horizontalLayout.addWidget(self.ns_field)
        horizontalLayout.addWidget(self.name_field)
        self.contentLayout.addRow(ns_name_label, horizontalLayout)
        args_label = QLabel("Args:", self.content)
        self.args_field = QComboBox(self.content)
        self.args_field.setSizeAdjustPolicy(QComboBox.AdjustToMinimumContentsLength)
        self.args_field.setSizePolicy(QSizePolicy(QSizePolicy.Expanding, QSizePolicy.Fixed))
        self.args_field.setEditable(True)
        self.contentLayout.addRow(args_label, self.args_field)
        args_history = nm.history().cachedParamValues('run_dialog/Args')
        args_history.insert(0, '')
        self.args_field.addItems(args_history)

        host_label = QLabel("Host:", self.content)
        self.host_field = QComboBox(self.content)
#    self.host_field.setSizeAdjustPolicy(QComboBox.AdjustToContents)
        self.host_field.setSizePolicy(QSizePolicy(QSizePolicy.Expanding, QSizePolicy.Fixed))
        self.host_field.setEditable(True)
        host_label.setBuddy(self.host_field)
        self.contentLayout.addRow(host_label, self.host_field)
        self.host_history = host_history = nm.history().cachedParamValues('/Host')
        if self.host in host_history:
            host_history.remove(self.host)
        host_history.insert(0, self.host)
        self.host_field.addItems(host_history)

        master_label = QLabel("ROS Master URI:", self.content)
        self.master_field = QComboBox(self.content)
        self.master_field.setSizePolicy(QSizePolicy(QSizePolicy.Expanding, QSizePolicy.Fixed))
        self.master_field.setEditable(True)
        master_label.setBuddy(self.host_field)
        self.contentLayout.addRow(master_label, self.master_field)
        self.master_history = master_history = nm.history().cachedParamValues('/Optional Parameter/ROS Master URI')
        self.masteruri = "ROS_MASTER_URI" if masteruri is None else masteruri
        if self.masteruri in master_history:
            master_history.remove(self.masteruri)
        master_history.insert(0, self.masteruri)
        self.master_field.addItems(master_history)

#    self.package_field.setFocus(QtCore.Qt.TabFocusReason)
        if hasattr(self.package_field, "textChanged"):  # qt compatibility
            self.package_field.textChanged.connect(self.on_package_selected)
        else:
            self.package_field.editTextChanged.connect(self.on_package_selected)
        self.binary_field.activated[str].connect(self.on_binary_selected)

    def run_params(self):
        '''
        Runs the selected node, or do nothing.
        :return: a tuple with host, package, binary, name, args, maseruri or empty tuple on errors
        '''
        self.binary = self.binary_field.currentText()
        self.host = self.host_field.currentText() if self.host_field.currentText() else self.host
        self.masteruri = self.master_field.currentText() if self.master_field.currentText() else self.masteruri
        if self.host not in self.host_history and self.host != 'localhost' and self.host != '127.0.0.1':
            nm.history().add2HostHistory(self.host)
        ns = self.ns_field.currentText()
        if ns and ns != '/':
            nm.history().addParamCache('run_dialog/NS', ns)
        args = self.args_field.currentText()
        if args:
            nm.history().addParamCache('run_dialog/Args', args)
        if self.package and self.binary:
            nm.history().addParamCache('/Host', self.host)
            return (self.host, self.package, self.binary, self.name_field.text(), ('__ns:=%s %s' % (ns, args)).split(' '), None if self.masteruri == 'ROS_MASTER_URI' else self.masteruri)
        return ()

    def on_package_selected(self, package):
        PackageDialog.on_package_selected(self, package)
        if self.packages and package in self.packages:
            self.args_field.setEnabled(True)
            self.ns_field.setEnabled(True)
            self.name_field.setEnabled(True)
            root, _ext = os.path.splitext(os.path.basename(self.binary_field.currentText()))
            self.name_field.setText(root)

    def on_binary_selected(self, binary):
        root, _ext = os.path.splitext(os.path.basename(binary))
        self.name_field.setText(root)
    def __init__(self, context):
      
        self.control_mode =  0
        self.mode_pub = rospy.Publisher('/flor/controller/mode_command', VigirControlModeCommand, queue_size=10)

        self._widget = context
        self.vbox = QVBoxLayout()

        #Add input for setting the spindle speed
        list_label = QLabel("Select Control Mode")
        self.vbox.addWidget(list_label)

        # Indexed list of allowed control modes from feedback
        self.allowed_modes = rospy.get_param("/atlas_controller/allowed_control_modes")

        self.allowed_modes=rospy.get_param("/atlas_controller/allowed_control_modes")
        self.mode_ids={}
        self.mode_ids
        for ndx,txt in enumerate(self.allowed_modes):
            self.mode_ids[txt] = ndx

        # API 2.13 ordering
        self.bdi_mode_names=['NONE       ',        'FREEZE     ',        'STAND_PREP ', \
                             'STAND      ',        'WALK       ',        'STEP       ',        'MANIPULATE ', \
                             'USER       ',        'CALIBRATE  ']


        self.list_box = QListWidget(None)
        self.list_box.addItems(self.allowed_modes)

        self.list_box.currentItemChanged.connect(self.handle_selection_change)
        self.vbox.addWidget(self.list_box)

        self.selection_label = QLabel("Flor Selected: "+self.allowed_modes[0]+"("+str(self.control_mode)+")")
        self.vbox.addWidget(self.selection_label)

        self.label          = QLabel("Flor Command : "+self.allowed_modes[0]+"("+str(self.control_mode)+")")
        self.vbox.addWidget(self.label)

        self.flor_mode         = 0
        self.bdi_current_mode  = 0
        self.bdi_desired_mode  = 0
        self.flor_mode_label = QLabel("Flor Mode    : "+self.allowed_modes[self.flor_mode]+"("+str(self.flor_mode)+")"+"  BDI:("+str(self.bdi_current_mode)+", "+str(self.bdi_desired_mode)+")")
        self.vbox.addWidget(self.flor_mode_label)

        #Add combo box for available settings
        self.available_modes = QComboBox();
        self.available_modes.addItem("");
        self.available_modes.addItem("BDI");
        self.available_modes.addItem("Enable Upper Body");
        self.available_modes.addItem("Enable Whole Body");

        self.available_modes.currentIndexChanged.connect(self.handle_avail_modes_changed)
        self.vbox.addWidget(self.available_modes);
        
        self.vbox.addStretch(1)

        #Add Button for sending the behavior mode command
        self.push_button = QPushButton("Set Mode")
        self.push_button.clicked.connect(self.handle_set_mode)
        self.vbox.addWidget(self.push_button)

        self.vbox.addStretch(1)


        hbox = QHBoxLayout()
        hbox.addStretch(1)
        self.stop_enable= QCheckBox()
        self.stop_enable.setChecked(False)
        hbox.addWidget(self.stop_enable)
        self.stop_enable.clicked.connect(self.handle_stop_enable)


        self.stop_button = QPushButton("STOP!")
        self.stop_button.clicked.connect(self.handle_stop)
        self.stop_button.setStyleSheet('QPushButton {background-color: gray }')
        hbox.addWidget(self.stop_button)
        hbox.addStretch(1)
        self.vbox.addLayout(hbox)
        self._widget.setLayout(self.vbox)

        #add stretch at end so all GUI elements are at top of dialog
        self.vbox.addStretch(1)
        
        self.flor_mode_cmd_sub    = rospy.Subscriber("/flor/controller/mode",              FlorControlMode,          self.florModeCallback)
Example #26
0
    def __init__(self,
                 topic,
                 msg_type,
                 show_only_rate=False,
                 masteruri=None,
                 use_ssh=False,
                 parent=None):
        '''
        Creates an input dialog.
        @param topic: the name of the topic
        @type topic: C{str}
        @param msg_type: the type of the topic
        @type msg_type: C{str}
        @raise Exception: if no topic class was found for the given type
        '''
        QDialog.__init__(self, parent=parent)
        self._masteruri = masteruri
        masteruri_str = '' if masteruri is None else '[%s]' % masteruri
        self.setObjectName(' - '.join(['EchoDialog', topic, masteruri_str]))
        self.setAttribute(Qt.WA_DeleteOnClose, True)
        self.setWindowFlags(Qt.Window)
        self.setWindowTitle('%s %s %s' %
                            ('Echo --- ' if not show_only_rate else 'Hz --- ',
                             topic, masteruri_str))
        self.resize(728, 512)
        self.verticalLayout = QVBoxLayout(self)
        self.verticalLayout.setObjectName("verticalLayout")
        self.verticalLayout.setContentsMargins(1, 1, 1, 1)
        self.mIcon = QIcon(":/icons/crystal_clear_prop_run_echo.png")
        self.setWindowIcon(self.mIcon)

        self.topic = topic
        self.show_only_rate = show_only_rate
        self.lock = threading.RLock()
        self.last_printed_count = 0
        self.msg_t0 = -1.
        self.msg_tn = 0
        self.times = []

        self.message_count = 0
        self._rate_message = ''
        self._scrapped_msgs = 0
        self._scrapped_msgs_sl = 0

        self._last_received_ts = 0
        self.receiving_hz = self.MESSAGE_HZ_LIMIT
        self.line_limit = self.MESSAGE_LINE_LIMIT

        self.field_filter_fn = None

        options = QWidget(self)
        if not show_only_rate:
            hLayout = QHBoxLayout(options)
            hLayout.setContentsMargins(1, 1, 1, 1)
            self.no_str_checkbox = no_str_checkbox = QCheckBox('Hide strings')
            no_str_checkbox.toggled.connect(self.on_no_str_checkbox_toggled)
            hLayout.addWidget(no_str_checkbox)
            self.no_arr_checkbox = no_arr_checkbox = QCheckBox('Hide arrays')
            no_arr_checkbox.toggled.connect(self.on_no_arr_checkbox_toggled)
            hLayout.addWidget(no_arr_checkbox)
            self.combobox_reduce_ch = QComboBox(self)
            self.combobox_reduce_ch.addItems(
                [str(self.MESSAGE_LINE_LIMIT), '0', '80', '256', '1024'])
            self.combobox_reduce_ch.activated[str].connect(
                self.combobox_reduce_ch_activated)
            self.combobox_reduce_ch.setEditable(True)
            self.combobox_reduce_ch.setToolTip(
                "Set maximum line width. 0 disables the limit.")
            hLayout.addWidget(self.combobox_reduce_ch)
            #      reduce_ch_label = QLabel('ch', self)
            #      hLayout.addWidget(reduce_ch_label)
            # add spacer
            spacerItem = QSpacerItem(515, 20, QSizePolicy.Expanding,
                                     QSizePolicy.Minimum)
            hLayout.addItem(spacerItem)
            # add combobox for displaying frequency of messages
            self.combobox_displ_hz = QComboBox(self)
            self.combobox_displ_hz.addItems([
                str(self.MESSAGE_HZ_LIMIT), '0', '0.1', '1', '50', '100',
                '1000'
            ])
            self.combobox_displ_hz.activated[str].connect(
                self.on_combobox_hz_activated)
            self.combobox_displ_hz.setEditable(True)
            hLayout.addWidget(self.combobox_displ_hz)
            displ_hz_label = QLabel('Hz', self)
            hLayout.addWidget(displ_hz_label)
            # add combobox for count of displayed messages
            self.combobox_msgs_count = QComboBox(self)
            self.combobox_msgs_count.addItems(
                [str(self.MAX_DISPLAY_MSGS), '0', '50', '100'])
            self.combobox_msgs_count.activated[str].connect(
                self.on_combobox_count_activated)
            self.combobox_msgs_count.setEditable(True)
            self.combobox_msgs_count.setToolTip(
                "Set maximum displayed message count. 0 disables the limit.")
            hLayout.addWidget(self.combobox_msgs_count)
            displ_count_label = QLabel('#', self)
            hLayout.addWidget(displ_count_label)
            # add topic control button for unsubscribe and subscribe
            self.topic_control_button = QToolButton(self)
            self.topic_control_button.setText('stop')
            self.topic_control_button.setIcon(
                QIcon(':/icons/deleket_deviantart_stop.png'))
            self.topic_control_button.clicked.connect(
                self.on_topic_control_btn_clicked)
            hLayout.addWidget(self.topic_control_button)
            # add clear button
            clearButton = QToolButton(self)
            clearButton.setText('clear')
            clearButton.clicked.connect(self.on_clear_btn_clicked)
            hLayout.addWidget(clearButton)
            self.verticalLayout.addWidget(options)

        self.display = QTextBrowser(self)
        self.display.setReadOnly(True)
        self.verticalLayout.addWidget(self.display)
        self.display.document().setMaximumBlockCount(500)
        self.max_displayed_msgs = self.MAX_DISPLAY_MSGS
        self._blocks_in_msg = None
        self.display.setOpenLinks(False)
        self.display.anchorClicked.connect(self._on_display_anchorClicked)

        self.status_label = QLabel('0 messages', self)
        self.verticalLayout.addWidget(self.status_label)

        # subscribe to the topic
        errmsg = ''
        try:
            self.__msg_class = message.get_message_class(msg_type)
            if not self.__msg_class:
                errmsg = "Cannot load message class for [%s]. Did you build messages?" % msg_type
#        raise Exception("Cannot load message class for [%s]. Did you build messages?"%msg_type)
        except Exception as e:
            self.__msg_class = None
            errmsg = "Cannot load message class for [%s]. Did you build messagest?\nError: %s" % (
                msg_type, e)
#      raise Exception("Cannot load message class for [%s]. Did you build messagest?\nError: %s"%(msg_type, e))
# variables for Subscriber
        self.msg_signal.connect(self._append_message)
        self.sub = None

        # vairables for SSH connection
        self.ssh_output_file = None
        self.ssh_error_file = None
        self.ssh_input_file = None
        self.text_signal.connect(self._append_text)
        self.text_hz_signal.connect(self._append_text_hz)
        self._current_msg = ''
        self._current_errmsg = ''
        self.text_error_signal.connect(self._append_error_text)

        # decide, which connection to open
        if use_ssh:
            self.__msg_class = None
            self._on_display_anchorClicked(QUrl(self._masteruri))
        elif self.__msg_class is None:
            errtxt = '<pre style="color:red; font-family:Fixedsys,Courier,monospace; padding:10px;">\n%s</pre>' % (
                errmsg)
            self.display.setText('<a href="%s">open using SSH</a>' %
                                 (masteruri))
            self.display.append(errtxt)
        else:
            self.sub = rospy.Subscriber(self.topic, self.__msg_class,
                                        self._msg_handle)

        self.print_hz_timer = QTimer()
        self.print_hz_timer.timeout.connect(self._on_calc_hz)
        self.print_hz_timer.start(1000)
    def __init__(self, context):
        #super(FootstepParamControlDialog, self).__init__(context)
        #self.setObjectName('FootstepParamControlDialog')
        super(FootstepParamControlWidget, self).__init__()
        self.name = 'FootstepParamControlWidget'
        
        #self._widget = QWidget()
        self._widget = context
        vbox = QVBoxLayout()

        ### STEP_COST_ESTIMATOR ########
        self.step_cost_vbox = QVBoxLayout()
   
        self.step_cost_groupbox = QGroupBox( "Step Cost Estimator" )
        self.step_cost_groupbox.setCheckable( True )
        self.step_cost_groupbox.setChecked(False)

        self.step_cost_combobox = QComboBox()

        self.step_cost_combobox.addItem( "Euclidean" )
        self.step_cost_combobox.addItem( "GPR" )       
        self.step_cost_combobox.addItem( "Map" ) 
        self.step_cost_combobox.addItem( "Boundary" )
        self.step_cost_combobox.addItem( "Dynamics" )
        
        self.step_cost_vbox.addWidget( self.step_cost_combobox )
       
        self.step_cost_groupbox.setLayout( self.step_cost_vbox )
 
        vbox.addWidget( self.step_cost_groupbox )

# #HARD       ### FOOTSTEP_SET ########
#        # parameters for discret footstep planning mode
#        vigir_atlas_control_msgs/VigirBehaviorStepData[] footstep_set            # set of footsteps (displacement vectors (in meter / rad))
#        float32[] footstep_cost                                         # cost for each footstep given in footstep set
#
# #HARD       ### LOAD_GPR_STEP_COST ########
#        # map step cost file
#        std_msgs/String map_step_cost_file
#
# #HARD       ### LOAD_MAP_STEP_COST ########
#        # destination of gpr file
#        std_msgs/String gpr_step_cost_file

        ### COLLISION_CHECK_TYPE ########
        self.collision_check_groupbox = QGroupBox( "Collision Check Type" )
        self.collision_check_groupbox.setCheckable( True )
        self.collision_check_groupbox.setChecked( False)

        self.collision_check_vbox = QVBoxLayout()
   
        self.collision_check_feet_checkbox = QCheckBox( "Feet" )      
        self.collision_check_vbox.addWidget( self.collision_check_feet_checkbox  )
        
        self.collision_check_ub_checkbox = QCheckBox( "Upper Body" )
        self.collision_check_vbox.addWidget( self.collision_check_ub_checkbox  )
        
        self.collision_check_fc_checkbox = QCheckBox( "Foot Contact Support" ) 
        self.collision_check_vbox.addWidget( self.collision_check_fc_checkbox  )

        self.collision_check_groupbox.setLayout( self.collision_check_vbox )
        
        vbox.addWidget( self.collision_check_groupbox )

        ### FOOT_SIZE ########
        self.foot_size_vbox = QVBoxLayout()
        
        self.foot_size_groupbox = QGroupBox( "Foot Size" )
        self.foot_size_groupbox.setCheckable( True )
        self.foot_size_groupbox.setChecked( False )

        self.foot_size_hbox = QHBoxLayout()

        self.foot_size_label = QLabel("Foot Size")
        self.foot_size_hbox.addWidget( self.foot_size_label )

        self.foot_size_x = QDoubleSpinBox()
        self.foot_size_x.setSingleStep(.01)
        self.foot_size_hbox.addWidget(self.foot_size_x)

        self.foot_size_y = QDoubleSpinBox()
        self.foot_size_y.setSingleStep(.01)
        self.foot_size_hbox.addWidget(self.foot_size_y)

        self.foot_size_z = QDoubleSpinBox()
        self.foot_size_z.setSingleStep(.01)
        self.foot_size_hbox.addWidget(self.foot_size_z)

        self.foot_size_vbox.addLayout( self.foot_size_hbox )
        
        self.foot_shift_hbox = QHBoxLayout()

        self.foot_shift_label = QLabel("Foot Origin Shift")
        self.foot_shift_hbox.addWidget( self.foot_shift_label )

        self.foot_shift_x = QDoubleSpinBox()
        self.foot_shift_x.setRange(-1.0, 1.0)
        self.foot_shift_x.setSingleStep(.01)
        self.foot_shift_hbox.addWidget(self.foot_shift_x)

        self.foot_shift_y = QDoubleSpinBox()
        self.foot_shift_y.setRange(-1.0, 1.0)
        self.foot_shift_y.setSingleStep(.01)
        self.foot_shift_hbox.addWidget(self.foot_shift_y)

        self.foot_shift_z = QDoubleSpinBox()
        self.foot_shift_z.setRange(-1.0, 1.0)
        self.foot_shift_z.setSingleStep(.01)
        self.foot_shift_hbox.addWidget(self.foot_shift_z)

        self.foot_size_vbox.addLayout( self.foot_shift_hbox )
    
        self.foot_size_groupbox.setLayout( self.foot_size_vbox )
        vbox.addWidget( self.foot_size_groupbox )

        ### UPPER_BODY_SIZE ########
            
        self.upper_vbox = QVBoxLayout()
   
        self.upper_groupbox = QGroupBox( "Upper Body Size" )
        self.upper_groupbox.setCheckable( True )
        self.upper_groupbox.setChecked( False )
        
        self.upper_size_hbox = QHBoxLayout()

        self.upper_size_label = QLabel("Upper Body Size")
        self.upper_size_hbox.addWidget( self.upper_size_label )

        self.upper_size_x = QDoubleSpinBox()
        self.upper_size_x.setSingleStep(.01)
        self.upper_size_hbox.addWidget(self.upper_size_x)

        self.upper_size_y = QDoubleSpinBox()
        self.upper_size_y.setSingleStep(.01)
        self.upper_size_hbox.addWidget(self.upper_size_y)

        self.upper_size_z = QDoubleSpinBox()
        self.upper_size_z.setSingleStep(.01)
        self.upper_size_hbox.addWidget(self.upper_size_z)

        self.upper_vbox.addLayout( self.upper_size_hbox )
        
        self.upper_origin_hbox = QHBoxLayout()

        self.upper_origin_label = QLabel("Upper Body Origin")
        self.upper_origin_hbox.addWidget( self.upper_origin_label )

        self.upper_origin_x = QDoubleSpinBox()
        self.upper_origin_x.setRange(-1.0, 1.0)
        self.upper_origin_x.setSingleStep(.01)
        self.upper_origin_hbox.addWidget(self.upper_origin_x)

        self.upper_origin_y = QDoubleSpinBox()
        self.upper_origin_y.setRange(-1.0, 1.0)
        self.upper_origin_y.setSingleStep(.01)
        self.upper_origin_hbox.addWidget(self.upper_origin_y)

        self.upper_origin_z = QDoubleSpinBox()
        self.upper_origin_z.setRange(-1.0, 1.0)
        self.upper_origin_z.setSingleStep(.01)
        self.upper_origin_hbox.addWidget(self.upper_origin_z)

        self.upper_vbox.addLayout( self.upper_origin_hbox )
       
        self.upper_groupbox.setLayout( self.upper_vbox ) 
        vbox.addWidget( self.upper_groupbox )
    
        ### TERRAIN_MODEL ########
        self.terrain_model_groupbox = QGroupBox( "Terrain Model" )
        self.terrain_model_groupbox.setCheckable( True )
        self.terrain_model_groupbox.setChecked( False )

        self.terrain_model_vbox = QVBoxLayout()
        self.terrain_model_checkbox = QCheckBox( "Use Terrain Model" )      
        self.terrain_model_vbox.addWidget( self.terrain_model_checkbox )
        
        self.terrain_min_ssx_hbox = QHBoxLayout()
        
        self.terrain_min_ssx_label = QLabel("Min Sampling Steps x")
        self.terrain_min_ssx_hbox.addWidget( self.terrain_min_ssx_label )

        self.terrain_min_ssx_val = QDoubleSpinBox()
        self.terrain_min_ssx_val.setSingleStep(1)
        self.terrain_min_ssx_val.setRange(0,100)
        self.terrain_min_ssx_hbox.addWidget( self.terrain_min_ssx_val )

        self.terrain_model_vbox.addLayout( self.terrain_min_ssx_hbox )
    
        self.terrain_min_ssy_hbox = QHBoxLayout()
        
        self.terrain_min_ssy_label = QLabel("Min Sampling Steps y")
        self.terrain_min_ssy_hbox.addWidget( self.terrain_min_ssy_label )

        self.terrain_min_ssy_val = QDoubleSpinBox()
        self.terrain_min_ssy_val.setSingleStep(1)
        self.terrain_min_ssy_val.setRange(0,100)
        self.terrain_min_ssy_hbox.addWidget( self.terrain_min_ssy_val )

        self.terrain_model_vbox.addLayout( self.terrain_min_ssy_hbox )
        
        self.terrain_max_ssx_hbox = QHBoxLayout()
        
        self.terrain_max_ssx_label = QLabel("Max Sampling Steps x")
        self.terrain_max_ssx_hbox.addWidget( self.terrain_max_ssx_label )

        self.terrain_max_ssx_val = QDoubleSpinBox()
        self.terrain_max_ssx_val.setSingleStep(1)
        self.terrain_max_ssx_val.setRange(0,100)
        self.terrain_max_ssx_hbox.addWidget( self.terrain_max_ssx_val )

        self.terrain_model_vbox.addLayout( self.terrain_max_ssx_hbox )
    
        self.terrain_max_ssy_hbox = QHBoxLayout()
        
        self.terrain_max_ssy_label = QLabel("Max Sampling Steps y")
        self.terrain_max_ssy_hbox.addWidget( self.terrain_max_ssy_label )

        self.terrain_max_ssy_val = QDoubleSpinBox()
        self.terrain_max_ssy_val.setSingleStep(1)
        self.terrain_max_ssy_val.setRange(0,100)
        self.terrain_max_ssy_hbox.addWidget( self.terrain_max_ssy_val )

        self.terrain_model_vbox.addLayout( self.terrain_max_ssy_hbox )

        self.terrain_max_iz_hbox = QHBoxLayout()
        
        self.terrain_max_iz_label = QLabel("Max Intrusion z")
        self.terrain_max_iz_hbox.addWidget( self.terrain_max_iz_label )

        self.terrain_max_iz_val = QDoubleSpinBox()
        self.terrain_max_iz_val.setDecimals(4)
        self.terrain_max_iz_val.setSingleStep(.0001)
        self.terrain_max_iz_val.setRange(0,.25)
        self.terrain_max_iz_hbox.addWidget( self.terrain_max_iz_val )

        self.terrain_model_vbox.addLayout( self.terrain_max_iz_hbox )

        self.terrain_max_gc_hbox = QHBoxLayout()
        
        self.terrain_max_gc_label = QLabel("Max Ground Clearance")
        self.terrain_max_gc_hbox.addWidget( self.terrain_max_gc_label )

        self.terrain_max_gc_val = QDoubleSpinBox()
        self.terrain_max_gc_val.setDecimals(4)
        self.terrain_max_gc_val.setSingleStep(.0001)
        self.terrain_max_gc_val.setRange(0,.25)
        self.terrain_max_gc_hbox.addWidget( self.terrain_max_gc_val )

        self.terrain_model_vbox.addLayout( self.terrain_max_gc_hbox )

        self.terrain_ms_hbox = QHBoxLayout()
        
        self.terrain_ms_label = QLabel("Minimal Support")
        self.terrain_ms_hbox.addWidget( self.terrain_ms_label )

        self.terrain_ms_val = QDoubleSpinBox()
        self.terrain_ms_val.setDecimals(2)
        self.terrain_ms_val.setSingleStep(.01)
        self.terrain_ms_val.setRange(0,1)
        self.terrain_ms_hbox.addWidget( self.terrain_ms_val )

        self.terrain_model_vbox.addLayout( self.terrain_ms_hbox )

        self.terrain_model_groupbox.setLayout( self.terrain_model_vbox )
        
        vbox.addWidget( self.terrain_model_groupbox ) 

        ### STANDARD_STEP_PARAMS ########

        self.std_step_vbox = QVBoxLayout()

        self.std_step_groupbox = QGroupBox( "Standard Step Parameters" )
        self.std_step_groupbox.setCheckable( True )
        self.std_step_groupbox.setChecked( False )

        self.foot_sep_hbox = QHBoxLayout()
        
        self.foot_sep_label = QLabel("Foot Separation")
        self.foot_sep_hbox.addWidget( self.foot_sep_label )

        self.foot_sep_val = QDoubleSpinBox()
        self.foot_sep_val.setSingleStep(.01)
        self.foot_sep_hbox.addWidget(self.foot_sep_val)

        self.std_step_vbox.addLayout( self.foot_sep_hbox )

        self.std_step_step_duration_hbox = QHBoxLayout()
        
        self.std_step_step_duration_label = QLabel("Step Duration")
        self.std_step_step_duration_hbox.addWidget( self.std_step_step_duration_label )

        self.std_step_step_duration_val = QDoubleSpinBox()
        self.std_step_step_duration_val.setSingleStep(.01)
        self.std_step_step_duration_hbox.addWidget( self.std_step_step_duration_val )

        self.std_step_vbox.addLayout( self.std_step_step_duration_hbox )

        self.std_step_sway_duration_hbox = QHBoxLayout()
        
        self.std_step_sway_duration_label = QLabel("Sway Duration")
        self.std_step_sway_duration_hbox.addWidget( self.std_step_sway_duration_label )

        self.std_step_sway_duration_val = QDoubleSpinBox()
        self.std_step_sway_duration_val.setSingleStep(.01)
        self.std_step_sway_duration_hbox.addWidget( self.std_step_sway_duration_val )

        self.std_step_vbox.addLayout( self.std_step_sway_duration_hbox )

        self.std_step_swing_height_hbox = QHBoxLayout()
        
        self.std_step_swing_height_label = QLabel("Swing Height")
        self.std_step_swing_height_hbox.addWidget( self.std_step_swing_height_label )

        self.std_step_swing_height_val = QDoubleSpinBox()
        self.std_step_swing_height_val.setSingleStep(.01)
        self.std_step_swing_height_hbox.addWidget( self.std_step_swing_height_val )

        self.std_step_vbox.addLayout( self.std_step_swing_height_hbox )

        self.std_step_lift_height_hbox = QHBoxLayout()
        
        self.std_step_lift_height_label = QLabel("Lift Height")
        self.std_step_lift_height_hbox.addWidget( self.std_step_lift_height_label )

        self.std_step_lift_height_val = QDoubleSpinBox()
        self.std_step_lift_height_val.setSingleStep(.01)
        self.std_step_lift_height_hbox.addWidget( self.std_step_lift_height_val )

        self.std_step_vbox.addLayout( self.std_step_lift_height_hbox )
       
        self.std_step_groupbox.setLayout( self.std_step_vbox ) 
        vbox.addWidget( self.std_step_groupbox )

        button_hbox = QHBoxLayout()
        
        button_get = QPushButton("Get Current Values")
        button_hbox.addWidget( button_get )

        button_submit = QPushButton("Send Values")
        button_hbox.addWidget( button_submit)

        vbox.addLayout( button_hbox )

        vbox.addStretch(1)

        self._widget.setLayout(vbox)

        #context.add_widget(self._widget)

        # publishers and subscribers

        self.param_pub = rospy.Publisher('/flor/footstep_planner/set_params', FootstepPlannerParams, queue_size=10)
        button_submit.pressed.connect(self.sendParams)

        self.param_sub = self.stateSubscriber   = rospy.Subscriber('/ros_footstep_planner/params', FootstepPlannerParams, self.getParamCallbackFcn)
        button_get.pressed.connect(self.getParams)
class QTopicWidget(QWidget):

    topic_changed_signal = Signal(str)

    def __init__(self, parent=None, topic_type=str(), is_action_topic=False):
        QWidget.__init__(self, parent)

        if is_action_topic:
            self.topic_type = topic_type + "Goal"
        else:
            self.topic_type = topic_type
        self.is_action_topic = is_action_topic

        # start widget
        hbox = QHBoxLayout()
        hbox.setMargin(0)
        hbox.setContentsMargins(0, 0, 0, 0)

        # topic combo box
        self.topic_combo_box = QComboBox()
        self.topic_combo_box.setEnabled(False)
        self.topic_combo_box.blockSignals(True)
        self.topic_combo_box.setValidator(
            QRegExpValidator(QRegExp('((\d|\w|/)(?!//))*'), self))
        self.topic_combo_box.currentIndexChanged[str].connect(
            self.topic_changed)
        hbox.addWidget(self.topic_combo_box)

        # get system icon
        icon = QIcon.fromTheme("view-refresh")
        size = icon.actualSize(QSize(32, 32))

        # add refresh button
        refresh_topics_button = QPushButton()
        refresh_topics_button.clicked.connect(self.update_topic_list)
        refresh_topics_button.setIcon(icon)
        refresh_topics_button.setFixedSize(size.width() + 2, size.height() + 2)
        hbox.addWidget(refresh_topics_button)

        # end widget
        self.setLayout(hbox)

        # init widget
        self.update_topic_list()

    def emit_topic_name(self):
        self.topic_changed_signal.emit(self.current_topic())

    def set_editable(self, enable):
        self.topic_combo_box.setEditable(enable)

    def current_topic(self):
        if self.topic_combo_box.isEnabled():
            return self.topic_combo_box.currentText()
        else:
            return str()

    @Slot(str)
    def topic_changed(self, topic_name):
        self.topic_changed_signal.emit(topic_name)

    @Slot()
    def update_topic_list(self):
        self.topic_combo_box.clear()
        self.topic_combo_box.setEnabled(False)
        self.topic_combo_box.blockSignals(True)
        self.topic_combo_box.addItem('Updating...')

        # get topic list
        _, _, topic_type = rospy.get_master().getTopicTypes()
        topic_dict = dict(topic_type)
        # filter list
        topic_dict_filtered = dict()
        for k, v in topic_dict.items():
            if (len(topic_type) == 0) or (v == self.topic_type):
                if self.is_action_topic:
                    topic_dict_filtered[k[:-5]] = v
                else:
                    topic_dict_filtered[k] = v

        self.topic_combo_box.clear()
        self.topic_combo_box.addItems(sorted(topic_dict_filtered.keys()))

        if self.topic_combo_box.count() > 0:
            self.topic_combo_box.setEnabled(True)
            self.topic_combo_box.blockSignals(False)
            self.topic_changed(self.topic_combo_box.currentText())
        else:
            self.topic_combo_box.addItem('No topics available!')
class QParameterSetSelectionWidget(QWidgetWithLogger):

    NO_PARAM_SET_TEXT = "No parameters available!"
    SELECT_TEXT = "<Select>"

    param_cleared_signal = Signal()
    param_changed_signal = Signal(str)

    def __init__(self, parent = None, logger = Logger()):
        QWidgetWithLogger.__init__(self, parent, logger)

        # start widget
        hbox = QHBoxLayout()
        hbox.setMargin(0)
        hbox.setContentsMargins(0, 0, 0, 0)

        # get system icon
        icon = QIcon.fromTheme("view-refresh")
        size = icon.actualSize(QSize(32, 32))

        # add combo box
        self.parameter_set_names_combo_box = QComboBox()
        self.parameter_set_names_combo_box.currentIndexChanged[str].connect(self.param_changed)
        hbox.addWidget(self.parameter_set_names_combo_box)

        # add refresh button
        self.get_all_parameter_set_names_button = QPushButton()
        self.get_all_parameter_set_names_button.clicked.connect(self._get_all_parameter_set_names)

        self.get_all_parameter_set_names_button.setIcon(icon)
        self.get_all_parameter_set_names_button.setFixedSize(size.width()+2, size.height()+2)

        hbox.addWidget(self.get_all_parameter_set_names_button)

        # end widget
        self.setLayout(hbox)

        # init widget
        self.reset_parameter_set_selection()

    def _init_action_client(self, topic_name):
        self.get_parameter_set_names_client = actionlib.SimpleActionClient(topic_name, GetParameterSetNamesAction)
        print "Parameter set topic changed: " + topic_name

    @Slot(str)
    def set_topic_name(self, topic_name):
        if (len(topic_name) > 0):
            self._init_action_client(topic_name)
            self._get_all_parameter_set_names()
        else:
            self.reset_parameter_set_selection()

    def reset_parameter_set_selection(self):
        self.parameter_set_names_combo_box.setEnabled(False)
        self.parameter_set_names_combo_box.blockSignals(True)
        self.parameter_set_names_combo_box.clear()
        self.parameter_set_names_combo_box.addItem(self.NO_PARAM_SET_TEXT)
        self.get_all_parameter_set_names_button.setEnabled(False)
        self.param_cleared_signal.emit()

    def current_parameter_set_name(self):
        if self.parameter_set_names_combo_box.currentText() == self.NO_PARAM_SET_TEXT:
            return str()
        else:
            return self.parameter_set_names_combo_box.currentText()

    @Slot(str)
    def param_changed(self, name):
        self.param_changed_signal.emit(name)

    # parameter set names handler
    def _get_all_parameter_set_names(self):
        if (self.get_parameter_set_names_client.wait_for_server(rospy.Duration(0.5))):
            self.logger.log_info("Requesting current list of parameter set names.")
            goal = GetParameterSetNamesGoal()
            self.get_parameter_set_names_client.send_goal(goal)

            # waiting for getting list of parameter set names
            if (self.get_parameter_set_names_client.wait_for_result(rospy.Duration(1.0))):
                result = self.get_parameter_set_names_client.get_result()

                self.logger.log_info("Received " + str(len(result.names)) + " parameter set names.")

                self.parameter_set_names_combo_box.blockSignals(True)
                self.parameter_set_names_combo_box.clear()
                self.parameter_set_names_combo_box.addItem(self.SELECT_TEXT)
                self.parameter_set_names_combo_box.setItemData(0, 0, Qt.UserRole-1)
                self.param_cleared_signal.emit()

                for name in result.names:
                    self.parameter_set_names_combo_box.addItem(name.data)

                self.parameter_set_names_combo_box.setEnabled(True)
                self.parameter_set_names_combo_box.blockSignals(False)
                self.get_all_parameter_set_names_button.setEnabled(True)
            else:
                self.logger.log_error("Didn't received any results. Check communcation!")
                self.reset_parameter_set_selection()
        else:
            self.logger.log_error("Can't connect to footstep planner parameter action server!")
            self.reset_parameter_set_selection()        
Example #30
0
    def __init__(self, topic, msg_type, show_only_rate=False, masteruri=None, use_ssh=False, parent=None):
        """
        Creates an input dialog.
        @param topic: the name of the topic
        @type topic: C{str}
        @param msg_type: the type of the topic
        @type msg_type: C{str}
        @raise Exception: if no topic class was found for the given type
        """
        QDialog.__init__(self, parent=parent)
        self._masteruri = masteruri
        masteruri_str = "" if masteruri is None else "[%s]" % masteruri
        self.setObjectName(" - ".join(["EchoDialog", topic, masteruri_str]))
        self.setAttribute(Qt.WA_DeleteOnClose, True)
        self.setWindowFlags(Qt.Window)
        self.setWindowTitle("%s %s %s" % ("Echo --- " if not show_only_rate else "Hz --- ", topic, masteruri_str))
        self.resize(728, 512)
        self.verticalLayout = QVBoxLayout(self)
        self.verticalLayout.setObjectName("verticalLayout")
        self.verticalLayout.setContentsMargins(1, 1, 1, 1)
        self.mIcon = QIcon(":/icons/crystal_clear_prop_run_echo.png")
        self.setWindowIcon(self.mIcon)

        self.topic = topic
        self.show_only_rate = show_only_rate
        self.lock = threading.RLock()
        self.last_printed_count = 0
        self.msg_t0 = -1.0
        self.msg_tn = 0
        self.times = []

        self.message_count = 0
        self._rate_message = ""
        self._scrapped_msgs = 0
        self._scrapped_msgs_sl = 0

        self._last_received_ts = 0
        self.receiving_hz = self.MESSAGE_HZ_LIMIT
        self.line_limit = self.MESSAGE_LINE_LIMIT

        self.field_filter_fn = None

        options = QWidget(self)
        if not show_only_rate:
            hLayout = QHBoxLayout(options)
            hLayout.setContentsMargins(1, 1, 1, 1)
            self.no_str_checkbox = no_str_checkbox = QCheckBox("Hide strings")
            no_str_checkbox.toggled.connect(self.on_no_str_checkbox_toggled)
            hLayout.addWidget(no_str_checkbox)
            self.no_arr_checkbox = no_arr_checkbox = QCheckBox("Hide arrays")
            no_arr_checkbox.toggled.connect(self.on_no_arr_checkbox_toggled)
            hLayout.addWidget(no_arr_checkbox)
            self.combobox_reduce_ch = QComboBox(self)
            self.combobox_reduce_ch.addItems([str(self.MESSAGE_LINE_LIMIT), "0", "80", "256", "1024"])
            self.combobox_reduce_ch.activated[str].connect(self.combobox_reduce_ch_activated)
            self.combobox_reduce_ch.setEditable(True)
            self.combobox_reduce_ch.setToolTip("Set maximum line width. 0 disables the limit.")
            hLayout.addWidget(self.combobox_reduce_ch)
            #      reduce_ch_label = QLabel('ch', self)
            #      hLayout.addWidget(reduce_ch_label)
            # add spacer
            spacerItem = QSpacerItem(515, 20, QSizePolicy.Expanding, QSizePolicy.Minimum)
            hLayout.addItem(spacerItem)
            # add combobox for displaying frequency of messages
            self.combobox_displ_hz = QComboBox(self)
            self.combobox_displ_hz.addItems([str(self.MESSAGE_HZ_LIMIT), "0", "0.1", "1", "50", "100", "1000"])
            self.combobox_displ_hz.activated[str].connect(self.on_combobox_hz_activated)
            self.combobox_displ_hz.setEditable(True)
            hLayout.addWidget(self.combobox_displ_hz)
            displ_hz_label = QLabel("Hz", self)
            hLayout.addWidget(displ_hz_label)
            # add combobox for count of displayed messages
            self.combobox_msgs_count = QComboBox(self)
            self.combobox_msgs_count.addItems([str(self.MAX_DISPLAY_MSGS), "0", "50", "100"])
            self.combobox_msgs_count.activated[str].connect(self.on_combobox_count_activated)
            self.combobox_msgs_count.setEditable(True)
            self.combobox_msgs_count.setToolTip("Set maximum displayed message count. 0 disables the limit.")
            hLayout.addWidget(self.combobox_msgs_count)
            displ_count_label = QLabel("#", self)
            hLayout.addWidget(displ_count_label)
            # add topic control button for unsubscribe and subscribe
            self.topic_control_button = QToolButton(self)
            self.topic_control_button.setText("stop")
            self.topic_control_button.setIcon(QIcon(":/icons/deleket_deviantart_stop.png"))
            self.topic_control_button.clicked.connect(self.on_topic_control_btn_clicked)
            hLayout.addWidget(self.topic_control_button)
            # add clear button
            clearButton = QToolButton(self)
            clearButton.setText("clear")
            clearButton.clicked.connect(self.on_clear_btn_clicked)
            hLayout.addWidget(clearButton)
            self.verticalLayout.addWidget(options)

        self.display = QTextBrowser(self)
        self.display.setReadOnly(True)
        self.verticalLayout.addWidget(self.display)
        self.display.document().setMaximumBlockCount(500)
        self.max_displayed_msgs = self.MAX_DISPLAY_MSGS
        self._blocks_in_msg = None
        self.display.setOpenLinks(False)
        self.display.anchorClicked.connect(self._on_display_anchorClicked)

        self.status_label = QLabel("0 messages", self)
        self.verticalLayout.addWidget(self.status_label)

        # subscribe to the topic
        errmsg = ""
        try:
            self.__msg_class = message.get_message_class(msg_type)
            if not self.__msg_class:
                errmsg = "Cannot load message class for [%s]. Did you build messages?" % msg_type
        #        raise Exception("Cannot load message class for [%s]. Did you build messages?"%msg_type)
        except Exception as e:
            self.__msg_class = None
            errmsg = "Cannot load message class for [%s]. Did you build messagest?\nError: %s" % (msg_type, e)
        #      raise Exception("Cannot load message class for [%s]. Did you build messagest?\nError: %s"%(msg_type, e))
        # variables for Subscriber
        self.msg_signal.connect(self._append_message)
        self.sub = None

        # vairables for SSH connection
        self.ssh_output_file = None
        self.ssh_error_file = None
        self.ssh_input_file = None
        self.text_signal.connect(self._append_text)
        self.text_hz_signal.connect(self._append_text_hz)
        self._current_msg = ""
        self._current_errmsg = ""
        self.text_error_signal.connect(self._append_error_text)

        # decide, which connection to open
        if use_ssh:
            self.__msg_class = None
            self._on_display_anchorClicked(QUrl(self._masteruri))
        elif self.__msg_class is None:
            errtxt = '<pre style="color:red; font-family:Fixedsys,Courier,monospace; padding:10px;">\n%s</pre>' % (
                errmsg
            )
            self.display.setText('<a href="%s">open using SSH</a>' % (masteruri))
            self.display.append(errtxt)
        else:
            self.sub = rospy.Subscriber(self.topic, self.__msg_class, self._msg_handle)

        self.print_hz_timer = QTimer()
        self.print_hz_timer.timeout.connect(self._on_calc_hz)
        self.print_hz_timer.start(1000)
Example #31
0
class NAODashboard(Dashboard):
    
    def setup(self, context):
        self.name = 'NAO Dashboard (%s)'%rosenv.get_master_uri()
        self.max_icon_size = QSize(50, 30)
        self.message = None

        self._dashboard_message = None
        self._last_dashboard_message_time = 0.0

        self._raw_byte = None
        self.digital_outs = [0, 0, 0]

        icons_path = path.join(roslib.packages.get_pkg_dir('nao_dashboard'), "icons/")

        self._robot_combobox = QComboBox()
        self._robot_combobox.setSizeAdjustPolicy(QComboBox.AdjustToContents)
        self._robot_combobox.setInsertPolicy(QComboBox.InsertAlphabetically)
        self._robot_combobox.setEditable(True)

        gobject.threads_init()
        dbus.glib.threads_init()
        self.robots = []
        self.sys_bus = dbus.SystemBus()
        self.avahi_server = dbus.Interface(self.sys_bus.get_object(avahi.DBUS_NAME, '/'), avahi.DBUS_INTERFACE_SERVER)

        self.sbrowser = dbus.Interface(self.sys_bus.get_object(avahi.DBUS_NAME, self.avahi_server.ServiceBrowserNew(avahi.IF_UNSPEC,
            avahi.PROTO_INET, '_naoqi._tcp', 'local', dbus.UInt32(0))), avahi.DBUS_INTERFACE_SERVICE_BROWSER)

        self.sbrowser.connect_to_signal("ItemNew", self.avahiNewItem)
        self.sbrowser.connect_to_signal("ItemRemove", self.avahiItemRemove)

        # Diagnostics
        self._monitor = MonitorDashWidget(self.context)

        # Rosout
        self._console = ConsoleDashWidget(self.context, minimal=False)

        ## Joint temperature
        self._temp_joint_button = StatusControl('Joint temperature', 'temperature_joints')

        ## CPU temperature
        self._temp_head_button = StatusControl('CPU temperature', 'temperature_head')

        ## Motors
        self._motors_button = Motors(self.context)

        ## Battery State
        self._power_state_ctrl = PowerStateControl('NAO Battery')

        self._agg_sub = rospy.Subscriber('diagnostics_agg', DiagnosticArray, self.new_diagnostic_message)
        self._last_dashboard_message_time = 0.0

    def get_widgets(self):
        return [ [self._robot_combobox], 
                [self._monitor, self._console, self._temp_joint_button, self._temp_head_button,
                 self._motors_button],
                [self._power_state_ctrl]
                ]

    def shutdown_dashboard(self):
        self._agg_sub.unregister()

    def new_diagnostic_message(self, msg):
        """
        callback to process dashboard_agg messages

        :param msg: dashboard_agg DashboardState message
        :type msg: pr2_msgs.msg.DashboardState
        """
        self._dashboard_message = msg
        self._last_dashboard_message_time = rospy.get_time()
        for status in msg.status:
            if status.name == '/Nao/Joints':
                highestTemp = ""
                lowestStiff = -1.0
                highestStiff = -1.0
                hotJoints = ""
                for kv in status.values:
                     if kv.key == 'Highest Temperature':
                         highestTemp = " (" + kv.value + "deg C)"
                     elif kv.key == 'Highest Stiffness':
                         highestStiff = float(kv.value)
                     elif kv.key == 'Lowest Stiffness without Hands':
                         lowestStiff = float(kv.value)
                     elif kv.key == 'Hot Joints':
                         hotJoints = str(kv.value)
                self.set_buttonStatus(self._temp_joint_button, status, "Joints: ", "%s %s"%(highestTemp, hotJoints))
                #if(lowestStiff < 0.0 or highestStiff < 0.0):
                    #self._motors_button.set_stale()
                    #self._motors_button.SetToolTip(wx.ToolTip("Stale"))
                #elif(lowestStiff > 0.9):
                    #self._motors_button.set_error()
                    #self._motors_button.SetToolTip(wx.ToolTip("Stiffness on"))
                #elif(highestStiff < 0.05):
                    #self._motors_button.set_ok()
                    #self._motors_button.SetToolTip(wx.ToolTip("Stiffness off"))
                #else:
                    #self._motors_button.set_warn()
                    #self._motors_button.SetToolTip(wx.ToolTip("Stiffness partially on (between %f and %f)" % (lowestStiff, highestStiff)))
            elif status.name == '/Nao/CPU':
                self.set_buttonStatus(self._temp_head_button, status, "CPU temperature: ")
            elif status.name == '/Nao/Battery/Battery':
                if status.level == 3:
                    self._power_state_ctrl.set_stale()
                else:
                    self._power_state_ctrl.set_power_state(status.values)

    def set_buttonStatus(self, button, status, statusPrefix = "", statusSuffix = ""):
        statusString = "Unknown"
        if status.level == DiagnosticStatus.OK:
            button.update_state(0)
            statusString = "OK"
        elif status.level == DiagnosticStatus.WARN:
            button.update_state(1)
            statusString = "Warn"
        elif status.level == DiagnosticStatus.ERROR:
            button.update_state(2)
            statusString = "Error"
        elif status.level == 3:
            button.update_state(3)
            statusString = "Stale"
        button.setToolTip(statusPrefix + statusString + statusSuffix)

    def avahiNewItem(self, interface, protocol, name, stype, domain, flags):
        self.avahi_server.ResolveService(interface, protocol, name, stype, 
            domain, avahi.PROTO_INET, dbus.UInt32(0), 
            reply_handler=self.service_resolved, error_handler=self.print_error)
        pass
    
    def avahiItemRemove(self, interface, protocol, name, stype, domain, flags):
        print "Remove"
        for robot in self.robots:
            if robot['name'] == str(name) and robot['address'] == str(address) and robot['port'] == int(port):
                self.robots.remove(robot)
        updateRobotCombobox();
      
    def service_resolved(self, interface, protocol, name, type, domain, host, aprotocol, address, port, txt, flags):
        self.robots.append({'name': str(name), 'address': str(address), 'port': int(port)})
        self.updateRobotCombobox()
        
    def updateRobotCombobox(self):
        selected = self._robot_combobox.currentText()
        for i in range(self._robot_combobox.count()):
            self._robot_combobox.removeItem(i)
        id = -1
        for robot in self.robots:
            text = str(robot)
            text = "%s (%s:%d)" % (robot['name'], robot['address'], robot['port'])
            self._robot_combobox.addItem(text, '%s:%d' % (robot['address'], robot['port']))
            if(text == selected):
                id = self._robot_combobox.count()-1;
            
        if(self._robot_combobox.count() == 1):
            self._robot_combobox.setCurrentIndex(0)
        elif(id > -1):
            self._robot_combobox.setCurrentIndex(id)

        
    def print_error(self, *args):
        print 'error_handler'
        print args

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

    def restore_settings(self, plugin_settings, instance_settings):
        self._console.restore_settings(plugin_settings, instance_settings)
        self._monitor.restore_settings(plugin_settings, instance_settings)
    def __init__(self, parent=None):
        QDialog.__init__(self, parent)
#    self.host = host
        self.setWindowIcon(QIcon(":/icons/irondevil_sync.png"))
        self.setWindowTitle('Sync')
        self.verticalLayout = QVBoxLayout(self)
        self.verticalLayout.setObjectName("verticalLayout")
        self.resize(350, 190)

        self.toolButton_SyncAll = QToolButton(self)
        sizePolicy = QSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding)
        sizePolicy.setHorizontalStretch(0)
        sizePolicy.setVerticalStretch(2)
        sizePolicy.setHeightForWidth(self.toolButton_SyncAll.sizePolicy().hasHeightForWidth())
        self.toolButton_SyncAll.setSizePolicy(sizePolicy)
        self.toolButton_SyncAll.setObjectName("toolButton_SyncAll")
        self.verticalLayout.addWidget(self.toolButton_SyncAll)
        self.toolButton_SyncAll.setText(self._translate("Sync All"))
        self.toolButton_SyncAll.clicked.connect(self._on_sync_all_clicked)

#     self.toolButton_SyncAllAnyMsg = QToolButton(self)
#     sizePolicy = QSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding)
#     sizePolicy.setHorizontalStretch(0)
#     sizePolicy.setVerticalStretch(1)
#     sizePolicy.setHeightForWidth(self.toolButton_SyncAllAnyMsg.sizePolicy().hasHeightForWidth())
#     self.toolButton_SyncAllAnyMsg.setSizePolicy(sizePolicy)
#     self.toolButton_SyncAllAnyMsg.setObjectName("toolButton_SyncAllAnyMsg")
#     self.verticalLayout.addWidget(self.toolButton_SyncAllAnyMsg)
#     self.toolButton_SyncAllAnyMsg.setText(self._translate("Sync all (+AnyMsg)"))
#     self.toolButton_SyncAllAnyMsg.clicked.connect(self._on_sync_all_anymsg_clicked)

        self.toolButton_SyncTopicOnDemand = QToolButton(self)
        sizePolicy = QSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding)
        sizePolicy.setHorizontalStretch(0)
        sizePolicy.setVerticalStretch(1)
        sizePolicy.setHeightForWidth(self.toolButton_SyncTopicOnDemand.sizePolicy().hasHeightForWidth())
        self.toolButton_SyncTopicOnDemand.setSizePolicy(sizePolicy)
        self.toolButton_SyncTopicOnDemand.setObjectName("toolButton_SyncTopicOnDemand")
        self.verticalLayout.addWidget(self.toolButton_SyncTopicOnDemand)
        self.toolButton_SyncTopicOnDemand.setText(self._translate("Sync only topics on demand"))
        self.toolButton_SyncTopicOnDemand.clicked.connect(self._on_sync_topics_on_demand_clicked)

        self.toolButton_SelectInterface = QToolButton(self)
        sizePolicy = QSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding)
        sizePolicy.setHorizontalStretch(0)
        sizePolicy.setVerticalStretch(1)
        sizePolicy.setHeightForWidth(self.toolButton_SelectInterface.sizePolicy().hasHeightForWidth())
        self.toolButton_SelectInterface.setSizePolicy(sizePolicy)
        self.toolButton_SelectInterface.setObjectName("toolButton_SelectInterface")
        self.verticalLayout.addWidget(self.toolButton_SelectInterface)
        self.toolButton_SelectInterface.setText(self._translate("Select an interface"))
        self.toolButton_SelectInterface.clicked.connect(self._on_select_interface_clicked)

        self.interface_field = QComboBox(self)
        self.interface_field.setInsertPolicy(QComboBox.InsertAlphabetically)
        self.interface_field.setSizePolicy(QSizePolicy(QSizePolicy.Expanding, QSizePolicy.Fixed))
        self.interface_field.setEditable(True)
        self.interface_field.setVisible(False)
        self.interface_field.setObjectName("interface_field")
        self.verticalLayout.addWidget(self.interface_field)
        self.interface_field.currentIndexChanged[str].connect(self._on_interface_selected)

        self.toolButton_EditInterface = QToolButton(self)
        sizePolicy = QSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding)
        sizePolicy.setHorizontalStretch(0)
        sizePolicy.setVerticalStretch(1)
        sizePolicy.setHeightForWidth(self.toolButton_EditInterface.sizePolicy().hasHeightForWidth())
        self.toolButton_EditInterface.setSizePolicy(sizePolicy)
        self.toolButton_EditInterface.setObjectName("toolButton_EditInterface")
        self.verticalLayout.addWidget(self.toolButton_EditInterface)
        self.toolButton_EditInterface.setText(self._translate("Edit selected interface"))
        self.toolButton_EditInterface.clicked.connect(self._on_edit_interface_clicked)
        self.toolButton_EditInterface.setVisible(False)

        self.toolButton_CreateInterface = QToolButton(self)
        sizePolicy = QSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding)
        sizePolicy.setHorizontalStretch(0)
        sizePolicy.setVerticalStretch(1)
        sizePolicy.setHeightForWidth(self.toolButton_CreateInterface.sizePolicy().hasHeightForWidth())
        self.toolButton_CreateInterface.setSizePolicy(sizePolicy)
        self.toolButton_CreateInterface.setObjectName("toolButton_CreateInterface")
        self.verticalLayout.addWidget(self.toolButton_CreateInterface)
        self.toolButton_CreateInterface.setText(self._translate("Create an interface"))
        self.toolButton_CreateInterface.clicked.connect(self._on_create_interface_clicked)
        self.toolButton_CreateInterface.setVisible(False)

        self.textedit = TextEdit('', self)
        self.hl = SyncHighlighter(self.textedit.document())
        sizePolicy = QSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding)
        self.textedit.setSizePolicy(sizePolicy)
        self.textedit.setObjectName("syncedit")
        self.verticalLayout.addWidget(self.textedit)
        self.textedit.setVisible(False)

        self._fill_interface_thread = None
        self._interfaces_files = None
        self._sync_args = []
        self._interface_filename = None

        self.buttonBox = QDialogButtonBox(self)
        self.buttonBox.setStandardButtons(QDialogButtonBox.Cancel)
        self.buttonBox.setOrientation(Qt.Horizontal)
        self.buttonBox.setObjectName("buttonBox")
        self.verticalLayout.addWidget(self.buttonBox)
        self.buttonBox.accepted.connect(self.accept)
        self.buttonBox.rejected.connect(self.reject)
        self._new_iface = True
class ControlModeWidget:

    def __init__(self, context):
      
        self.control_mode =  0
        self.mode_pub = rospy.Publisher('/flor/controller/mode_command', VigirControlModeCommand, queue_size=10)

        self._widget = context
        self.vbox = QVBoxLayout()

        #Add input for setting the spindle speed
        list_label = QLabel("Select Control Mode")
        self.vbox.addWidget(list_label)

        # Indexed list of allowed control modes from feedback
        self.allowed_modes = rospy.get_param("/atlas_controller/allowed_control_modes")

        self.allowed_modes=rospy.get_param("/atlas_controller/allowed_control_modes")
        self.mode_ids={}
        self.mode_ids
        for ndx,txt in enumerate(self.allowed_modes):
            self.mode_ids[txt] = ndx

        # API 2.13 ordering
        self.bdi_mode_names=['NONE       ',        'FREEZE     ',        'STAND_PREP ', \
                             'STAND      ',        'WALK       ',        'STEP       ',        'MANIPULATE ', \
                             'USER       ',        'CALIBRATE  ']


        self.list_box = QListWidget(None)
        self.list_box.addItems(self.allowed_modes)

        self.list_box.currentItemChanged.connect(self.handle_selection_change)
        self.vbox.addWidget(self.list_box)

        self.selection_label = QLabel("Flor Selected: "+self.allowed_modes[0]+"("+str(self.control_mode)+")")
        self.vbox.addWidget(self.selection_label)

        self.label          = QLabel("Flor Command : "+self.allowed_modes[0]+"("+str(self.control_mode)+")")
        self.vbox.addWidget(self.label)

        self.flor_mode         = 0
        self.bdi_current_mode  = 0
        self.bdi_desired_mode  = 0
        self.flor_mode_label = QLabel("Flor Mode    : "+self.allowed_modes[self.flor_mode]+"("+str(self.flor_mode)+")"+"  BDI:("+str(self.bdi_current_mode)+", "+str(self.bdi_desired_mode)+")")
        self.vbox.addWidget(self.flor_mode_label)

        #Add combo box for available settings
        self.available_modes = QComboBox();
        self.available_modes.addItem("");
        self.available_modes.addItem("BDI");
        self.available_modes.addItem("Enable Upper Body");
        self.available_modes.addItem("Enable Whole Body");

        self.available_modes.currentIndexChanged.connect(self.handle_avail_modes_changed)
        self.vbox.addWidget(self.available_modes);
        
        self.vbox.addStretch(1)

        #Add Button for sending the behavior mode command
        self.push_button = QPushButton("Set Mode")
        self.push_button.clicked.connect(self.handle_set_mode)
        self.vbox.addWidget(self.push_button)

        self.vbox.addStretch(1)


        hbox = QHBoxLayout()
        hbox.addStretch(1)
        self.stop_enable= QCheckBox()
        self.stop_enable.setChecked(False)
        hbox.addWidget(self.stop_enable)
        self.stop_enable.clicked.connect(self.handle_stop_enable)


        self.stop_button = QPushButton("STOP!")
        self.stop_button.clicked.connect(self.handle_stop)
        self.stop_button.setStyleSheet('QPushButton {background-color: gray }')
        hbox.addWidget(self.stop_button)
        hbox.addStretch(1)
        self.vbox.addLayout(hbox)
        self._widget.setLayout(self.vbox)

        #add stretch at end so all GUI elements are at top of dialog
        self.vbox.addStretch(1)
        
        self.flor_mode_cmd_sub    = rospy.Subscriber("/flor/controller/mode",              FlorControlMode,          self.florModeCallback)

    def shutdown_plugin(self):
        print "Shutting down ..."
        self.flor_mode_cmd_sub.unregister()
        self.mode_pub.unregister()
        print "Done!"

    # Update BDI state
    def simStateCallback(self, state):
        if ((self.bdi_current_state != state.current_behavior) or (self.bdi_desired_state != state.desired_behavior) or (self.bdi_error_code != state.error_code) or (self.bdi_behavior_status != state.behavior_feedback.status_flags) ):
            self.bdi_current_state   = state.current_behavior
            self.bdi_desired_state   = state.desired_behavior
            self.bdi_error_code      = state.error_code
            self.bdi_behavior_status = state.behavior_feedback.status_flags
            if ((self.bdi_current_state < 0) or (self.bdi_current_state >= length(self.bdi_mode_names))):
                self.bdi_state_label.setText(  " BDI State : "+self.bdi_mode_names[0]+"("+str(self.bdi_current_state)+", " + str(self.bdi_desired_state) + ") EC:("+str(self.bdi_error_code)+", " + str(self.bdi_behavior_status) +")")
            else:
                self.bdi_state_label.setText(  " BDI State : "+self.bdi_mode_names[self.bdi_current_state]+"("+str(self.bdi_current_state)+", " + str(self.bdi_desired_state) + ") EC:("+str(self.bdi_error_code)+", " + str(self.bdi_behavior_status) +")")

    def simCommandCallback(self, bdi_cmd):
        if (self.bdi_behavior != bdi_cmd.behavior) :
            self.bdi_behavior  = bdi_cmd.behavior
            self.bdi_command_label.setText(" BDI Cmd   : "+self.bdi_mode_names[self.bdi_behavior]+"("+str(self.bdi_behavior)+")")

    def florModeCallback(self, cmd):
        if ( (self.flor_mode != cmd.control_mode) or (self.bdi_current_mode != cmd.bdi_current_behavior)  or (self.bdi_desired_mode != cmd.bdi_desired_behavior) ):
            
            if (self.flor_mode != cmd.control_mode) and (self.control_mode != cmd.control_mode):
                print "Flor mode changed externally - clear selection"
                self.clearSelections()
                self.selection_label.setText("Flor Selected  : ")
                self.label.setText("Flor Command : ")
                
            self.flor_mode          = cmd.control_mode
            self.bdi_current_mode   = cmd.bdi_current_behavior
            self.bdi_desired_mode   = cmd.bdi_desired_behavior
            print "Flor mode: ", self.flor_mode, "  BDI: ",self.bdi_current_mode,", ",self.bdi_desired_mode
            if (self.flor_mode > 250):
                print "Invalid control mode "
                self.flor_mode = 0
            #print "Allowed modes:"
            #print self.allowed_modes

            self.flor_mode_label.setText(" Flor Mode   : "+self.allowed_modes[self.flor_mode]+"("+str(self.flor_mode)+") BDI:("+str(self.bdi_current_mode)+","+str(self.bdi_desired_mode)+")")

    def clearSelections(self):
        for i in range(self.list_box.count()):
            item = self.list_box.item(i)
            self.list_box.setItemSelected(item, False)
        self.list_box.setCurrentRow(-1)
                    
    #Slot for selecting
    def handle_selection_change(self, curr, prev):
        if (curr != None):
            self.control_mode = self.mode_ids[curr.text()]
            self.selection_label.setText("Flor Selected  : "+curr.text()+"("+str(self.control_mode)+")")
        #else:
        #    print "NULL selection"
            
        #self.label.setText(self.allowed_modes[selected])
        #self.spindle_speed_pub.publish(data=math.radians(degree_per_sec))
    @Slot(bool)
    def handle_set_mode(self):
        print "Selected=",self.allowed_modes[self.control_mode], ' id=', self.control_mode
        self.label.setText("Flor Command : "+self.allowed_modes[self.control_mode]+"("+str(self.control_mode)+")")
        mode_msg = VigirControlModeCommand()
        mode_msg.header.stamp = rospy.Time.now()
        mode_msg.requested_control_mode  = self.control_mode
        print mode_msg
        self.mode_pub.publish(mode_msg)

    @Slot(bool)
    def handle_stop(self):
        # FLOR_STOP command
        if (self.stop_enable.isChecked()):
            self.clearSelections()
            self.selection_label.setText("Flor Selected  : ")
            self.control_mode = self.mode_ids['stop']
            print "Selected=",self.allowed_modes[self.control_mode], ' id=', self.control_mode
            #self.list_box
            self.selection_label.setText("Flor Selected  : "+self.allowed_modes[self.control_mode]+"("+str(self.control_mode)+")")
            self.label.setText("Flor Command : "+self.allowed_modes[self.control_mode]+"("+str(self.control_mode)+")")
            mode_msg = VigirControlModeCommand()
            mode_msg.header.stamp = rospy.Time.now()
            mode_msg.requested_control_mode     =  self.control_mode
            print mode_msg
            self.mode_pub.publish(mode_msg)
            
        else:
            print "Stop disabled!"

    @Slot(bool)
    def handle_stop_enable(self):
        if (self.stop_enable.isChecked()):
            self.stop_button.setStyleSheet('QPushButton {background-color: red }')
            #self.stop_enable.setChecked(False)
        else:
            self.stop_button.setStyleSheet('QPushButton {background-color: gray }')
            #self.stop_enable.setChecked(True)


    @Slot(bool)
    def handle_avail_modes_changed(self, index):
        print 'no longer mapping allowable modes'
        return
Example #34
0
class EchoDialog(QDialog):

    MESSAGE_LINE_LIMIT = 128
    MESSAGE_HZ_LIMIT = 10
    MAX_DISPLAY_MSGS = 25
    STATISTIC_QUEUE_LEN = 5000
    '''
  This dialog shows the output of a topic.
  '''

    finished_signal = Signal(str)
    '''
  finished_signal has as parameter the name of the topic and is emitted, if this
  dialog was closed.
  '''

    msg_signal = Signal(object, bool)
    '''
  msg_signal is a signal, which is emitted, if a new message was received.
  '''

    text_hz_signal = Signal(str)
    text_signal = Signal(str)
    '''
  text_signal is a signal, which is emitted, if a new text to display was received.
  '''

    text_error_signal = Signal(str)
    '''
  text_error_signal is a signal, which is emitted, if a new error text to display was received.
  '''

    request_pw = Signal(object)

    def __init__(self,
                 topic,
                 msg_type,
                 show_only_rate=False,
                 masteruri=None,
                 use_ssh=False,
                 parent=None):
        '''
        Creates an input dialog.
        @param topic: the name of the topic
        @type topic: C{str}
        @param msg_type: the type of the topic
        @type msg_type: C{str}
        @raise Exception: if no topic class was found for the given type
        '''
        QDialog.__init__(self, parent=parent)
        self._masteruri = masteruri
        masteruri_str = '' if masteruri is None else '[%s]' % masteruri
        self.setObjectName(' - '.join(['EchoDialog', topic, masteruri_str]))
        self.setAttribute(Qt.WA_DeleteOnClose, True)
        self.setWindowFlags(Qt.Window)
        self.setWindowTitle('%s %s %s' %
                            ('Echo --- ' if not show_only_rate else 'Hz --- ',
                             topic, masteruri_str))
        self.resize(728, 512)
        self.verticalLayout = QVBoxLayout(self)
        self.verticalLayout.setObjectName("verticalLayout")
        self.verticalLayout.setContentsMargins(1, 1, 1, 1)
        self.mIcon = QIcon(":/icons/crystal_clear_prop_run_echo.png")
        self.setWindowIcon(self.mIcon)

        self.topic = topic
        self.show_only_rate = show_only_rate
        self.lock = threading.RLock()
        self.last_printed_count = 0
        self.msg_t0 = -1.
        self.msg_tn = 0
        self.times = []

        self.message_count = 0
        self._rate_message = ''
        self._scrapped_msgs = 0
        self._scrapped_msgs_sl = 0

        self._last_received_ts = 0
        self.receiving_hz = self.MESSAGE_HZ_LIMIT
        self.line_limit = self.MESSAGE_LINE_LIMIT

        self.field_filter_fn = None

        options = QWidget(self)
        if not show_only_rate:
            hLayout = QHBoxLayout(options)
            hLayout.setContentsMargins(1, 1, 1, 1)
            self.no_str_checkbox = no_str_checkbox = QCheckBox('Hide strings')
            no_str_checkbox.toggled.connect(self.on_no_str_checkbox_toggled)
            hLayout.addWidget(no_str_checkbox)
            self.no_arr_checkbox = no_arr_checkbox = QCheckBox('Hide arrays')
            no_arr_checkbox.toggled.connect(self.on_no_arr_checkbox_toggled)
            hLayout.addWidget(no_arr_checkbox)
            self.combobox_reduce_ch = QComboBox(self)
            self.combobox_reduce_ch.addItems(
                [str(self.MESSAGE_LINE_LIMIT), '0', '80', '256', '1024'])
            self.combobox_reduce_ch.activated[str].connect(
                self.combobox_reduce_ch_activated)
            self.combobox_reduce_ch.setEditable(True)
            self.combobox_reduce_ch.setToolTip(
                "Set maximum line width. 0 disables the limit.")
            hLayout.addWidget(self.combobox_reduce_ch)
            #      reduce_ch_label = QLabel('ch', self)
            #      hLayout.addWidget(reduce_ch_label)
            # add spacer
            spacerItem = QSpacerItem(515, 20, QSizePolicy.Expanding,
                                     QSizePolicy.Minimum)
            hLayout.addItem(spacerItem)
            # add combobox for displaying frequency of messages
            self.combobox_displ_hz = QComboBox(self)
            self.combobox_displ_hz.addItems([
                str(self.MESSAGE_HZ_LIMIT), '0', '0.1', '1', '50', '100',
                '1000'
            ])
            self.combobox_displ_hz.activated[str].connect(
                self.on_combobox_hz_activated)
            self.combobox_displ_hz.setEditable(True)
            hLayout.addWidget(self.combobox_displ_hz)
            displ_hz_label = QLabel('Hz', self)
            hLayout.addWidget(displ_hz_label)
            # add combobox for count of displayed messages
            self.combobox_msgs_count = QComboBox(self)
            self.combobox_msgs_count.addItems(
                [str(self.MAX_DISPLAY_MSGS), '0', '50', '100'])
            self.combobox_msgs_count.activated[str].connect(
                self.on_combobox_count_activated)
            self.combobox_msgs_count.setEditable(True)
            self.combobox_msgs_count.setToolTip(
                "Set maximum displayed message count. 0 disables the limit.")
            hLayout.addWidget(self.combobox_msgs_count)
            displ_count_label = QLabel('#', self)
            hLayout.addWidget(displ_count_label)
            # add topic control button for unsubscribe and subscribe
            self.topic_control_button = QToolButton(self)
            self.topic_control_button.setText('stop')
            self.topic_control_button.setIcon(
                QIcon(':/icons/deleket_deviantart_stop.png'))
            self.topic_control_button.clicked.connect(
                self.on_topic_control_btn_clicked)
            hLayout.addWidget(self.topic_control_button)
            # add clear button
            clearButton = QToolButton(self)
            clearButton.setText('clear')
            clearButton.clicked.connect(self.on_clear_btn_clicked)
            hLayout.addWidget(clearButton)
            self.verticalLayout.addWidget(options)

        self.display = QTextBrowser(self)
        self.display.setReadOnly(True)
        self.verticalLayout.addWidget(self.display)
        self.display.document().setMaximumBlockCount(500)
        self.max_displayed_msgs = self.MAX_DISPLAY_MSGS
        self._blocks_in_msg = None
        self.display.setOpenLinks(False)
        self.display.anchorClicked.connect(self._on_display_anchorClicked)

        self.status_label = QLabel('0 messages', self)
        self.verticalLayout.addWidget(self.status_label)

        # subscribe to the topic
        errmsg = ''
        try:
            self.__msg_class = message.get_message_class(msg_type)
            if not self.__msg_class:
                errmsg = "Cannot load message class for [%s]. Did you build messages?" % msg_type
#        raise Exception("Cannot load message class for [%s]. Did you build messages?"%msg_type)
        except Exception as e:
            self.__msg_class = None
            errmsg = "Cannot load message class for [%s]. Did you build messagest?\nError: %s" % (
                msg_type, e)
#      raise Exception("Cannot load message class for [%s]. Did you build messagest?\nError: %s"%(msg_type, e))
# variables for Subscriber
        self.msg_signal.connect(self._append_message)
        self.sub = None

        # vairables for SSH connection
        self.ssh_output_file = None
        self.ssh_error_file = None
        self.ssh_input_file = None
        self.text_signal.connect(self._append_text)
        self.text_hz_signal.connect(self._append_text_hz)
        self._current_msg = ''
        self._current_errmsg = ''
        self.text_error_signal.connect(self._append_error_text)

        # decide, which connection to open
        if use_ssh:
            self.__msg_class = None
            self._on_display_anchorClicked(QUrl(self._masteruri))
        elif self.__msg_class is None:
            errtxt = '<pre style="color:red; font-family:Fixedsys,Courier,monospace; padding:10px;">\n%s</pre>' % (
                errmsg)
            self.display.setText('<a href="%s">open using SSH</a>' %
                                 (masteruri))
            self.display.append(errtxt)
        else:
            self.sub = rospy.Subscriber(self.topic, self.__msg_class,
                                        self._msg_handle)

        self.print_hz_timer = QTimer()
        self.print_hz_timer.timeout.connect(self._on_calc_hz)
        self.print_hz_timer.start(1000)

#    print "======== create", self.objectName()
#
#  def __del__(self):
#    print "******* destroy", self.objectName()

#  def hideEvent(self, event):
#    self.close()

    def closeEvent(self, event):
        if self.sub is not None:
            self.sub.unregister()
            del self.sub
        try:
            self.ssh_output_file.close()
            self.ssh_error_file.close()
            # send Ctrl+C to remote process
            self.ssh_input_file.write('%s\n' % chr(3))
            self.ssh_input_file.close()
        except:
            pass
        self.finished_signal.emit(self.topic)
        if self.parent() is None:
            QApplication.quit()
#    else:
#      self.setParent(None)

    def create_field_filter(self, echo_nostr, echo_noarr):
        def field_filter(val):
            try:
                # fields = val.__slots__
                # field_types = val._slot_types
                for f, t in zip(val.__slots__, val._slot_types):
                    if echo_noarr and '[' in t:
                        continue
                    elif echo_nostr and 'string' in t:
                        continue
                    yield f
            except:
                pass

        return field_filter

    def on_no_str_checkbox_toggled(self, state):
        self.field_filter_fn = self.create_field_filter(
            state, self.no_arr_checkbox.isChecked())

    def on_no_arr_checkbox_toggled(self, state):
        self.field_filter_fn = self.create_field_filter(
            self.no_str_checkbox.isChecked(), state)

    def combobox_reduce_ch_activated(self, ch_txt):
        try:
            self.line_limit = int(ch_txt)
        except ValueError:
            try:
                self.line_limit = float(ch_txt)
            except ValueError:
                self.combobox_reduce_ch.setEditText(str(self.line_limit))

    def on_combobox_hz_activated(self, hz_txt):
        try:
            self.receiving_hz = int(hz_txt)
        except ValueError:
            try:
                self.receiving_hz = float(hz_txt)
            except ValueError:
                self.combobox_displ_hz.setEditText(str(self.receiving_hz))

    def on_combobox_count_activated(self, count_txt):
        try:
            self.max_displayed_msgs = int(count_txt)
            self._blocks_in_msg = None
        except ValueError:
            self.combobox_msgs_count.setEditText(str(self.max_displayed_msgs))

    def on_clear_btn_clicked(self):
        self.display.clear()
        with self.lock:
            self.message_count = 0
            self._scrapped_msgs = 0
            del self.times[:]

    def on_topic_control_btn_clicked(self):
        try:
            if self.sub is None and self.ssh_output_file is None:
                if self.__msg_class:
                    self.sub = rospy.Subscriber(self.topic, self.__msg_class,
                                                self._msg_handle)
                else:
                    self._on_display_anchorClicked(QUrl(self._masteruri))
                self.topic_control_button.setText('stop')
                self.topic_control_button.setIcon(
                    QIcon(':/icons/deleket_deviantart_stop.png'))
            else:
                if self.sub is not None:
                    self.sub.unregister()
                    self.sub = None
                elif self.ssh_output_file is not None:
                    self.ssh_output_file.close()
                    self.ssh_error_file.close()
                    self.ssh_output_file = None
                self.topic_control_button.setText('play')
                self.topic_control_button.setIcon(
                    QIcon(':/icons/deleket_deviantart_play.png'))
                self.no_str_checkbox.setEnabled(True)
                self.no_arr_checkbox.setEnabled(True)
        except Exception as e:
            rospy.logwarn('Error while stop/play echo for topic %s: %s' %
                          (self.topic, e))

    def _msg_handle(self, data):
        self.msg_signal.emit(data,
                             (data._connection_header['latching'] != '0'))

    def _append_message(self, msg, latched):
        '''
        Adds a label to the dialog's layout and shows the given text.
        @param msg: the text to add to the dialog
        @type msg: message object
        '''
        current_time = time.time()
        self._count_messages(current_time)
        # skip messages, if they are received often then MESSAGE_HZ_LIMIT
        if self._last_received_ts != 0 and self.receiving_hz != 0:
            if not latched and current_time - self._last_received_ts < 1.0 / self.receiving_hz:
                self._scrapped_msgs += 1
                self._scrapped_msgs_sl += 1
                return
        self._last_received_ts = current_time
        if not self.show_only_rate:
            # convert message to string and reduce line width to current limit
            msg = message.strify_message(msg,
                                         field_filter=self.field_filter_fn)
            if isinstance(msg, tuple):
                msg = msg[0]
            msg = self._trim_width(msg)
            msg = msg.replace('<', '&lt;').replace('>', '&gt;')
            # create a notification about scrapped messages
            if self._scrapped_msgs_sl > 0:
                txt = '<pre style="color:red; font-family:Fixedsys,Courier,monospace; padding:10px;">scrapped %s message because of Hz-settings</pre>' % self._scrapped_msgs_sl
                self.display.append(txt)
                self._scrapped_msgs_sl = 0
            txt = '<pre style="background-color:#FFFCCC; font-family:Fixedsys,Courier; padding:10px;">---------- %s --------------------\n%s</pre>' % (
                datetime.now().strftime("%d.%m.%Y %H:%M:%S.%f"), msg)
            # set the count of the displayed messages on receiving the first message
            self._update_max_msg_count(txt)
            self.display.append(txt)
        self._print_status()

    def _count_messages(self, ts=time.time()):
        '''
        Counts the received messages. Call this method only on receive message.
        '''
        current_time = ts
        with self.lock:
            # time reset
            if self.msg_t0 < 0 or self.msg_t0 > current_time:
                self.msg_t0 = current_time
                self.msg_tn = current_time
                self.times = []
            else:
                self.times.append(current_time - self.msg_tn)
                self.msg_tn = current_time
            # keep only statistics for the last 5000 messages so as not to run out of memory
            if len(self.times) > self.STATISTIC_QUEUE_LEN:
                self.times.pop(0)
            self.message_count += 1

    def _trim_width(self, msg):
        '''
        reduce line width to current limit
        :param msg: the message
        :type msg: str
        :return: trimmed message
        '''
        result = msg
        if self.line_limit != 0:
            a = ''
            for l in msg.splitlines():
                a = a + (l if len(l) <= self.line_limit else
                         l[0:self.line_limit - 3] + '...') + '\n'
            result = a
        return result

    def _update_max_msg_count(self, txt):
        '''
        set the count of the displayed messages on receiving the first message
        :param txt: text of the message, which will be added to the document
        :type txt: str
        '''
        if self._blocks_in_msg is None:
            td = QTextDocument(txt)
            self._blocks_in_msg = td.blockCount()
            self.display.document().setMaximumBlockCount(
                self._blocks_in_msg * self.max_displayed_msgs)

    def _on_calc_hz(self):
        if rospy.is_shutdown():
            self.close()
            return
        if self.message_count == self.last_printed_count:
            return
        with self.lock:
            # the code from ROS rostopic
            n = len(self.times)
            if n < 2:
                return
            mean = sum(self.times) / n
            rate = 1. / mean if mean > 0. else 0
            # std dev
            std_dev = math.sqrt(sum((x - mean)**2 for x in self.times) / n)
            # min and max
            max_delta = max(self.times)
            min_delta = min(self.times)
            self.last_printed_count = self.message_count
            self._rate_message = "average rate: %.3f\tmin: %.3fs   max: %.3fs   std dev: %.5fs   window: %s" % (
                rate, min_delta, max_delta, std_dev, n + 1)
            if self._scrapped_msgs > 0:
                self._rate_message += " --- scrapped msgs: %s" % self._scrapped_msgs
            self._print_status()
            if self.show_only_rate:
                self.display.append(self._rate_message)

    def _print_status(self):
        self.status_label.setText('%s messages   %s' %
                                  (self.message_count, self._rate_message))

    def _append_text(self, text):
        '''
        Append echo text received through the SSH.
        '''
        with self.lock:
            self._current_msg += text
            if self._current_msg.find('---') != -1:
                messages = self._current_msg.split('---')
                for m in messages[:-1]:
                    current_time = time.time()
                    self._count_messages(current_time)
                    # limit the displayed text width
                    m = self._trim_width(m)
                    txt = '<pre style="background-color:#FFFCCC; font-family:Fixedsys,Courier; padding:10px;">---------- %s --------------------\n%s</pre>' % (
                        datetime.now().strftime("%d.%m.%Y %H:%M:%S.%f"), m)
                    # set the count of the displayed messages on receiving the first message
                    self._update_max_msg_count(txt)
                    self.display.append(txt)
                self._current_msg = messages[-1]
            self._print_status()

    def _append_error_text(self, text):
        '''
        Append error text received through the SSH.
        '''
        with self.lock:
            self._current_errmsg += text
            if self._current_errmsg.find('\n') != -1:
                messages = self._current_errmsg.split('\n')
                for m in messages[:-1]:
                    txt = '<pre style="color:red; font-family:Fixedsys,Courier,monospace; padding:10px;">%s</pre>' % m
                    self.display.append(txt)
                self._current_errmsg = messages[-1]

    def _append_text_hz(self, text):
        '''
        Append text received through the SSH for hz view.
        '''
        with self.lock:
            self._current_msg += text
            if self._current_msg.find('\n') != -1:
                messages = self._current_msg.split('\n')
                for m in messages[:-1]:
                    txt = '<div style="font-family:Fixedsys,Courier;">%s</div>' % (
                        m)
                    self.display.append(txt)
                self._current_msg = messages[-1]

    def _on_display_anchorClicked(self, url, user=None, pw=None):
        try:
            ok = False
            if self.show_only_rate:
                self.ssh_input_file, self.ssh_output_file, self.ssh_error_file, ok = nm.ssh(
                ).ssh_exec(url.host(), ['rostopic hz %s' % (self.topic)],
                           user,
                           pw,
                           auto_pw_request=True,
                           get_pty=True)
                self.status_label.setText('connected to %s over SSH' %
                                          url.host())
            else:
                self.combobox_displ_hz.setEnabled(False)
                nostr = '--nostr' if self.no_str_checkbox.isChecked() else ''
                noarr = '--noarr' if self.no_arr_checkbox.isChecked() else ''
                self.ssh_input_file, self.ssh_output_file, self.ssh_error_file, ok = nm.ssh(
                ).ssh_exec(
                    url.host(),
                    ['rostopic echo %s %s %s' % (nostr, noarr, self.topic)],
                    user,
                    pw,
                    auto_pw_request=True,
                    get_pty=True)
            if ok:
                self.display.clear()
                target = self._read_output_hz if self.show_only_rate else self._read_output
                thread = threading.Thread(target=target,
                                          args=((self.ssh_output_file, )))
                thread.setDaemon(True)
                thread.start()
                thread = threading.Thread(target=self._read_error,
                                          args=((self.ssh_error_file, )))
                thread.setDaemon(True)
                thread.start()
            elif self.ssh_output_file:
                self.ssh_output_file.close()
                self.ssh_error_file.close()
        except Exception as e:
            self._append_error_text('%s\n' % e)
#      import traceback
#      print traceback.format_exc()

    def _read_output_hz(self, output_file):
        try:
            while not output_file.closed:
                text = output_file.read(1)
                if text:
                    self.text_hz_signal.emit(text)
        except:
            pass
#      import traceback
#      print traceback.format_exc()

    def _read_output(self, output_file):
        while not output_file.closed:
            text = output_file.read(1)
            if text:
                self.text_signal.emit(text)

    def _read_error(self, error_file):
        try:
            while not error_file.closed:
                text = error_file.read(1)
                if text:
                    self.text_error_signal.emit(text)
        except:
            pass
Example #35
0
class SyncDialog(QDialog):
    '''
    A dialog to set the sync options.
    '''
    def __init__(self, parent=None):
        QDialog.__init__(self, parent)
        #    self.host = host
        self.setWindowIcon(QIcon(":/icons/irondevil_sync.png"))
        self.setWindowTitle('Sync')
        self.verticalLayout = QVBoxLayout(self)
        self.verticalLayout.setObjectName("verticalLayout")
        self.resize(350, 190)

        self.toolButton_SyncAll = QToolButton(self)
        sizePolicy = QSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding)
        sizePolicy.setHorizontalStretch(0)
        sizePolicy.setVerticalStretch(2)
        sizePolicy.setHeightForWidth(
            self.toolButton_SyncAll.sizePolicy().hasHeightForWidth())
        self.toolButton_SyncAll.setSizePolicy(sizePolicy)
        self.toolButton_SyncAll.setObjectName("toolButton_SyncAll")
        self.verticalLayout.addWidget(self.toolButton_SyncAll)
        self.toolButton_SyncAll.setText(self._translate("Sync All"))
        self.toolButton_SyncAll.clicked.connect(self._on_sync_all_clicked)

        #     self.toolButton_SyncAllAnyMsg = QToolButton(self)
        #     sizePolicy = QSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding)
        #     sizePolicy.setHorizontalStretch(0)
        #     sizePolicy.setVerticalStretch(1)
        #     sizePolicy.setHeightForWidth(self.toolButton_SyncAllAnyMsg.sizePolicy().hasHeightForWidth())
        #     self.toolButton_SyncAllAnyMsg.setSizePolicy(sizePolicy)
        #     self.toolButton_SyncAllAnyMsg.setObjectName("toolButton_SyncAllAnyMsg")
        #     self.verticalLayout.addWidget(self.toolButton_SyncAllAnyMsg)
        #     self.toolButton_SyncAllAnyMsg.setText(self._translate("Sync all (+AnyMsg)"))
        #     self.toolButton_SyncAllAnyMsg.clicked.connect(self._on_sync_all_anymsg_clicked)

        self.toolButton_SyncTopicOnDemand = QToolButton(self)
        sizePolicy = QSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding)
        sizePolicy.setHorizontalStretch(0)
        sizePolicy.setVerticalStretch(1)
        sizePolicy.setHeightForWidth(
            self.toolButton_SyncTopicOnDemand.sizePolicy().hasHeightForWidth())
        self.toolButton_SyncTopicOnDemand.setSizePolicy(sizePolicy)
        self.toolButton_SyncTopicOnDemand.setObjectName(
            "toolButton_SyncTopicOnDemand")
        self.verticalLayout.addWidget(self.toolButton_SyncTopicOnDemand)
        self.toolButton_SyncTopicOnDemand.setText(
            self._translate("Sync only topics on demand"))
        self.toolButton_SyncTopicOnDemand.clicked.connect(
            self._on_sync_topics_on_demand_clicked)

        self.toolButton_SelectInterface = QToolButton(self)
        sizePolicy = QSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding)
        sizePolicy.setHorizontalStretch(0)
        sizePolicy.setVerticalStretch(1)
        sizePolicy.setHeightForWidth(
            self.toolButton_SelectInterface.sizePolicy().hasHeightForWidth())
        self.toolButton_SelectInterface.setSizePolicy(sizePolicy)
        self.toolButton_SelectInterface.setObjectName(
            "toolButton_SelectInterface")
        self.verticalLayout.addWidget(self.toolButton_SelectInterface)
        self.toolButton_SelectInterface.setText(
            self._translate("Select an interface"))
        self.toolButton_SelectInterface.clicked.connect(
            self._on_select_interface_clicked)

        self.interface_field = QComboBox(self)
        self.interface_field.setInsertPolicy(QComboBox.InsertAlphabetically)
        self.interface_field.setSizePolicy(
            QSizePolicy(QSizePolicy.Expanding, QSizePolicy.Fixed))
        self.interface_field.setEditable(True)
        self.interface_field.setVisible(False)
        self.interface_field.setObjectName("interface_field")
        self.verticalLayout.addWidget(self.interface_field)
        self.interface_field.currentIndexChanged[str].connect(
            self._on_interface_selected)

        self.toolButton_EditInterface = QToolButton(self)
        sizePolicy = QSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding)
        sizePolicy.setHorizontalStretch(0)
        sizePolicy.setVerticalStretch(1)
        sizePolicy.setHeightForWidth(
            self.toolButton_EditInterface.sizePolicy().hasHeightForWidth())
        self.toolButton_EditInterface.setSizePolicy(sizePolicy)
        self.toolButton_EditInterface.setObjectName("toolButton_EditInterface")
        self.verticalLayout.addWidget(self.toolButton_EditInterface)
        self.toolButton_EditInterface.setText(
            self._translate("Edit selected interface"))
        self.toolButton_EditInterface.clicked.connect(
            self._on_edit_interface_clicked)
        self.toolButton_EditInterface.setVisible(False)

        self.toolButton_CreateInterface = QToolButton(self)
        sizePolicy = QSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding)
        sizePolicy.setHorizontalStretch(0)
        sizePolicy.setVerticalStretch(1)
        sizePolicy.setHeightForWidth(
            self.toolButton_CreateInterface.sizePolicy().hasHeightForWidth())
        self.toolButton_CreateInterface.setSizePolicy(sizePolicy)
        self.toolButton_CreateInterface.setObjectName(
            "toolButton_CreateInterface")
        self.verticalLayout.addWidget(self.toolButton_CreateInterface)
        self.toolButton_CreateInterface.setText(
            self._translate("Create an interface"))
        self.toolButton_CreateInterface.clicked.connect(
            self._on_create_interface_clicked)
        self.toolButton_CreateInterface.setVisible(False)

        self.textedit = TextEdit('', self)
        self.hl = SyncHighlighter(self.textedit.document())
        sizePolicy = QSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding)
        self.textedit.setSizePolicy(sizePolicy)
        self.textedit.setObjectName("syncedit")
        self.verticalLayout.addWidget(self.textedit)
        self.textedit.setVisible(False)

        self._fill_interface_thread = None
        self._interfaces_files = None
        self._sync_args = []
        self._interface_filename = None

        self.buttonBox = QDialogButtonBox(self)
        self.buttonBox.setStandardButtons(QDialogButtonBox.Cancel)
        self.buttonBox.setOrientation(Qt.Horizontal)
        self.buttonBox.setObjectName("buttonBox")
        self.verticalLayout.addWidget(self.buttonBox)
        self.buttonBox.accepted.connect(self.accept)
        self.buttonBox.rejected.connect(self.reject)
        self._new_iface = True

    def _translate(self, text):
        if hasattr(QApplication, "UnicodeUTF8"):
            return QApplication.translate("Form", text, None,
                                          QApplication.UnicodeUTF8)
        else:
            return QApplication.translate("Form", text, None)

    @property
    def sync_args(self):
        return self._sync_args

    @property
    def interface_filename(self):
        return self._interface_filename

    def _on_sync_all_clicked(self):
        self.setResult(QDialog.Accepted)
        self._sync_args = []
        self._sync_args.append(''.join(['_interface_url:=', "'.'"]))
        self._sync_args.append(''.join(['_sync_topics_on_demand:=', 'False']))
        self._sync_args.append(''.join(['_ignore_hosts:=', '[]']))
        self._sync_args.append(''.join(['_sync_hosts:=', '[]']))
        self._sync_args.append(''.join(['_ignore_nodes:=', '[]']))
        self._sync_args.append(''.join(['_sync_nodes:=', '[]']))
        self._sync_args.append(''.join(['_ignore_topics:=', '[]']))
        self._sync_args.append(''.join(['_ignore_publishers:=', '[]']))
        self._sync_args.append(''.join(['_ignore_subscribers:=', '[]']))
        self._sync_args.append(''.join(['_sync_topics:=', '[]']))
        self._sync_args.append(''.join(['_ignore_services:=', '[]']))
        self._sync_args.append(''.join(['_sync_services:=', '[]']))
        self._sync_args.append(''.join(['_sync_remote_nodes:=', 'False']))
        self._interface_filename = None
        self.accept()

#   def _on_sync_all_anymsg_clicked(self):
#     self._sync_args = []
#     self._sync_args.append(''.join(['_interface_url:=', "'.'"]))
#     self._sync_args.append(''.join(['_sync_topics_on_demand:=', 'True']))
#     self._sync_args.append(''.join(['_ignore_hosts:=', '[]']))
#     self._sync_args.append(''.join(['_sync_hosts:=', '[]']))
#     self._sync_args.append(''.join(['_ignore_nodes:=', '[]']))
#     self._sync_args.append(''.join(['_sync_nodes:=', '[]']))
#     self._sync_args.append(''.join(['_ignore_topics:=', '[]']))
#     self._sync_args.append(''.join(['_sync_topics:=', '[/*]']))
#     self._sync_args.append(''.join(['_ignore_services:=', '[]']))
#     self._sync_args.append(''.join(['_sync_services:=', '[]']))
#     self._sync_args.append(''.join(['_sync_remote_nodes:=', 'False']))
#     self._interface_filename = None
#     self.accept()

    def _on_sync_topics_on_demand_clicked(self):
        self._sync_args = []
        self._sync_args.append(''.join(['_interface_url:=', "'.'"]))
        self._sync_args.append(''.join(['_sync_topics_on_demand:=', 'True']))
        self._sync_args.append(''.join(['_ignore_hosts:=', '[]']))
        self._sync_args.append(''.join(['_sync_hosts:=', '[]']))
        self._sync_args.append(''.join(['_ignore_nodes:=', '[]']))
        self._sync_args.append(''.join(['_sync_nodes:=', '[]']))
        self._sync_args.append(''.join(['_ignore_topics:=', '[]']))
        self._sync_args.append(''.join(['_ignore_publishers:=', '[]']))
        self._sync_args.append(''.join(['_ignore_subscribers:=', '[]']))
        self._sync_args.append(''.join(['_sync_topics:=',
                                        '[/only_on_demand]']))
        self._sync_args.append(''.join(['_ignore_services:=', '[/*]']))
        self._sync_args.append(''.join(['_sync_services:=', '[]']))
        self._sync_args.append(''.join(['_sync_remote_nodes:=', 'False']))
        self._interface_filename = None
        self.accept()

    def _on_select_interface_clicked(self):
        self.toolButton_SyncAll.setVisible(False)
        #    self.toolButton_SyncAllAnyMsg.setVisible(False)
        self.toolButton_SyncTopicOnDemand.setVisible(False)
        self.toolButton_SelectInterface.setVisible(False)
        self.interface_field.setVisible(True)
        self.toolButton_CreateInterface.setVisible(True)
        self.toolButton_EditInterface.setVisible(True)
        self.toolButton_EditInterface.setEnabled(False)
        self.textedit.setVisible(False)
        #    # fill the interfaces
        if self._interfaces_files is None:
            self.interface_field.addItems(['interface searching...'])
            self.interface_field.setCurrentIndex(0)
            self._fill_interface_thread = InterfacesThread()
            self._fill_interface_thread.interfaces.connect(
                self._fill_interfaces)
            self._fill_interface_thread.start()
        else:
            self.toolButton_EditInterface.setEnabled(
                self.interface_field.currentText() in self._interfaces_files)
        self.buttonBox.clear()
        self.buttonBox.setStandardButtons(QDialogButtonBox.Ok
                                          | QDialogButtonBox.Cancel)
        self.interface_field.setFocus(Qt.TabFocusReason)
        self.resize(350, 80)

    def _fill_interfaces(self, interfaces_files):
        self._interfaces_files = interfaces_files
        self.interface_field.clear()
        self.interface_field.clearEditText()
        self.interface_field.addItems(self._interfaces_files.keys())

    def _on_interface_selected(self, interface):
        if self._interfaces_files and interface in self._interfaces_files:
            self._sync_args = []
            self._sync_args.append(''.join(['_interface_url:=', interface]))
            self.toolButton_EditInterface.setEnabled(True)
        else:
            self.toolButton_EditInterface.setEnabled(False)

    def accept(self):
        if self.textedit.isVisible():
            try:
                tmp_file = os.path.join(screen.LOG_PATH,
                                        'tmp_sync_interface.sync')
                with open(tmp_file, 'w+') as f:
                    f.write(self.textedit.toPlainText())
                from fkie_master_discovery.common import read_interface
                read_interface(tmp_file)
                if not self._new_iface and self.interface_field.currentText(
                ) in self._interfaces_files:
                    fileName = self._interfaces_files[
                        self.interface_field.currentText()]
                else:
                    fileName, _ = QFileDialog.getSaveFileName(
                        self, 'Save sync interface', '/home',
                        "Sync Files (*.sync)")
                if fileName:
                    with open(fileName, 'w+') as f:
                        self._interface_filename = fileName
                        f.write(self.textedit.toPlainText())
                        if self._new_iface:
                            self.interface_field.clear()
                            self._interfaces_files = None
                        self._on_select_interface_clicked()


#        QDialog.accept(self)
#        self.resetView()
            except Exception as e:
                MessageBox.warning(self, "Create sync interface",
                                   "Error while create interface", utf8(e))
        elif self.interface_field.isVisible():
            interface = self.interface_field.currentText()
            if self._interfaces_files and interface in self._interfaces_files:
                self._interface_filename = self._interfaces_files[interface]
                self._sync_args = []
                self._sync_args.append(''.join(['_interface_url:=',
                                                interface]))
                QDialog.accept(self)
                self.resetView()
        else:
            QDialog.accept(self)
            self.resetView()

    def reject(self):
        if self.textedit.isVisible():
            self._on_select_interface_clicked()
        else:
            QDialog.reject(self)
            self.resetView()

    def _on_create_interface_clicked(self):
        self._new_iface = True
        self.interface_field.setVisible(False)
        self.toolButton_CreateInterface.setVisible(False)
        self.toolButton_EditInterface.setVisible(False)
        self.textedit.setVisible(True)
        self.textedit.setText(
            "# The ignore_* lists will be processed first.\n"
            "# For ignore/sync nodes, topics or services\n"
            "# use follow declaration:\n"
            "#{param name}: \n"
            "#   - {ros name}\n"
            "# or for selected hosts:\n"
            "#   - {host name}:\n"
            "#     - {ros name}\n\n"
            "# you can use follow wildcard: '*', but not as a first character\n"
            "ignore_hosts:\n"
            "sync_hosts:\n\n"
            "ignore_nodes:\n"
            "sync_nodes:\n\n"
            "ignore_topics:\n"
            "ignore_publishers:\n"
            "ignore_subscribers:\n"
            "sync_topics:\n\n"
            "ignore_services:\n"
            "  - /*get_loggers\n"
            "  - /*set_logger_level\n"
            "sync_services:\n\n"
            "# If sync_topics_on_demand is True the local subscribed and published topics\n"
            "# are synchronized with remote even if they are not in the sync_* list.\n"
            "sync_topics_on_demand: False\n\n"
            "# The nodes which are running not at the same host as the ROS master are not\n"
            "# synchronized by default. Use sync_remote_nodes to sync these nodes also.\n"
            "sync_remote_nodes: False\n\n")
        self.resize(350, 300)

    def _on_edit_interface_clicked(self):
        self._new_iface = False
        self.interface_field.setVisible(False)
        self.toolButton_CreateInterface.setVisible(False)
        self.toolButton_EditInterface.setVisible(False)
        self.textedit.setVisible(True)
        if self.interface_field.currentText() in self._interfaces_files:
            try:
                with open(
                        self._interfaces_files[
                            self.interface_field.currentText()], 'rw') as f:
                    iface = f.read()
                    self.textedit.setText(iface)
            except Exception as e:
                MessageBox.warning(self, "Edit sync interface",
                                   "Error while open interface", utf8(e))
        self.resize(350, 300)

    def resetView(self):
        self.toolButton_SyncAll.setVisible(True)
        #     self.toolButton_SyncAllAnyMsg.setVisible(True)
        self.toolButton_SyncTopicOnDemand.setVisible(True)
        self.toolButton_SelectInterface.setVisible(True)
        self.interface_field.setVisible(False)
        self.toolButton_CreateInterface.setVisible(False)
        self.toolButton_EditInterface.setVisible(False)
        self.textedit.setVisible(False)
        self.buttonBox.clear()
        self.buttonBox.setStandardButtons(QDialogButtonBox.Cancel)
        self.resize(350, 160)
class QParameterSetSelectionWidget(QWidgetWithLogger):

    NO_PARAM_SET_TEXT = "No parameters available!"
    SELECT_TEXT = "<Select>"

    param_cleared_signal = Signal()
    param_changed_signal = Signal(str)

    def __init__(self, parent=None, logger=Logger()):
        QWidgetWithLogger.__init__(self, parent, logger)

        # start widget
        hbox = QHBoxLayout()
        hbox.setMargin(0)
        hbox.setContentsMargins(0, 0, 0, 0)

        # get system icon
        icon = QIcon.fromTheme("view-refresh")
        size = icon.actualSize(QSize(32, 32))

        # add combo box
        self.parameter_set_names_combo_box = QComboBox()
        self.parameter_set_names_combo_box.currentIndexChanged[str].connect(
            self.param_changed)
        hbox.addWidget(self.parameter_set_names_combo_box)

        # add refresh button
        self.get_all_parameter_set_names_button = QPushButton()
        self.get_all_parameter_set_names_button.clicked.connect(
            self._get_all_parameter_set_names)

        self.get_all_parameter_set_names_button.setIcon(icon)
        self.get_all_parameter_set_names_button.setFixedSize(
            size.width() + 2,
            size.height() + 2)

        hbox.addWidget(self.get_all_parameter_set_names_button)

        # end widget
        self.setLayout(hbox)

        # init widget
        self.reset_parameter_set_selection()

    def _init_action_client(self, topic_name):
        self.get_parameter_set_names_client = actionlib.SimpleActionClient(
            topic_name, GetParameterSetNamesAction)
        print "Parameter set topic changed: " + topic_name

    @Slot(str)
    def set_topic_name(self, topic_name):
        if len(topic_name) > 0:
            self._init_action_client(topic_name)
            self._get_all_parameter_set_names()
        else:
            self.reset_parameter_set_selection()

    def reset_parameter_set_selection(self):
        self.parameter_set_names_combo_box.setEnabled(False)
        self.parameter_set_names_combo_box.blockSignals(True)
        self.parameter_set_names_combo_box.clear()
        self.parameter_set_names_combo_box.addItem(self.NO_PARAM_SET_TEXT)
        self.get_all_parameter_set_names_button.setEnabled(False)
        self.param_cleared_signal.emit()

    def current_parameter_set_name(self):
        if self.parameter_set_names_combo_box.currentText(
        ) == self.NO_PARAM_SET_TEXT:
            return str()
        else:
            return self.parameter_set_names_combo_box.currentText()

    @Slot(str)
    def param_changed(self, name):
        self.param_changed_signal.emit(name)

    # parameter set names handler
    def _get_all_parameter_set_names(self):
        if self.get_parameter_set_names_client.wait_for_server(
                rospy.Duration(0.5)):
            self.logger.log_info(
                "Requesting current list of parameter set names.")
            goal = GetParameterSetNamesGoal()
            self.get_parameter_set_names_client.send_goal(goal)

            # waiting for getting list of parameter set names
            if self.get_parameter_set_names_client.wait_for_result(
                    rospy.Duration(1.0)):
                result = self.get_parameter_set_names_client.get_result()

                self.logger.log_info("Received " + str(len(result.names)) +
                                     " parameter set names.")

                self.parameter_set_names_combo_box.blockSignals(True)
                self.parameter_set_names_combo_box.clear()
                self.parameter_set_names_combo_box.addItem(self.SELECT_TEXT)
                self.parameter_set_names_combo_box.setItemData(
                    0, 0, Qt.UserRole - 1)
                self.param_cleared_signal.emit()

                for name in result.names:
                    self.parameter_set_names_combo_box.addItem(name.data)

                self.parameter_set_names_combo_box.setEnabled(True)
                self.parameter_set_names_combo_box.blockSignals(False)
                self.get_all_parameter_set_names_button.setEnabled(True)
            else:
                self.logger.log_error(
                    "Didn't received any results. Check communcation!")
                self.reset_parameter_set_selection()
        else:
            self.logger.log_error(
                "Can't connect to footstep planner parameter action server!")
            self.reset_parameter_set_selection()
Example #37
0
    def __init__(self, parent=None):
        QDialog.__init__(self, parent)
        #    self.host = host
        self.setWindowIcon(QIcon(":/icons/irondevil_sync.png"))
        self.setWindowTitle('Sync')
        self.verticalLayout = QVBoxLayout(self)
        self.verticalLayout.setObjectName("verticalLayout")
        self.resize(350, 190)

        self.toolButton_SyncAll = QToolButton(self)
        sizePolicy = QSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding)
        sizePolicy.setHorizontalStretch(0)
        sizePolicy.setVerticalStretch(2)
        sizePolicy.setHeightForWidth(
            self.toolButton_SyncAll.sizePolicy().hasHeightForWidth())
        self.toolButton_SyncAll.setSizePolicy(sizePolicy)
        self.toolButton_SyncAll.setObjectName("toolButton_SyncAll")
        self.verticalLayout.addWidget(self.toolButton_SyncAll)
        self.toolButton_SyncAll.setText(self._translate("Sync All"))
        self.toolButton_SyncAll.clicked.connect(self._on_sync_all_clicked)

        #     self.toolButton_SyncAllAnyMsg = QToolButton(self)
        #     sizePolicy = QSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding)
        #     sizePolicy.setHorizontalStretch(0)
        #     sizePolicy.setVerticalStretch(1)
        #     sizePolicy.setHeightForWidth(self.toolButton_SyncAllAnyMsg.sizePolicy().hasHeightForWidth())
        #     self.toolButton_SyncAllAnyMsg.setSizePolicy(sizePolicy)
        #     self.toolButton_SyncAllAnyMsg.setObjectName("toolButton_SyncAllAnyMsg")
        #     self.verticalLayout.addWidget(self.toolButton_SyncAllAnyMsg)
        #     self.toolButton_SyncAllAnyMsg.setText(self._translate("Sync all (+AnyMsg)"))
        #     self.toolButton_SyncAllAnyMsg.clicked.connect(self._on_sync_all_anymsg_clicked)

        self.toolButton_SyncTopicOnDemand = QToolButton(self)
        sizePolicy = QSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding)
        sizePolicy.setHorizontalStretch(0)
        sizePolicy.setVerticalStretch(1)
        sizePolicy.setHeightForWidth(
            self.toolButton_SyncTopicOnDemand.sizePolicy().hasHeightForWidth())
        self.toolButton_SyncTopicOnDemand.setSizePolicy(sizePolicy)
        self.toolButton_SyncTopicOnDemand.setObjectName(
            "toolButton_SyncTopicOnDemand")
        self.verticalLayout.addWidget(self.toolButton_SyncTopicOnDemand)
        self.toolButton_SyncTopicOnDemand.setText(
            self._translate("Sync only topics on demand"))
        self.toolButton_SyncTopicOnDemand.clicked.connect(
            self._on_sync_topics_on_demand_clicked)

        self.toolButton_SelectInterface = QToolButton(self)
        sizePolicy = QSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding)
        sizePolicy.setHorizontalStretch(0)
        sizePolicy.setVerticalStretch(1)
        sizePolicy.setHeightForWidth(
            self.toolButton_SelectInterface.sizePolicy().hasHeightForWidth())
        self.toolButton_SelectInterface.setSizePolicy(sizePolicy)
        self.toolButton_SelectInterface.setObjectName(
            "toolButton_SelectInterface")
        self.verticalLayout.addWidget(self.toolButton_SelectInterface)
        self.toolButton_SelectInterface.setText(
            self._translate("Select an interface"))
        self.toolButton_SelectInterface.clicked.connect(
            self._on_select_interface_clicked)

        self.interface_field = QComboBox(self)
        self.interface_field.setInsertPolicy(QComboBox.InsertAlphabetically)
        self.interface_field.setSizePolicy(
            QSizePolicy(QSizePolicy.Expanding, QSizePolicy.Fixed))
        self.interface_field.setEditable(True)
        self.interface_field.setVisible(False)
        self.interface_field.setObjectName("interface_field")
        self.verticalLayout.addWidget(self.interface_field)
        self.interface_field.currentIndexChanged[str].connect(
            self._on_interface_selected)

        self.toolButton_EditInterface = QToolButton(self)
        sizePolicy = QSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding)
        sizePolicy.setHorizontalStretch(0)
        sizePolicy.setVerticalStretch(1)
        sizePolicy.setHeightForWidth(
            self.toolButton_EditInterface.sizePolicy().hasHeightForWidth())
        self.toolButton_EditInterface.setSizePolicy(sizePolicy)
        self.toolButton_EditInterface.setObjectName("toolButton_EditInterface")
        self.verticalLayout.addWidget(self.toolButton_EditInterface)
        self.toolButton_EditInterface.setText(
            self._translate("Edit selected interface"))
        self.toolButton_EditInterface.clicked.connect(
            self._on_edit_interface_clicked)
        self.toolButton_EditInterface.setVisible(False)

        self.toolButton_CreateInterface = QToolButton(self)
        sizePolicy = QSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding)
        sizePolicy.setHorizontalStretch(0)
        sizePolicy.setVerticalStretch(1)
        sizePolicy.setHeightForWidth(
            self.toolButton_CreateInterface.sizePolicy().hasHeightForWidth())
        self.toolButton_CreateInterface.setSizePolicy(sizePolicy)
        self.toolButton_CreateInterface.setObjectName(
            "toolButton_CreateInterface")
        self.verticalLayout.addWidget(self.toolButton_CreateInterface)
        self.toolButton_CreateInterface.setText(
            self._translate("Create an interface"))
        self.toolButton_CreateInterface.clicked.connect(
            self._on_create_interface_clicked)
        self.toolButton_CreateInterface.setVisible(False)

        self.textedit = TextEdit('', self)
        self.hl = SyncHighlighter(self.textedit.document())
        sizePolicy = QSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding)
        self.textedit.setSizePolicy(sizePolicy)
        self.textedit.setObjectName("syncedit")
        self.verticalLayout.addWidget(self.textedit)
        self.textedit.setVisible(False)

        self._fill_interface_thread = None
        self._interfaces_files = None
        self._sync_args = []
        self._interface_filename = None

        self.buttonBox = QDialogButtonBox(self)
        self.buttonBox.setStandardButtons(QDialogButtonBox.Cancel)
        self.buttonBox.setOrientation(Qt.Horizontal)
        self.buttonBox.setObjectName("buttonBox")
        self.verticalLayout.addWidget(self.buttonBox)
        self.buttonBox.accepted.connect(self.accept)
        self.buttonBox.rejected.connect(self.reject)
        self._new_iface = True
Example #38
0

if __name__ == '__main__':
    import sys
    from python_qt_binding.QtGui import QApplication, QComboBox, QLineEdit, QMainWindow, QTreeView, QVBoxLayout, QWidget
    app = QApplication(sys.argv)
    mw = QMainWindow()
    widget = QWidget(mw)
    layout = QVBoxLayout(widget)

    edit = QLineEdit()
    edit_completer = TopicCompleter(edit)
    # edit_completer.setCompletionMode(QCompleter.InlineCompletion)
    edit.setCompleter(edit_completer)

    combo = QComboBox()
    combo.setEditable(True)
    combo_completer = TopicCompleter(combo)
    # combo_completer.setCompletionMode(QCompleter.InlineCompletion)
    combo.lineEdit().setCompleter(combo_completer)

    model_tree = QTreeView()
    model_tree.setModel(combo_completer.model())
    model_tree.expandAll()
    for column in range(combo_completer.model().columnCount()):
        model_tree.resizeColumnToContents(column)

    completion_tree = QTreeView()
    completion_tree.setModel(combo_completer.completionModel())
    completion_tree.expandAll()
    for column in range(combo_completer.completionModel().columnCount()):
Example #39
0
class EchoDialog(QDialog):

    MESSAGE_LINE_LIMIT = 128
    MESSAGE_HZ_LIMIT = 10
    MAX_DISPLAY_MSGS = 25
    STATISTIC_QUEUE_LEN = 5000

    """
  This dialog shows the output of a topic.
  """

    finished_signal = Signal(str)
    """
  finished_signal has as parameter the name of the topic and is emitted, if this
  dialog was closed.
  """

    msg_signal = Signal(object, bool)
    """
  msg_signal is a signal, which is emitted, if a new message was received.
  """

    text_hz_signal = Signal(str)
    text_signal = Signal(str)
    """
  text_signal is a signal, which is emitted, if a new text to display was received.
  """

    text_error_signal = Signal(str)
    """
  text_error_signal is a signal, which is emitted, if a new error text to display was received.
  """

    request_pw = Signal(object)

    def __init__(self, topic, msg_type, show_only_rate=False, masteruri=None, use_ssh=False, parent=None):
        """
        Creates an input dialog.
        @param topic: the name of the topic
        @type topic: C{str}
        @param msg_type: the type of the topic
        @type msg_type: C{str}
        @raise Exception: if no topic class was found for the given type
        """
        QDialog.__init__(self, parent=parent)
        self._masteruri = masteruri
        masteruri_str = "" if masteruri is None else "[%s]" % masteruri
        self.setObjectName(" - ".join(["EchoDialog", topic, masteruri_str]))
        self.setAttribute(Qt.WA_DeleteOnClose, True)
        self.setWindowFlags(Qt.Window)
        self.setWindowTitle("%s %s %s" % ("Echo --- " if not show_only_rate else "Hz --- ", topic, masteruri_str))
        self.resize(728, 512)
        self.verticalLayout = QVBoxLayout(self)
        self.verticalLayout.setObjectName("verticalLayout")
        self.verticalLayout.setContentsMargins(1, 1, 1, 1)
        self.mIcon = QIcon(":/icons/crystal_clear_prop_run_echo.png")
        self.setWindowIcon(self.mIcon)

        self.topic = topic
        self.show_only_rate = show_only_rate
        self.lock = threading.RLock()
        self.last_printed_count = 0
        self.msg_t0 = -1.0
        self.msg_tn = 0
        self.times = []

        self.message_count = 0
        self._rate_message = ""
        self._scrapped_msgs = 0
        self._scrapped_msgs_sl = 0

        self._last_received_ts = 0
        self.receiving_hz = self.MESSAGE_HZ_LIMIT
        self.line_limit = self.MESSAGE_LINE_LIMIT

        self.field_filter_fn = None

        options = QWidget(self)
        if not show_only_rate:
            hLayout = QHBoxLayout(options)
            hLayout.setContentsMargins(1, 1, 1, 1)
            self.no_str_checkbox = no_str_checkbox = QCheckBox("Hide strings")
            no_str_checkbox.toggled.connect(self.on_no_str_checkbox_toggled)
            hLayout.addWidget(no_str_checkbox)
            self.no_arr_checkbox = no_arr_checkbox = QCheckBox("Hide arrays")
            no_arr_checkbox.toggled.connect(self.on_no_arr_checkbox_toggled)
            hLayout.addWidget(no_arr_checkbox)
            self.combobox_reduce_ch = QComboBox(self)
            self.combobox_reduce_ch.addItems([str(self.MESSAGE_LINE_LIMIT), "0", "80", "256", "1024"])
            self.combobox_reduce_ch.activated[str].connect(self.combobox_reduce_ch_activated)
            self.combobox_reduce_ch.setEditable(True)
            self.combobox_reduce_ch.setToolTip("Set maximum line width. 0 disables the limit.")
            hLayout.addWidget(self.combobox_reduce_ch)
            #      reduce_ch_label = QLabel('ch', self)
            #      hLayout.addWidget(reduce_ch_label)
            # add spacer
            spacerItem = QSpacerItem(515, 20, QSizePolicy.Expanding, QSizePolicy.Minimum)
            hLayout.addItem(spacerItem)
            # add combobox for displaying frequency of messages
            self.combobox_displ_hz = QComboBox(self)
            self.combobox_displ_hz.addItems([str(self.MESSAGE_HZ_LIMIT), "0", "0.1", "1", "50", "100", "1000"])
            self.combobox_displ_hz.activated[str].connect(self.on_combobox_hz_activated)
            self.combobox_displ_hz.setEditable(True)
            hLayout.addWidget(self.combobox_displ_hz)
            displ_hz_label = QLabel("Hz", self)
            hLayout.addWidget(displ_hz_label)
            # add combobox for count of displayed messages
            self.combobox_msgs_count = QComboBox(self)
            self.combobox_msgs_count.addItems([str(self.MAX_DISPLAY_MSGS), "0", "50", "100"])
            self.combobox_msgs_count.activated[str].connect(self.on_combobox_count_activated)
            self.combobox_msgs_count.setEditable(True)
            self.combobox_msgs_count.setToolTip("Set maximum displayed message count. 0 disables the limit.")
            hLayout.addWidget(self.combobox_msgs_count)
            displ_count_label = QLabel("#", self)
            hLayout.addWidget(displ_count_label)
            # add topic control button for unsubscribe and subscribe
            self.topic_control_button = QToolButton(self)
            self.topic_control_button.setText("stop")
            self.topic_control_button.setIcon(QIcon(":/icons/deleket_deviantart_stop.png"))
            self.topic_control_button.clicked.connect(self.on_topic_control_btn_clicked)
            hLayout.addWidget(self.topic_control_button)
            # add clear button
            clearButton = QToolButton(self)
            clearButton.setText("clear")
            clearButton.clicked.connect(self.on_clear_btn_clicked)
            hLayout.addWidget(clearButton)
            self.verticalLayout.addWidget(options)

        self.display = QTextBrowser(self)
        self.display.setReadOnly(True)
        self.verticalLayout.addWidget(self.display)
        self.display.document().setMaximumBlockCount(500)
        self.max_displayed_msgs = self.MAX_DISPLAY_MSGS
        self._blocks_in_msg = None
        self.display.setOpenLinks(False)
        self.display.anchorClicked.connect(self._on_display_anchorClicked)

        self.status_label = QLabel("0 messages", self)
        self.verticalLayout.addWidget(self.status_label)

        # subscribe to the topic
        errmsg = ""
        try:
            self.__msg_class = message.get_message_class(msg_type)
            if not self.__msg_class:
                errmsg = "Cannot load message class for [%s]. Did you build messages?" % msg_type
        #        raise Exception("Cannot load message class for [%s]. Did you build messages?"%msg_type)
        except Exception as e:
            self.__msg_class = None
            errmsg = "Cannot load message class for [%s]. Did you build messagest?\nError: %s" % (msg_type, e)
        #      raise Exception("Cannot load message class for [%s]. Did you build messagest?\nError: %s"%(msg_type, e))
        # variables for Subscriber
        self.msg_signal.connect(self._append_message)
        self.sub = None

        # vairables for SSH connection
        self.ssh_output_file = None
        self.ssh_error_file = None
        self.ssh_input_file = None
        self.text_signal.connect(self._append_text)
        self.text_hz_signal.connect(self._append_text_hz)
        self._current_msg = ""
        self._current_errmsg = ""
        self.text_error_signal.connect(self._append_error_text)

        # decide, which connection to open
        if use_ssh:
            self.__msg_class = None
            self._on_display_anchorClicked(QUrl(self._masteruri))
        elif self.__msg_class is None:
            errtxt = '<pre style="color:red; font-family:Fixedsys,Courier,monospace; padding:10px;">\n%s</pre>' % (
                errmsg
            )
            self.display.setText('<a href="%s">open using SSH</a>' % (masteruri))
            self.display.append(errtxt)
        else:
            self.sub = rospy.Subscriber(self.topic, self.__msg_class, self._msg_handle)

        self.print_hz_timer = QTimer()
        self.print_hz_timer.timeout.connect(self._on_calc_hz)
        self.print_hz_timer.start(1000)

    #    print "======== create", self.objectName()
    #
    #  def __del__(self):
    #    print "******* destroy", self.objectName()

    #  def hideEvent(self, event):
    #    self.close()

    def closeEvent(self, event):
        if self.sub is not None:
            self.sub.unregister()
            del self.sub
        try:
            self.ssh_output_file.close()
            self.ssh_error_file.close()
            # send Ctrl+C to remote process
            self.ssh_input_file.write("%s\n" % chr(3))
            self.ssh_input_file.close()
        except:
            pass
        self.finished_signal.emit(self.topic)
        if self.parent() is None:
            QApplication.quit()

    #    else:
    #      self.setParent(None)

    def create_field_filter(self, echo_nostr, echo_noarr):
        def field_filter(val):
            try:
                # fields = val.__slots__
                # field_types = val._slot_types
                for f, t in zip(val.__slots__, val._slot_types):
                    if echo_noarr and "[" in t:
                        continue
                    elif echo_nostr and "string" in t:
                        continue
                    yield f
            except:
                pass

        return field_filter

    def on_no_str_checkbox_toggled(self, state):
        self.field_filter_fn = self.create_field_filter(state, self.no_arr_checkbox.isChecked())

    def on_no_arr_checkbox_toggled(self, state):
        self.field_filter_fn = self.create_field_filter(self.no_str_checkbox.isChecked(), state)

    def combobox_reduce_ch_activated(self, ch_txt):
        try:
            self.line_limit = int(ch_txt)
        except ValueError:
            try:
                self.line_limit = float(ch_txt)
            except ValueError:
                self.combobox_reduce_ch.setEditText(str(self.line_limit))

    def on_combobox_hz_activated(self, hz_txt):
        try:
            self.receiving_hz = int(hz_txt)
        except ValueError:
            try:
                self.receiving_hz = float(hz_txt)
            except ValueError:
                self.combobox_displ_hz.setEditText(str(self.receiving_hz))

    def on_combobox_count_activated(self, count_txt):
        try:
            self.max_displayed_msgs = int(count_txt)
            self._blocks_in_msg = None
        except ValueError:
            self.combobox_msgs_count.setEditText(str(self.max_displayed_msgs))

    def on_clear_btn_clicked(self):
        self.display.clear()
        with self.lock:
            self.message_count = 0
            self._scrapped_msgs = 0
            del self.times[:]

    def on_topic_control_btn_clicked(self):
        try:
            if self.sub is None and self.ssh_output_file is None:
                if self.__msg_class:
                    self.sub = rospy.Subscriber(self.topic, self.__msg_class, self._msg_handle)
                else:
                    self._on_display_anchorClicked(QUrl(self._masteruri))
                self.topic_control_button.setText("stop")
                self.topic_control_button.setIcon(QIcon(":/icons/deleket_deviantart_stop.png"))
            else:
                if self.sub is not None:
                    self.sub.unregister()
                    self.sub = None
                elif self.ssh_output_file is not None:
                    self.ssh_output_file.close()
                    self.ssh_error_file.close()
                    self.ssh_output_file = None
                self.topic_control_button.setText("play")
                self.topic_control_button.setIcon(QIcon(":/icons/deleket_deviantart_play.png"))
                self.no_str_checkbox.setEnabled(True)
                self.no_arr_checkbox.setEnabled(True)
        except Exception as e:
            rospy.logwarn("Error while stop/play echo for topic %s: %s" % (self.topic, e))

    def _msg_handle(self, data):
        self.msg_signal.emit(data, (data._connection_header["latching"] != "0"))

    def _append_message(self, msg, latched):
        """
        Adds a label to the dialog's layout and shows the given text.
        @param msg: the text to add to the dialog
        @type msg: message object
        """
        current_time = time.time()
        self._count_messages(current_time)
        # skip messages, if they are received often then MESSAGE_HZ_LIMIT
        if self._last_received_ts != 0 and self.receiving_hz != 0:
            if not latched and current_time - self._last_received_ts < 1.0 / self.receiving_hz:
                self._scrapped_msgs += 1
                self._scrapped_msgs_sl += 1
                return
        self._last_received_ts = current_time
        if not self.show_only_rate:
            # convert message to string and reduce line width to current limit
            msg = message.strify_message(msg, field_filter=self.field_filter_fn)
            if isinstance(msg, tuple):
                msg = msg[0]
            msg = self._trim_width(msg)
            msg = msg.replace("<", "&lt;").replace(">", "&gt;")
            # create a notification about scrapped messages
            if self._scrapped_msgs_sl > 0:
                txt = (
                    '<pre style="color:red; font-family:Fixedsys,Courier,monospace; padding:10px;">scrapped %s message because of Hz-settings</pre>'
                    % self._scrapped_msgs_sl
                )
                self.display.append(txt)
                self._scrapped_msgs_sl = 0
            txt = (
                '<pre style="background-color:#FFFCCC; font-family:Fixedsys,Courier; padding:10px;">---------- %s --------------------\n%s</pre>'
                % (datetime.now().strftime("%d.%m.%Y %H:%M:%S.%f"), msg)
            )
            # set the count of the displayed messages on receiving the first message
            self._update_max_msg_count(txt)
            self.display.append(txt)
        self._print_status()

    def _count_messages(self, ts=time.time()):
        """
        Counts the received messages. Call this method only on receive message.
        """
        current_time = ts
        with self.lock:
            # time reset
            if self.msg_t0 < 0 or self.msg_t0 > current_time:
                self.msg_t0 = current_time
                self.msg_tn = current_time
                self.times = []
            else:
                self.times.append(current_time - self.msg_tn)
                self.msg_tn = current_time
            # keep only statistics for the last 5000 messages so as not to run out of memory
            if len(self.times) > self.STATISTIC_QUEUE_LEN:
                self.times.pop(0)
            self.message_count += 1

    def _trim_width(self, msg):
        """
        reduce line width to current limit
        :param msg: the message
        :type msg: str
        :return: trimmed message
        """
        result = msg
        if self.line_limit != 0:
            a = ""
            for l in msg.splitlines():
                a = a + (l if len(l) <= self.line_limit else l[0 : self.line_limit - 3] + "...") + "\n"
            result = a
        return result

    def _update_max_msg_count(self, txt):
        """
        set the count of the displayed messages on receiving the first message
        :param txt: text of the message, which will be added to the document
        :type txt: str
        """
        if self._blocks_in_msg is None:
            td = QTextDocument(txt)
            self._blocks_in_msg = td.blockCount()
            self.display.document().setMaximumBlockCount(self._blocks_in_msg * self.max_displayed_msgs)

    def _on_calc_hz(self):
        if rospy.is_shutdown():
            self.close()
            return
        if self.message_count == self.last_printed_count:
            return
        with self.lock:
            # the code from ROS rostopic
            n = len(self.times)
            if n < 2:
                return
            mean = sum(self.times) / n
            rate = 1.0 / mean if mean > 0.0 else 0
            # std dev
            std_dev = math.sqrt(sum((x - mean) ** 2 for x in self.times) / n)
            # min and max
            max_delta = max(self.times)
            min_delta = min(self.times)
            self.last_printed_count = self.message_count
            self._rate_message = "average rate: %.3f\tmin: %.3fs   max: %.3fs   std dev: %.5fs   window: %s" % (
                rate,
                min_delta,
                max_delta,
                std_dev,
                n + 1,
            )
            if self._scrapped_msgs > 0:
                self._rate_message += " --- scrapped msgs: %s" % self._scrapped_msgs
            self._print_status()
            if self.show_only_rate:
                self.display.append(self._rate_message)

    def _print_status(self):
        self.status_label.setText("%s messages   %s" % (self.message_count, self._rate_message))

    def _append_text(self, text):
        """
        Append echo text received through the SSH.
        """
        with self.lock:
            self._current_msg += text
            if self._current_msg.find("---") != -1:
                messages = self._current_msg.split("---")
                for m in messages[:-1]:
                    current_time = time.time()
                    self._count_messages(current_time)
                    # limit the displayed text width
                    m = self._trim_width(m)
                    txt = (
                        '<pre style="background-color:#FFFCCC; font-family:Fixedsys,Courier; padding:10px;">---------- %s --------------------\n%s</pre>'
                        % (datetime.now().strftime("%d.%m.%Y %H:%M:%S.%f"), m)
                    )
                    # set the count of the displayed messages on receiving the first message
                    self._update_max_msg_count(txt)
                    self.display.append(txt)
                self._current_msg = messages[-1]
            self._print_status()

    def _append_error_text(self, text):
        """
        Append error text received through the SSH.
        """
        with self.lock:
            self._current_errmsg += text
            if self._current_errmsg.find("\n") != -1:
                messages = self._current_errmsg.split("\n")
                for m in messages[:-1]:
                    txt = '<pre style="color:red; font-family:Fixedsys,Courier,monospace; padding:10px;">%s</pre>' % m
                    self.display.append(txt)
                self._current_errmsg = messages[-1]

    def _append_text_hz(self, text):
        """
        Append text received through the SSH for hz view.
        """
        with self.lock:
            self._current_msg += text
            if self._current_msg.find("\n") != -1:
                messages = self._current_msg.split("\n")
                for m in messages[:-1]:
                    txt = '<div style="font-family:Fixedsys,Courier;">%s</div>' % (m)
                    self.display.append(txt)
                self._current_msg = messages[-1]

    def _on_display_anchorClicked(self, url, user=None, pw=None):
        try:
            ok = False
            if self.show_only_rate:
                self.ssh_input_file, self.ssh_output_file, self.ssh_error_file, ok = nm.ssh().ssh_exec(
                    url.host(), ["rostopic hz %s" % (self.topic)], user, pw, auto_pw_request=True, get_pty=True
                )
                self.status_label.setText("connected to %s over SSH" % url.host())
            else:
                self.combobox_displ_hz.setEnabled(False)
                nostr = "--nostr" if self.no_str_checkbox.isChecked() else ""
                noarr = "--noarr" if self.no_arr_checkbox.isChecked() else ""
                self.ssh_input_file, self.ssh_output_file, self.ssh_error_file, ok = nm.ssh().ssh_exec(
                    url.host(),
                    ["rostopic echo %s %s %s" % (nostr, noarr, self.topic)],
                    user,
                    pw,
                    auto_pw_request=True,
                    get_pty=True,
                )
            if ok:
                self.display.clear()
                target = self._read_output_hz if self.show_only_rate else self._read_output
                thread = threading.Thread(target=target, args=((self.ssh_output_file,)))
                thread.setDaemon(True)
                thread.start()
                thread = threading.Thread(target=self._read_error, args=((self.ssh_error_file,)))
                thread.setDaemon(True)
                thread.start()
            elif self.ssh_output_file:
                self.ssh_output_file.close()
                self.ssh_error_file.close()
        except Exception as e:
            self._append_error_text("%s\n" % e)

    #      import traceback
    #      print traceback.format_exc()

    def _read_output_hz(self, output_file):
        try:
            while not output_file.closed:
                text = output_file.read(1)
                if text:
                    self.text_hz_signal.emit(text)
        except:
            pass

    #      import traceback
    #      print traceback.format_exc()

    def _read_output(self, output_file):
        while not output_file.closed:
            text = output_file.read(1)
            if text:
                self.text_signal.emit(text)

    def _read_error(self, error_file):
        try:
            while not error_file.closed:
                text = error_file.read(1)
                if text:
                    self.text_error_signal.emit(text)
        except:
            pass