def get_ylim(self): """get Y limits""" if self._data_plot_widget: return self._data_plot_widget.get_ylim() else: qWarning("No plot widget; returning default Y limits") return [0.0, 10.0]
def _evaluate_expression(self, expression, slot_type): successful_eval = True try: # try to evaluate expression value = eval(expression, {}, self._eval_locals) except Exception: successful_eval = False if slot_type is str: if successful_eval: value = str(value) else: # for string slots just convert the expression to str, if it did not evaluate successfully value = str(expression) successful_eval = True elif successful_eval: type_set = set((slot_type, type(value))) # check if value's type and slot_type belong to the same type group, i.e. array types, numeric types # and if they do, make sure values's type is converted to the exact slot_type if type_set <= set((list, tuple)) or type_set <= set((int, float)): # convert to the right type value = slot_type(value) if successful_eval and isinstance(value, slot_type): return True, value else: qWarning('Publisher._evaluate_expression(): failed to evaluate expression: "%s" as Python type "%s"' % (expression, slot_type.__name__)) return False, None
def load_bag(self, filename): qWarning("Loading %s" % filename) # QProgressBar can EITHER: show text or show a bouncing loading bar, # but apparently the text is hidden when the bounding loading bar is # shown #self.progress_bar.setRange(0, 0) self.set_status_text.emit("Loading %s" % filename) #progress_format = self.progress_bar.format() #progress_text_visible = self.progress_bar.isTextVisible() #self.progress_bar.setFormat("Loading %s" % filename) #self.progress_bar.setTextVisible(True) bag = rosbag.Bag(filename) self.play_button.setEnabled(True) self.thumbs_button.setEnabled(True) self.zoom_in_button.setEnabled(True) self.zoom_out_button.setEnabled(True) self.zoom_all_button.setEnabled(True) self.faster_button.setEnabled(True) self.slower_button.setEnabled(True) self.begin_button.setEnabled(True) self.end_button.setEnabled(True) self.save_button.setEnabled(True) self.record_button.setEnabled(False) self._timeline.add_bag(bag) qWarning("Done loading %s" % filename ) # put the progress bar back the way it was self.set_status_text.emit("")
def _message_recorded(self, topic, msg, t): if self._timeline_frame._start_stamp is None: self._timeline_frame._start_stamp = t self._timeline_frame._end_stamp = t self._timeline_frame._playhead = t elif self._timeline_frame._end_stamp is None or t > self._timeline_frame._end_stamp: self._timeline_frame._end_stamp = t if not self._timeline_frame.topics or topic not in self._timeline_frame.topics: self._timeline_frame.topics = self._get_topics() self._timeline_frame._topics_by_datatype = self._get_topics_by_datatype() self._playhead_positions_cvs[topic] = threading.Condition() self._messages_cvs[topic] = threading.Condition() self._message_loaders[topic] = MessageLoaderThread(self, topic) if self._timeline_frame._stamp_left is None: self.reset_zoom() # Notify the index caching thread that it has work to do with self._timeline_frame.index_cache_cv: self._timeline_frame.invalidated_caches.add(topic) self._timeline_frame.index_cache_cv.notify() if topic in self._listeners: for listener in self._listeners[topic]: try: listener.timeline_changed() except Exception as ex: qWarning('Error calling timeline_changed on %s: %s' % (type(listener), str(ex)))
def add_widget(self, widget): if widget in self._embed_widgets: qWarning('PluginHandlerXEmbedClient.add_widget() widget "%s" already added' % widget.objectName()) return embed_widget = QX11EmbedWidget() layout = QVBoxLayout() layout.setContentsMargins(0, 0, 0, 0) layout.addWidget(widget) embed_widget.setLayout(layout) # close embed widget when container is closed # TODO necessary? #embed_widget.containerClosed.connect(embed_widget.close) embed_container_window_id = self._remote_container.embed_widget(os.getpid(), widget.objectName()) embed_widget.embedInto(embed_container_window_id) signaler = WindowChangedSignaler(widget, widget) signaler.window_icon_changed_signal.connect(self._on_embed_widget_icon_changed) signaler.window_title_changed_signal.connect(self._on_embed_widget_title_changed) self._embed_widgets[widget] = embed_widget, signaler # trigger to update initial window icon and title signaler.window_icon_changed_signal.emit(widget) signaler.window_title_changed_signal.emit(widget) embed_widget.show()
def dragEnterEvent(self, event): if event.mimeData().hasText(): topic_name = str(event.mimeData().text()) if len(topic_name) == 0: qWarning('PoseViewWidget.dragEnterEvent(): event.mimeData() text is empty') return else: if not hasattr(event.source(), 'selectedItems') or len(event.source().selectedItems()) == 0: qWarning('PoseViewWidget.dragEnterEvent(): event.source() has no attribute selectedItems or length of selectedItems is 0') return item = event.source().selectedItems()[0] topic_name = item.data(0, Qt.UserRole) if topic_name is None: qWarning('PoseViewWidget.dragEnterEvent(): selectedItem has no UserRole data with a topic name') return # check for valid topic msg_class, self._topic_name, _ = get_topic_class(topic_name) if msg_class is None: qWarning('PoseViewWidget.dragEnterEvent(): No message class was found for topic "%s".' % topic_name) return # check for valid message class quaternion_slot_path, point_slot_path = self._get_slot_paths(msg_class) if quaternion_slot_path is None and point_slot_path is None: qWarning('PoseViewWidget.dragEnterEvent(): No Pose, Quaternion or Point data was found outside of arrays in "%s" on topic "%s".' % (msg_class._type, topic_name)) return event.acceptProposedAction()
def _evaluate_expression(self, expression, slot_type): successful_eval = True successful_conversion = True try: # try to evaluate expression value = eval(expression, {}, self._eval_locals) except Exception: # just use expression-string as value value = expression successful_eval = False try: # try to convert value to right type value = slot_type(value) except Exception: successful_conversion = False if successful_conversion: return value elif successful_eval: qWarning('ServiceCaller.fill_message_slots(): can not convert expression to slot type: %s -> %s' % (type(value), slot_type)) else: qWarning('ServiceCaller.fill_message_slots(): failed to evaluate expression: %s' % (expression)) return None
def _add_dock_widget_to_main_window(self, dock_widget): if self._main_window is not None: # warn about dock_widget with same object name old_dock_widget = self._main_window.findChild(DockWidget, dock_widget.objectName()) if old_dock_widget is not None: qWarning('PluginHandler._add_dock_widget_to_main_window() duplicate object name "%s", assign unique object names before adding widgets!' % dock_widget.objectName()) self._main_window.addDockWidget(Qt.BottomDockWidgetArea, dock_widget)
def send_logger_change_message(self, node, logger, level): """ Sends a logger level change request to 'node'. :param node: name of the node to chaange, ''str'' :param logger: name of the logger to change, ''str'' :param level: name of the level to change, ''str'' :returns: True if the response is valid, ''bool'' :returns: False if the request raises an exception or would not change the cached state, ''bool'' """ servicename = node + '/set_logger_level' if self._current_levels[logger].lower() == level.lower(): return False service = rosservice.get_service_class_by_name(servicename) request = service._request_class() setattr(request, 'logger', logger) setattr(request, 'level', level) proxy = rospy.ServiceProxy(str(servicename), service) try: proxy(request) self._current_levels[logger] = level.upper() except rospy.ServiceException as e: qWarning('SetupDialog.level_changed(): request:\n%r' % (request)) qWarning('SetupDialog.level_changed() "%s":\n%s' % (servicename, e)) return False return True
def _handle_save_clicked(self, checked): filename = QFileDialog.getSaveFileName(self, 'Save to File', '.', self.tr('rqt_console msg file {.csv} (*.csv)')) if filename[0] != '': filename = filename[0] if filename[-4:] != '.csv': filename += '.csv' try: handle = open(filename, 'w') except IOError as e: qWarning(str(e)) return try: handle.write(';'.join(MessageDataModel.columns) + '\n') for index in range(self._proxy_model.rowCount()): row = self._proxy_model.mapToSource(self._proxy_model.index(index, 0)).row() msg = self._model._messages[row] data = {} data['message'] = msg.message.replace('"', '\\"') data['severity'] = str(msg.severity) data['node'] = msg.node data['stamp'] = str(msg.stamp[0]) + '.' + str(msg.stamp[1]).zfill(9) data['topics'] = ','.join(msg.topics) data['location'] = msg.location line = [] for column in MessageDataModel.columns: line.append('"%s"' % data[column]) handle.write(';'.join(line) + '\n') except Exception as e: qWarning('File save failed: %s' % str(e)) return False finally: handle.close() return True
def gripper_click(self, button_name): grip_side = '' grip_side_text = '' if ('Left' in button_name): grip_side = 'l' grip_side_text = 'left' else: grip_side = 'r' grip_side_text = 'right' if ('Open' in button_name): grip_action = 20.0 grip_action_text = 'close' qWarning('Robot opened %s gripper' % (grip_side_text)) else: grip_action = 0.0 grip_action_text = 'open' qWarning('Robot closed %s gripper' % (grip_side_text)) self.show_text_in_rviz("%sing %s Gripper" % (grip_action_text.capitalize(), grip_side_text.capitalize())) self.gripper_action(grip_side, grip_action) self._widget.sender().setText('%s %s Gripper' % (grip_action_text.capitalize(), grip_side_text.capitalize()))
def on_pushButton_calibrate_clicked(self): self._widget.pushButton_calibrate.setEnabled(False) status_icon = QIcon.fromTheme('stock_no') # Fill request information request = self._selected_service['service_class']._request_class() request.target_hue.data = self._widget.spinBox_hue.value() request.mult_diffs.data = self._widget.spinBox_diff.value() request.mult_sat.data = self._widget.spinBox_sat.value() try: # Call service response = self._selected_service['service_proxy'](request) except rospy.ServiceException as e: qWarning('on_pushButton_calibrate_clicked(): error calling service "%s":\n%s' % (self._selected_service['service_name'], e)) else: # Get debug image and show img = response.image_debug qImage = QImage(img.data, img.width, img.height, img.step, QImage.Format_RGB888) qPixmap = QPixmap() qPixmap.convertFromImage(qImage) pixmapItem = QGraphicsPixmapItem(qPixmap) self._qGraphicsScene.clear() self._qGraphicsScene.addItem(pixmapItem) self._widget.graphicsView.fitInView(QRectF(qPixmap.rect()), Qt.KeepAspectRatio) if response.success.data == True: status_icon = QIcon.fromTheme('stock_yes') self._widget.label_status.setPixmap(status_icon.pixmap(status_icon.actualSize(QSize(24, 24)))) self._widget.pushButton_calibrate.setEnabled(True)
def command_cb(self): clickedButtonName = self._widget.sender().text() for key in self.commands.keys(): if (self.commands[key] == clickedButtonName): qWarning('Sending speech command: '+ key) command = Command() command.command = key self.speech_cmd_publisher.publish(command)
def _create_player(self): if not self._player: try: self._player = Player(self) if self._publish_clock: self._player.start_clock_publishing() except Exception as ex: qWarning('Error starting player; aborting publish: %s' % str(ex)) return False return True
def update_topics(self): self.model().clear() topic_list = rospy.get_published_topics() for topic_path, topic_type in topic_list: topic_name = topic_path.strip('/') message_class = roslib.message.get_message_class(topic_type) if message_class is None: qWarning('TopicCompleter.update_topics(): could not get message class for topic type "%s" on topic "%s"' % (topic_type, topic_path)) continue message_instance = message_class() self.model().add_message(message_instance, topic_name, topic_type, topic_path)
def rotate_head(self, button_name): if('Left' in button_name): #qWarning('x: %s, y: %s' % (self.head_x, self.head_y)) if (self.head_x < -0.8 and self.head_y > 0.0): self.show_warning('Can\'t rotate anymore') elif (self.head_y < 0.0): self.head_x += 0.1 self.head_y = -((1.0 - self.head_x ** 2.0) ** 0.5) self.show_text_in_rviz("Turning Head Left") else: self.head_x -= 0.1 self.head_y = (1.0 - self.head_x ** 2.0) ** 0.5 self.show_text_in_rviz("Turning Head Left") qWarning('x: %s, y: %s' % (self.head_x, self.head_y)) self.head_action(self.head_x, self.head_y, self.head_z) elif('Up' in button_name): if (self.head_z <= 1.6): self.head_z += 0.1 self.show_text_in_rviz("Moving Head Up") self.head_action(self.head_x, self.head_y, self.head_z) else: self.show_warning('Can\'t look up anymore') elif('Down' in button_name): if (self.head_z >= -2.2): self.head_z -= 0.1 self.show_text_in_rviz("Moving Head Down") self.head_action(self.head_x, self.head_y, self.head_z) else: self.show_warning('Can\'t look down anymore') else: #qWarning('x: %s, y: %s' % (self.head_x, self.head_y)) if (self.head_x < -0.8 and self.head_y < 0.0): self.show_warning('Can\'t rotate anymore') elif (self.head_y > 0.0): self.head_x += 0.1 self.head_y = (1.0 - self.head_x ** 2.0) ** 0.5 self.show_text_in_rviz("Turning Head Right") else: self.head_x -= 0.1 self.head_y = -((1.0 - self.head_x ** 2.0) ** 0.5) self.show_text_in_rviz("Turning Head Right") #qWarning('x: %s, y: %s' % (self.head_x, self.head_y)) self.head_action(self.head_x, self.head_y, self.head_z)
def level_changed(self, row): """ Handles the rowchanged event for the level_list widget Makes a service call to change the logger level for the indicated node/logger to the selected value :param row: the selected row in level_list, ''int'' """ if row == -1: return if row < 0 or row >= self.level_list.count(): qWarning('Level row %s out of bounds. Current count: %s' % (row, self.level_list.count())) return self._caller.send_logger_change_message(self.node_list.currentItem().text(), self.logger_list.currentItem().text(), self.level_list.item(row).text())
def dragEnterEvent(self, event): if not event.mimeData().hasText(): if not hasattr(event.source(), 'selectedItems') or len(event.source().selectedItems()) == 0: qWarning('Plot.dragEnterEvent(): not hasattr(event.source(), selectedItems) or len(event.source().selectedItems()) == 0') return item = event.source().selectedItems()[0] ros_topic_name = item.data(0, Qt.UserRole) if ros_topic_name is None: qWarning('Plot.dragEnterEvent(): not hasattr(item, ros_topic_name_)') return # TODO: do some checks for valid topic here event.acceptProposedAction()
def on_refresh_services_button_clicked(self): service_names = rosservice.get_service_list() self._services = {} for service_name in service_names: try: self._services[service_name] = rosservice.get_service_class_by_name(service_name) #qDebug('ServiceCaller.on_refresh_services_button_clicked(): found service %s using class %s' % (service_name, self._services[service_name])) except (rosservice.ROSServiceException, rosservice.ROSServiceIOException) as e: qWarning('ServiceCaller.on_refresh_services_button_clicked(): could not get class of service %s:\n%s' % (service_name, e)) self.service_combo_box.clear() self.service_combo_box.addItems(sorted(service_names))
def update_plot(self): if self.data_plot is not None: needs_redraw = False for topic_name, rosdata in self._rosdata.items(): try: data_x, data_y = rosdata.next() if data_x or data_y: self.data_plot.update_values(topic_name, data_x, data_y) needs_redraw = True except RosPlotException as e: qWarning('PlotWidget.update_plot(): error in rosplot: %s' % e) if needs_redraw: self.data_plot.redraw()
def _change_publisher_rate(self, publisher_info, topic_name, new_value): try: rate = float(new_value) except Exception: qWarning('Publisher._change_publisher_rate(): could not parse rate value: %s' % (new_value)) else: publisher_info['rate'] = rate #qDebug('Publisher._change_publisher_rate(): %s rate changed: %fHz' % (publisher_info['topic_name'], publisher_info['rate'])) publisher_info['timer'].stop() if publisher_info['enabled'] and publisher_info['rate'] > 0: publisher_info['timer'].start(int(1000.0 / publisher_info['rate'])) # make sure the column value reflects the actual rate return '%.2f' % publisher_info['rate']
def add_topic(self, topic_name): if topic_name in self._rosdata: qWarning('PlotWidget.add_topic(): topic already subscribed: %s' % topic_name) return self._rosdata[topic_name] = ROSData(topic_name, self._start_time) if self._rosdata[topic_name].error is not None: qWarning(str(self._rosdata[topic_name].error)) del self._rosdata[topic_name] else: data_x, data_y = self._rosdata[topic_name].next() self.data_plot.add_curve(topic_name, topic_name, data_x, data_y) self._subscribed_topics_changed()
def _refresh_loggers(self, node): """ Stores a list of loggers available for passed in node :param node: name of the node to query, ''str'' """ self._current_loggers = [] self._current_levels = {} servicename = node + '/get_loggers' try: service = rosservice.get_service_class_by_name(servicename) except rosservice.ROSServiceIOException as e: qWarning('During get_service_class_by_name "%s":\n%s' % (servicename, e)) return False request = service._request_class() proxy = rospy.ServiceProxy(str(servicename), service) try: response = proxy(request) except rospy.ServiceException as e: qWarning('SetupDialog.get_loggers(): request:\n%s' % (type(request))) qWarning('SetupDialog.get_loggers() "%s":\n%s' % (servicename, e)) return False if response._slot_types[0] == 'roscpp/Logger[]': for logger in getattr(response, response.__slots__[0]): self._current_loggers.append(getattr(logger, 'name')) self._current_levels[getattr(logger, 'name')] = getattr(logger, 'level') else: qWarning(repr(response)) return False return True
def start_plugin(self, plugin_name, argv): qDebug('PluginManagerDBusInterface.start_plugin(%s)' % plugin_name) plugins = self._plugin_manager.find_plugins_by_name(plugin_name) if len(plugins) == 0: msg = 'PluginManagerDBusInterface.start_plugin() found no plugin matching "%s"' % plugin_name qWarning(msg) return (1, msg) elif len(plugins) > 1: msg = 'PluginManagerDBusInterface.start_plugin() found multiple plugins matching "%s"\n%s' % (plugin_name, '\n'.join(plugins.values())) qWarning(msg) return (1, msg) plugin_id = plugins.keys()[0] self._plugin_manager.load_plugin(plugin_id, argv=argv.split(' ') if argv else []) return (0, plugin_id)
def _run_export_region(self, export_bag, topics, start_stamp, end_stamp, bag_entries): """ Threaded function that saves the current selection to a new bag file :param export_bag: bagfile to write to, ''rosbag.bag'' :param topics: topics to write to the file, ''list(str)'' :param start_stamp: start of area to save, ''rospy.Time'' :param end_stamp: end of area to save, ''rospy.Time'' """ total_messages = len(bag_entries) update_step = max(1, total_messages / 100) message_num = 1 progress = 0 # Write out the messages for bag, entry in bag_entries: if self.background_task_cancel: break try: topic, msg, t = self.read_message(bag, entry.position) export_bag.write(topic, msg, t) except Exception as ex: qWarning('Error exporting message at position %s: %s' % (str(entry.position), str(ex))) export_bag.close() self.stop_background_task() return if message_num % update_step == 0 or message_num == total_messages: new_progress = int(100.0 * (float(message_num) / total_messages)) if new_progress != progress: progress = new_progress if not self.background_task_cancel: self.background_progress = progress self.status_bar_changed_signal.emit() message_num += 1 # Close the bag try: self.background_progress = 0 self.status_bar_changed_signal.emit() export_bag.close() except Exception as ex: QMessageBox( QMessageBox.Warning, 'rqt_bag', 'Error closing bag file [%s]: %s' % (export_bag.filename, str(ex)), QMessageBox.Ok).exec_() self.stop_background_task()
def on_pushButton_refresh_clicked(self): self._services = {} # Select calibration services service_names = rosservice.get_service_list() for service_name in service_names: try: current_service = rosservice.get_service_class_by_name(service_name) if current_service.__name__ == CALIBRATION_SERVICE_TYPE_NAME: self._services[service_name] = current_service except (rosservice.ROSServiceException, rosservice.ROSServiceIOException) as e: qWarning('on_pushButton_refresh_clicked(): could not get class of service %s:\n%s' % (service_name, e)) self._widget.comboBox_services.clear() self._widget.comboBox_services.addItems(sorted(self._services.keys()))
def add_publisher(self, topic_name, type_name, rate, enabled): topic_name = str(topic_name) try: self._node._validate_topic_or_service_name(topic_name) except InvalidTopicNameException as e: qWarning(str(e)) return publisher_info = { 'topic_name': topic_name, 'type_name': str(type_name), 'rate': float(rate), 'enabled': bool(enabled), } self._add_publisher(publisher_info)
def load_plugins(self): for plugin in [ImagePlugin(), SandtrayPlugin()]: view = plugin.get_view_class() timeline_renderer = plugin.get_renderer_class() msg_types = plugin.get_message_types() for msg_type in msg_types: self._viewer_types.setdefault(msg_type, []).append(view) if timeline_renderer: self._timeline_renderers[msg_type] = timeline_renderer( self) qWarning('Loaded plugin %s' % view.name)
def _handle_load_clicked(self, checked): filename = QFileDialog.getOpenFileName( self, self.tr('Load from File'), '.', self.tr('rqt_console message file {.csv} (*.csv)')) if filename[0] != '': try: handle = open(filename[0]) except IOError as e: qWarning(str(e)) return self.pause_button.setChecked(True) self._handle_pause_clicked(True) self._datamodel.load_from_file(handle) handle.close() self.update_status()
def add_topic(self, topic_name): if topic_name in self._rosdata: qWarning('PlotWidget.add_topic(): topic already subscribed: %s' % topic_name) # NOQA return self._rosdata[topic_name] = ROSData(topic_name, self._start_time) if self._rosdata[topic_name].error is not None: qWarning(str(self._rosdata[topic_name].error)) del self._rosdata[topic_name] else: data_x, data_y = self._rosdata[topic_name].next() self.data_plot.add_curve(topic_name, topic_name, data_x, data_y) self._subscribed_topics_changed()
def update_topics(self): self.model().clear() topic_list = rospy.get_published_topics() for topic_path, topic_type in topic_list: topic_name = topic_path.strip('/') message_class = roslib.message.get_message_class(topic_type) if message_class is None: qWarning( 'TopicCompleter.update_topics(): ' 'could not get message class for topic type "%s" on topic "%s"' % (topic_type, topic_path)) continue message_instance = message_class() self.model().add_message(message_instance, topic_name, topic_type, topic_path)
def _find_plugins(self, export_tag, discovery_data): crawl = True if discovery_data: data = discovery_data.get_settings('rqt_gui.RospkgPluginProvider') export_data = data.get_settings(export_tag) crawl = export_tag not in data.child_groups() plugins = [] if crawl: qDebug("RospkgPluginProvider._find_plugins() crawling for plugins of type '%s'" % export_tag) for package_name, package_path in get_packages_with_prefixes().items(): package_share_path = os.path.join(package_path, 'share', package_name) package_file_path = os.path.join( package_share_path, PACKAGE_MANIFEST_FILENAME) if os.path.isfile(package_file_path): # only try to import catkin if a PACKAGE_FILE is found try: package = parse_package(package_file_path) except InvalidPackage as e: qWarning('Could not parse package file "%s":\n%s' % (package_file_path, e)) continue for export in package.exports: if export.tagname != export_tag or 'plugin' not in export.attributes: continue plugin_xml_path = export.attributes['plugin'] plugin_xml_path = plugin_xml_path.replace('${prefix}', package_share_path) plugins.append([package_name, plugin_xml_path]) continue # write crawling information to cache if discovery_data: plugins_by_package = {} for (package_name, export) in plugins: if package_name not in plugins_by_package: plugins_by_package[package_name] = [] plugins_by_package[package_name].append(export) for package_name, exports in plugins_by_package.items(): export_data.set_value(package_name, os.pathsep.join([str(e) for e in exports])) else: # use cached information for package_name in export_data.all_keys(): exports = export_data.value(package_name) if exports: for export in exports.split(os.pathsep): plugins.append([package_name, export]) return plugins
def _load_plugin_load(self, instance_id, callback, argv=None): # if the requested instance is already running, do nothing if str(instance_id) in self._running_plugins: raise Exception( 'PluginManager._load_plugin(%s) instance already loaded' % str(instance_id)) # containers are pseudo-plugins and handled by a special handler if self._container_manager is not None and instance_id.plugin_id == self._container_manager.get_container_descriptor( ).plugin_id(): handler = PluginHandlerContainer(self, self._main_window, instance_id, self._application_context, self._container_manager) # use platform specific handler for multiprocess-mode if available elif self._application_context.options.multi_process or self._application_context.options.embed_plugin: try: from .plugin_handler_xembed import PluginHandlerXEmbed handler = PluginHandlerXEmbed(self, self._main_window, instance_id, self._application_context, self._container_manager, argv) except ImportError: qCritical( 'PluginManager._load_plugin() could not load plugin in a separate process' ) return # use direct handler for in-process plugins else: handler = PluginHandlerDirect(self, self._main_window, instance_id, self._application_context, self._container_manager, argv) handler.set_minimized_dock_widgets_toolbar( self._minimized_dock_widgets_toolbar) if instance_id.plugin_id not in self._plugin_descriptors.keys(): qWarning( 'PluginManager._load_plugin() could not load plugin "%s": plugin not available' % (instance_id.plugin_id)) return plugin_descriptor = self._plugin_descriptors[instance_id.plugin_id] handler.set_plugin_descriptor(plugin_descriptor) self._add_running_plugin(instance_id, handler) handler.load(self._plugin_provider, callback)
def level_changed(self, row): """ Handles the rowchanged event for the level_list widget Makes a service call to change the logger level for the indicated node/logger to the selected value :param row: the selected row in level_list, ''int'' """ if row == -1: return if row < 0 or row >= self.level_list.count(): qWarning('Level row %s out of bounds. Current count: %s' % (row, self.level_list.count())) return self._caller.send_logger_change_message( self.node_list.currentItem().text(), self.logger_list.currentItem().text(), self.level_list.item(row).text())
def save_to_file(self, filehandle): """ Saves to an already open filehandle. :return: True if file write is successful, ''bool'' OR :return: False if file write fails, ''bool'' """ try: filehandle.write(self.sourceModel()._messages.header_print()) for index in range(self.rowCount()): row = self.mapToSource(self.index(index, 0)).row() filehandle.write(self.sourceModel()._messages.get_message_list()[row].file_print()) except Exception as e: qWarning('File save failed: %s' % str(e)) return False return True
def _handle_save_clicked(self, checked): filename = QFileDialog.getSaveFileName( self, 'Save to File', '.', self.tr('rqt_console msg file {.csv} (*.csv)')) if filename[0] != '': filename = filename[0] if filename[-4:] != '.csv': filename += '.csv' try: handle = open(filename, 'w') except IOError as e: qWarning(str(e)) return self._proxymodel.save_to_file(handle) handle.close() self.update_status()
def __init__(self, topic_name, topic_type): super(TopicInfo, self).__init__(100) self._subscriber = None self.monitoring = False self._reset_data() self.message_class = None self._topic_name = None try: self.message_class = roslib.message.get_message_class(topic_type) self._topic_name = topic_name except Exception as e: self.message_class = None self._topic_name = None qWarning( 'TopicInfo.__init__(): can not get message class info for "%s":\n%s' % (topic_name, e))
def _change_publisher_rate(self, publisher_info, topic_name, new_value): try: rate = float(new_value) except Exception: qWarning( 'Publisher._change_publisher_rate(): could not parse rate value: %s' % (new_value)) else: publisher_info['rate'] = rate #qDebug('Publisher._change_publisher_rate(): %s rate changed: %fHz' % (publisher_info['topic_name'], publisher_info['rate'])) publisher_info['timer'].stop() if publisher_info['enabled'] and publisher_info['rate'] > 0: publisher_info['timer'].start( int(1000.0 / publisher_info['rate'])) # make sure the column value reflects the actual rate return '%.2f' % publisher_info['rate']
def start_plugin(self, plugin_name, argv): qDebug('PluginManagerDBusInterface.start_plugin(%s)' % plugin_name) plugins = self._plugin_manager.find_plugins_by_name(plugin_name) if len(plugins) == 0: msg = 'PluginManagerDBusInterface.start_plugin() found no plugin matching "%s"' % plugin_name qWarning(msg) return (1, msg) elif len(plugins) > 1: msg = 'PluginManagerDBusInterface.start_plugin() found multiple plugins matching "%s"\n%s' % ( plugin_name, '\n'.join(plugins.values())) qWarning(msg) return (1, msg) plugin_id = plugins.keys()[0] self._plugin_manager.load_plugin(plugin_id, argv=argv.split(' ') if argv else []) return (0, plugin_id)
def _process_msg_expression(self, expression): """ Checks if expression matches the format <package_name>.msg.<str2> If expression matches that format then we attempt to import <package_name> and store it in self._eval_locals[<package_name>] for use with eval. """ tokens = expression.lstrip('[').split('.', 2) if len(tokens) == 3 and tokens[1] == 'msg': try: module = importlib.import_module(tokens[0]) self._eval_locals[tokens[0]] = module except ModuleNotFoundError: qWarning( 'ServiceCallerWidget._process_msg_expression failed to import: {}.' .format(tokens[0] + '.msg'))
def startDrag(self, supportedActions): index = self.currentIndex() if not index.isValid(): return item = self.model().itemFromIndex(index) path = getattr(item, '_path', None) if path is None: qWarning('MessageTreeWidget.startDrag(): no _path set on item %s' % item) return data = QMimeData() data.setText(item._path) drag = QDrag(self) drag.setMimeData(data) drag.exec_()
def dragEnterEvent(self, event): if not event.mimeData().hasText(): if not hasattr(event.source(), 'selectedItems') or len( event.source().selectedItems()) == 0: qWarning( 'Plot.dragEnterEvent(): not hasattr(event.source(), selectedItems) or len(event.source().selectedItems()) == 0' ) return item = event.source().selectedItems()[0] ros_topic_name = item.data(0, Qt.UserRole) if ros_topic_name is None: qWarning( 'Plot.dragEnterEvent(): not hasattr(item, ros_topic_name_)' ) return # TODO: do some checks for valid topic here event.acceptProposedAction()
def __init__(self, topic_name, topic_type): super(TopicInfo, self).__init__(100) self._topic_name = topic_name self.error = None self._subscriber = None self.monitoring = False self._reset_data() self.message_class = None try: self.message_class = roslib.message.get_message_class(topic_type) except Exception as e: self.message_class = None qWarning('TopicInfo.__init__(): %s' % (e)) if self.message_class is None: self.error = 'can not get message class for type "%s"' % topic_type qWarning('TopicInfo.__init__(): topic "%s": %s' % (topic_name, self.error))
def on_refresh_services_button_clicked(self): service_names = rosservice.get_service_list() self._services = {} for service_name in service_names: try: self._services[ service_name] = rosservice.get_service_class_by_name( service_name) #qDebug('ServiceCaller.on_refresh_services_button_clicked(): found service %s using class %s' % (service_name, self._services[service_name])) except (rosservice.ROSServiceException, rosservice.ROSServiceIOException) as e: qWarning( 'ServiceCaller.on_refresh_services_button_clicked(): could not get class of service %s:\n%s' % (service_name, e)) self.service_combo_box.clear() self.service_combo_box.addItems(sorted(service_names))
def dragEnterEvent(self, e): if not e.mimeData().hasText(): if not hasattr(e.source(), 'selectedItems') or len(e.source().selectedItems()) == 0: qWarning('NavView.dragEnterEvent(): not hasattr(event.source(), selectedItems) or len(event.source().selectedItems()) == 0') return item = e.source().selectedItems()[0] topic_name = item.data(0, Qt.UserRole) if topic_name == None: qWarning('NavView.dragEnterEvent(): not hasattr(item, ros_topic_name_)') return else: topic_name = str(e.mimeData().text()) if accepted_topic(topic_name): e.accept() e.acceptProposedAction()
def __init__(self): self.player = None try: import ossaudiodev self.device = ossaudiodev.open('w') self.device.setfmt(ossaudiodev.AFMT_S16_LE) self.player = 'oss' except Exception, e: qWarning('Could not open dsp device :%s'%e) try: import alsaaudio self.device = alsaaudio.PCM() self.device.setformat(alsaaudio.PCM_FORMAT_S16_LE) self.player = 'alsa' qWarning('Using alsaaudio. If sound quality is not good enough, consider installing osspd') except Exception, e: raise e
def add_topic(self, topic_name): topics_changed = False for topic_name in get_plot_fields(topic_name)[0]: if topic_name in self._rosdata: qWarning('PlotWidget.add_topic(): topic already subscribed: %s' % topic_name) continue self._rosdata[topic_name] = ROSData(topic_name, self._start_time) if self._rosdata[topic_name].error is not None: qWarning(str(self._rosdata[topic_name].error)) del self._rosdata[topic_name] else: data_x, data_y = self._rosdata[topic_name].next() self.data_plot.add_curve(topic_name, topic_name, data_x, data_y) topics_changed = True if topics_changed: self._subscribed_topics_changed()
def logger_changed(self, row): """ Handles the rowchanged event for the logger_list widget Populates level_list with the levels for the logger selected :param row: the selected row in logger_list, ''int'' """ if row == -1: return if row < 0 or row >= self.logger_list.count(): qWarning('Logger row %s out of bounds. Current count: %s' % (row, self.logger_list.count())) return if self.level_list.count() == 0: for level in self._caller.get_levels(): self.level_list.addItem(level) for index in range(self.level_list.count()): if self.level_list.item(index).text().lower() == self._caller._current_levels[self.logger_list.currentItem().text()].lower(): self.level_list.setCurrentRow(index)
def _evaluate_expression(self, expression, slot_type=None, is_array=False): successful_eval = True successful_conversion = True self._process_msg_expression(expression) try: # try to evaluate expression value = eval(expression, {}, self._eval_locals) except Exception: # just use expression-string as value value = expression successful_eval = False if is_array: if not type(value) is list: value = list(value) if slot_type and len(value) > 0 and type( value[0]) is not slot_type: for i, v in enumerate(value): try: # try to convert value to right type value[i] = slot_type(v) except Exception: successful_conversion = False else: if slot_type and type(value) != slot_type: try: # try to convert value to right type value = slot_type(value) except Exception: successful_conversion = False if successful_conversion: return value elif successful_eval: qWarning('ServiceCaller._evaluate_expression(): ' 'can not convert expression to slot type: %s -> %s' % (type(value), slot_type)) else: qWarning( 'ServiceCaller._evaluate_expression(): failed to evaluate expression: %s' % (expression)) return None
def _load_plugin_completed(self, handler, exception): instance_id = handler.instance_id() if exception is not None: if isinstance(exception, PluginLoadError): qWarning('PluginManager._load_plugin() could not load plugin "%s": %s' % (instance_id.plugin_id, exception)) else: qCritical('PluginManager._load_plugin() could not load plugin "%s"%s' % (instance_id.plugin_id, (':\n%s' % traceback.format_exc() if exception != True else ''))) self._remove_running_plugin(instance_id) # quit embed application if self._application_context.options.embed_plugin: exit(-1) return qDebug('PluginManager._load_plugin(%s) successful' % str(instance_id)) handler.close_signal.connect(self.unload_plugin) handler.reload_signal.connect(self.reload_plugin) handler.help_signal.connect(self._emit_plugin_help_signal)
def save_pose(self): # Add to database name = self.name_textbox.text() pose = self.gui.get_joint_state(self.side) qWarning('Saving pose as: ' + name) isAdded = self.gui.arm_db.savePos(self.side, name, pose) if not isAdded: # name already exists... self.reject() return # Update GUI if self.side == PoseSaver.LEFT: self.gui.combo_box_left.addItem(name, pose) else: # self.side == PoseSaver.RIGHT: self.gui.combo_box_right.addItem(name, pose) self.accept()
def record_bag(self, filename, all=True, topics=[], regex=False, limit=0): try: self._recorder = Recorder( filename, bag_lock=self._bag_lock, all=all, topics=topics, regex=regex, limit=limit) except Exception as ex: qWarning('Error opening bag for recording [%s]: %s' % (filename, str(ex))) return self._recorder.add_listener(self._message_recorded) self.add_bag(self._recorder.bag) self._recorder.start() self.wrap = False self._timeline_frame._index_cache_thread.period = 0.1 self.update()
def _add_toolbar(self, toolbar): # every toolbar needs a unique name for save/restore geometry/state to work toolbar_object_name = toolbar.objectName() prefix = self._instance_id.tidy_str() + '__' # when added, removed and readded the prefix should not be prepended multiple times if not toolbar_object_name.startswith(prefix): toolbar_object_name = prefix + toolbar_object_name toolbar.setObjectName(toolbar_object_name) if self._application_context.options.freeze_layout: toolbar.setMovable(False) self._toolbars.append(toolbar) if self._main_window is not None: # warn about toolbar with same object name old_toolbar = self._main_window.findChild(QToolBar, toolbar.objectName()) if old_toolbar is not None: qWarning('PluginHandler._add_toolbar() duplicate object name "%s", assign unique object names before adding toolbars!' % toolbar.objectName()) self._main_window.addToolBar(Qt.TopToolBarArea, toolbar)
def logger_changed(self, row): """ Handles the rowchanged event for the logger_list widget Populates level_list with the levels for the logger selected :param row: the selected row in logger_list, ''int'' """ if row == -1: return if row < 0 or row >= self.logger_list.count(): qWarning('Logger row %s out of bounds. Current count: %s' % (row, self.logger_list.count())) return if self.level_list.count() == 0: for level in self._caller.get_levels(): self.level_list.addItem(level) for index in range(self.level_list.count()): if self.level_list.item(index).text().lower() == \ self._caller._current_levels[self.logger_list.currentItem().text()].lower(): self.level_list.setCurrentRow(index)
def add_topic(self, topic_code, topic_item): topics_changed = False topic_name = topic_code + '/' + topic_item #for topic_name in get_plot_fields(topic_name)[0]: # <<<<<<<< this is what allows for multiple topics if topic_name in self._rosdata: qWarning('PlotWidget.add_topic(): topic already subscribed: %s' % topic_name) #continue return self._rosdata[topic_name] = ROSData(topic_code, topic_item, self._start_time) if self._rosdata[topic_name].error is not None: qWarning(str(self._rosdata[topic_name].error)) del self._rosdata[topic_name] else: data_x, data_y = next(self._rosdata[topic_name]) self.data_plot.add_curve(topic_name, topic_name, data_x, data_y) #print self._rosdata.items() # ------------------------------------------ topics_changed = True
def load_plugins(self): from rqt_gui.rospkg_plugin_provider import RospkgPluginProvider self.plugin_provider = RospkgPluginProvider('rqt_bag', 'rqt_bag::Plugin') plugin_descriptors = self.plugin_provider.discover(None) for plugin_descriptor in plugin_descriptors: try: plugin = self.plugin_provider.load(plugin_descriptor.plugin_id(), plugin_context=None) except Exception as e: qWarning('rqt_bag.TimelineFrame.load_plugins() failed to load plugin "%s":\n%s' % (plugin_descriptor.plugin_id(), e)) continue try: view = plugin.get_view_class() except Exception as e: qWarning('rqt_bag.TimelineFrame.load_plugins() failed to get view from plugin "%s":\n%s' % (plugin_descriptor.plugin_id(), e)) continue timeline_renderer = None try: timeline_renderer = plugin.get_renderer_class() except AttributeError: pass except Exception as e: qWarning('rqt_bag.TimelineFrame.load_plugins() failed to get renderer from plugin "%s":\n%s' % (plugin_descriptor.plugin_id(), e)) msg_types = [] try: msg_types = plugin.get_message_types() except AttributeError: pass except Exception as e: qWarning('rqt_bag.TimelineFrame.load_plugins() failed to get message types from plugin "%s":\n%s' % (plugin_descriptor.plugin_id(), e)) finally: if not msg_types: qWarning('rqt_bag.TimelineFrame.load_plugins() plugin "%s" declares no message types:\n%s' % (plugin_descriptor.plugin_id(), e)) for msg_type in msg_types: self._viewer_types.setdefault(msg_type, []).append(view) if timeline_renderer: self._timeline_renderers[msg_type] = timeline_renderer(self) qDebug('rqt_bag.TimelineFrame.load_plugins() loaded plugin "%s"' % plugin_descriptor.plugin_id())