def set_message(self, msg): """ Clears the tree view and displays the new message :param msg: message object to display in the treeview, ''msg'' """ # Remember whether items were expanded or not before deleting if self._msg: for item in self.get_all_items(): path = self.get_item_path(item) if item.isExpanded(): self._expanded_paths.add(path) elif path in self._expanded_paths: self._expanded_paths.remove(path) self.clear() if msg: # Populate the tree self._add_msg_object(None, '', '', msg, msg._type) if self._expanded_paths is None: self._expanded_paths = set() else: # Expand those that were previously expanded, and collapse any paths that we've seen for the first time for item in self.get_all_items(): path = self.get_item_path(item) if path in self._expanded_paths: item.setExpanded(True) else: item.setExpanded(False) self._msg = msg QWidget.update(self)
class MyPlugin(Plugin): def __init__(self, context): super(MyPlugin, self).__init__(context) # Give QObjects reasonable names self.setObjectName('MyPlugin') rp = rospkg.RosPack() # Process standalone plugin command-line arguments from argparse import ArgumentParser parser = ArgumentParser() # Add argument(s) to the parser. parser.add_argument("-q", "--quiet", action="store_true", dest="quiet", help="Put plugin in silent mode") args, unknowns = parser.parse_known_args(context.argv()) if not args.quiet: print 'arguments: ', args print 'unknowns: ', unknowns # Create QWidget self._widget = QWidget() # Get path to UI file which is a sibling of this file # in this example the .ui and .py file are in the same folder ui_file = os.path.join(rp.get_path('test'), 'resource', 'MyPlugin.ui') # Extend the widget with all attributes and children from UI file loadUi(ui_file, self._widget) # Give QObjects reasonable names self._widget.setObjectName('MyPluginUi') # Show _widget.windowTitle on left-top of each plugin (when # it's set in _widget). This is useful when you open multiple # plugins at once. Also if you open multiple instances of your # plugin at once, these lines add number to make it easy to # tell from pane to pane. if context.serial_number() > 1: self._widget.setWindowTitle(self._widget.windowTitle() + (' (%d)' % context.serial_number())) # Add widget to the user interface context.add_widget(self._widget) def shutdown_plugin(self): # TODO unregister all publishers here pass 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
def __init__(self, parent, updater, config, nodename): super(TabGroup, self).__init__(updater, config, nodename) self.parent = parent if not self.parent.tab_bar: self.parent.tab_bar = QTabWidget() self.wid = QWidget() self.wid.setLayout(self.grid) parent.tab_bar.addTab(self.wid, self.param_name)
def __init__(self, context): super(MyPlugin, self).__init__(context) # Give QObjects reasonable names self.setObjectName('MyPlugin') # Process standalone plugin command-line arguments from argparse import ArgumentParser parser = ArgumentParser() # Add argument(s) to the parser. parser.add_argument("-q", "--quiet", action="store_true", dest="quiet", help="Put plugin in silent mode") args, unknowns = parser.parse_known_args(context.argv()) if not args.quiet: print 'arguments: ', args print 'unknowns: ', unknowns # Create QWidget self._widget = QWidget() # Get path to UI file which should be in the "resource" folder of this package ui_file = os.path.join(rospkg.RosPack().get_path('my_plugin'), 'resource', 'MyPlugin.ui') # Extend the widget with all attributes and children from UI file loadUi(ui_file, self._widget) # Give QObjects reasonable names self._widget.setObjectName('MyPluginUi') # Show _widget.windowTitle on left-top of each plugin (when # it's set in _widget). This is useful when you open multiple # plugins at once. Also if you open multiple instances of your # plugin at once, these lines add number to make it easy to # tell from pane to pane. if context.serial_number() > 1: self._widget.setWindowTitle(self._widget.windowTitle() + (' (%d)' % context.serial_number())) # Push button. self._widget.button_test.clicked.connect(self.on_button_test_clicked) # Add widget to the user interface context.add_widget(self._widget) # Simple topic publisher from ROS tutorial. self.rosPub = rospy.Publisher('my_plugin_pub', String, queue_size=10) self.rosPubCount = 0 # Simple topic subscriber. self.rosSub = rospy.Subscriber("my_plugin_sub", String, self.ros_string_handler) # Start simple ROS server. self.rosSrv = rospy.Service("add_two_ints", AddTwoInts, self.handle_add_two_ints)
def __init__(self, context): """ Constructor """ super(CarlaControlPlugin, self).__init__(context) self.setObjectName('CARLA Control') self._widget = QWidget() self._node = CompatibleNode('rqt_carla_control_node') package_share_dir = roscomp.get_package_share_directory( 'rqt_carla_control') ui_file = os.path.join(package_share_dir, 'resource', 'CarlaControl.ui') loadUi(ui_file, self._widget) self._widget.setObjectName('CarlaControl') if context.serial_number() > 1: self._widget.setWindowTitle(self._widget.windowTitle() + (' (%d)' % context.serial_number())) self.pause_icon = QIcon( QPixmap(os.path.join(package_share_dir, 'resource', 'pause.png'))) self.play_icon = QIcon( QPixmap(os.path.join(package_share_dir, 'resource', 'play.png'))) self._widget.pushButtonStepOnce.setIcon( QIcon( QPixmap( os.path.join(package_share_dir, 'resource', 'step_once.png')))) self.carla_status = None self.carla_status_subscriber = self._node.new_subscription( CarlaStatus, "/carla/status", self.carla_status_changed, qos_profile=10) self.carla_control_publisher = self._node.new_publisher( CarlaControl, "/carla/control", qos_profile=10) self._widget.pushButtonPlayPause.setDisabled(True) self._widget.pushButtonStepOnce.setDisabled(True) self._widget.pushButtonPlayPause.setIcon(self.play_icon) self._widget.pushButtonPlayPause.clicked.connect( self.toggle_play_pause) self._widget.pushButtonStepOnce.clicked.connect(self.step_once) context.add_widget(self._widget) if roscomp.get_ros_version() == 2: spin_thread = threading.Thread(target=self._node.spin, daemon=True) spin_thread.start()
def __init__(self, context): super(HilPlugin, self).__init__(context) self.setObjectName('HilPlugin') self._widget = QWidget() rp = rospkg.RosPack() ui_file = os.path.join(rospkg.RosPack().get_path('rqt_rotors'), 'resource', 'HilPlugin.ui') loadUi(ui_file, self._widget) self._widget.setObjectName('HilPluginUi') if context.serial_number() > 1: self._widget.setWindowTitle(self._widget.windowTitle() + (' (%d)' % context.serial_number())) context.add_widget(self._widget) # Set the initial parameters of UI elements self._widget.button_set_hil_mode.setEnabled(False) self._widget.button_arm.setEnabled(False) self._widget.button_reboot_autopilot.setEnabled(False) self._widget.text_state.setText(self.STR_UNKNOWN) self.clear_mav_mode() # Initialize class variables self.last_heartbeat_time = time.time() self.mav_mode = 65 self.mav_status = 255 self.armed = False self.connected = False self.guided = False self.hil_enabled = False # Set the functions that are called when signals are emitted self._widget.button_set_hil_mode.pressed.connect( self.on_set_hil_mode_button_pressed) self._widget.button_arm.pressed.connect(self.on_arm_button_pressed) self._widget.button_reboot_autopilot.pressed.connect( self.on_reboot_autopilot_button_pressed) # Create ROS service proxies self.arm = rospy.ServiceProxy(self.STR_MAVROS_ARM_SERVICE_NAME, CommandBool) self.send_command_long = rospy.ServiceProxy( self.STR_MAVROS_COMMAND_LONG_SERVICE_NAME, CommandLong) self.set_mode = rospy.ServiceProxy( self.STR_MAVROS_SET_MODE_SERVICE_NAME, SetMode) # Initialize ROS subscribers and publishers self.sys_status_sub = rospy.Subscriber(self.STR_SYS_STATUS_SUB_TOPIC, State, self.sys_status_callback, queue_size=1)
def __init__(self, context): super(MyPlugin, self).__init__(context) # Give QObjects reasonable names self.setObjectName('MyPlugin') # Process standalone plugin command-line arguments from argparse import ArgumentParser parser = ArgumentParser() # Add argument(s) to the parser. parser.add_argument("-q", "--quiet", action="store_true", dest="quiet", help="Put plugin in silent mode") args, unknowns = parser.parse_known_args(context.argv()) if not args.quiet: print 'arguments: ', args print 'unknowns: ', unknowns # Create QWidget self._widget = QWidget() # Get path to UI file which should be in the "resource" folder of this package ui_file = os.path.join(rospkg.RosPack().get_path('m3_rqt'), 'resource', 'MyPlugin.ui') # Extend the widget with all attributes and children from UI file loadUi(ui_file, self._widget) # Give QObjects reasonable names self._widget.setObjectName('M3') # Show _widget.windowTitle on left-top of each plugin (when # it's set in _widget). This is useful when you open multiple # plugins at once. Also if you open multiple instances of your # plugin at once, these lines add number to make it easy to # tell from pane to pane. if context.serial_number() > 1: self._widget.setWindowTitle(self._widget.windowTitle() + (' (%d)' % context.serial_number())) # Add widget to the user interface context.add_widget(self._widget) self.target_pos = self._widget.findChild(QSlider, "target_pos") self.target_force = self._widget.findChild(QSlider, "target_force") self.target_pos.valueChanged.connect(self.pos_target_change) self.target_force.valueChanged.connect(self.force_target_change) import select, socket self.s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) self.s.bind(('255.255.255.255', self.port)) self.s.setblocking(0) self.server_thread = threading.Thread(target=self.receiveStatus) self.server_thread.daemon = True self.server_thread.start() self.s_cmd = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
def __init__(self, context): super(MyPlugin, self).__init__(context) # Give QObjects reasonable names self.setObjectName('MyPlugin') # Create publisher self.signal_publisher = rospy.Publisher('/gui_signal', String, queue_size=10) # self.speech_publisher = rospy.Publisher('/speech_content', String, queue_size=10) # Process standalone plugin command-line arguments from argparse import ArgumentParser parser = ArgumentParser() # Add argument(s) to the parser parser.add_argument("-q", "--quiet", action="store_true", dest="quiet", help="Put plugin in silent mode") args, unknowns = parser.parse_known_args(context.argv()) if not args.quiet: print 'arguments: ', args print 'unknowns: ', unknowns # Create QWidget self._widget = QWidget() # Get path to UI file which should be in the "resource" folder of this package ui_file = os.path.join(rospkg.RosPack().get_path('rqt_mypkg'), 'resource', 'MyPlugin.ui') # Extend the widget with all atrributes and children from UI File loadUi(ui_file, self._widget) # Give QObjects reasonable names self._widget.setObjectName('MyPluginUi') # Show _widget.windowTitle on left-top of each plugin(when it's set in _widget). # This is useful when you open multiple plugins aat once. Also if you open multiple # instances of your plugin at once, these lines add number to make it easy to # tell from pane to pane. if context.serial_number() > 1: self._widget.setWindowTitle(self._widget.windowTitle() + (' %d' % context.serial_number())) else: self._widget.setWindowTitle(self._widget.windowTitle()) # Add widget to the user interface context.add_widget(self._widget) self._widget.motorinitButton.clicked[bool].connect( self.__handle_motor_init_clicked) self._widget.positioninitButton.clicked[bool].connect( self.__handle_position_init_clicked) self._widget.stopButton.clicked[bool].connect( self.__handle_stop_clicked) self._widget.startButton.clicked[bool].connect( self.__handle_start_clicked) self._widget.standbyButton.clicked[bool].connect( self.__handle_standby_clicked)
def __init__(self, context): super(GaussPlugin, self).__init__(context) # Give QObjects reasonable names self.setObjectName('GaussPlugin') rp = rospkg.RosPack() rospy.loginfo('[RQt] Started Gauss RQt node!') # Process standalone plugin command-line arguments from argparse import ArgumentParser parser = ArgumentParser() # Add argument(s) to the parser. parser.add_argument("-q", "--quiet", action="store_true", dest="quiet", help="Put plugin in silent mode") args, unknowns = parser.parse_known_args(context.argv()) if not args.quiet: print '[RQt] arguments: ', args print '[RQt] unknowns: ', unknowns # Create QWidget self._widget = QWidget() # Get path to UI file which is a sibling of this file # in this example the .ui and .py file are in the same folder ui_file = os.path.join(rp.get_path('rqt_gauss'), 'resource', 'GaussPlugin.ui') # Extend the widget with all attributes and children from UI file loadUi(ui_file, self._widget) # Give QObjects reasonable names self._widget.setObjectName('GaussPluginUi') # Do connections and stuff here. For complex plugins, consider # creating custom helper classes instead of QWidget self.status_pub = rospy.Publisher('/gauss/flight', RPSChangeFlightStatus, queue_size=1) self.acceptance_pub = rospy.Publisher('/gauss/flightacceptance', RPSFlightPlanAccept, queue_size=1) rospy.Subscriber('/gauss/alternative_flight_plan', UTMAlternativeFlightPlan, self.alternative_flight_plan_callback) self.read_icao_service = rospy.ServiceProxy('/gauss/read_icao', ReadIcao) self._widget.refresh_button.clicked.connect(self.handle_refresh_button_clicked) self._widget.start_button.clicked.connect(self.handle_start_button_clicked) self._widget.stop_button.clicked.connect(self.handle_stop_button_clicked) self.pop_up.connect(self.show_pop_up) self.alternative_flight_plan = None self.handle_refresh_button_clicked() # Try to refresh here # Show _widget.windowTitle on left-top of each plugin (when # it's set in _widget). This is useful when you open multiple # plugins at once. Also if you open multiple instances of your # plugin at once, these lines add number to make it easy to # tell from pane to pane. if context.serial_number() > 1: self._widget.setWindowTitle(self._widget.windowTitle() + (' (%d)' % context.serial_number())) # Add widget to the user interface context.add_widget(self._widget)
class PID(Plugin): def __init__(self, context): super(PID, self).__init__(context) # Give QObjects reasonable names self.setObjectName('CamConfig') # Process standalone plugin command-line arguments from argparse import ArgumentParser parser = ArgumentParser() # Add argument(s) to the parser. parser.add_argument("-q", "--quiet", action="store_true", dest="quiet", help="Put plugin in silent mode") args, unknowns = parser.parse_known_args(context.argv()) if not args.quiet: print 'Running rqt_pid' # Create QWidget self._widget = QWidget() # Get path to UI file which should be in the "resource" folder of this package ui_file = os.path.join(rospkg.RosPack().get_path('rqt_pid'), 'resource', 'pid.ui') # Extend the widget with all attributes and children from UI file loadUi('/home/krishan/catkin_ws/src/rqt_pid/resource/pid.ui', self._widget, {'PIDView': 'PIDView'}) # Give QObjects reasonable names self._widget.setObjectName('PID_UI') # Show _widget.windowTitle on left-top of each plugin (when # it's set in _widget). This is useful when you open multiple # plugins at once. Also if you open multiple instances of your # plugin at once, these lines add number to make it easy to # tell from pane to pane. if context.serial_number() > 1: self._widget.setWindowTitle(self._widget.windowTitle() + (' (%d)' % context.serial_number())) # Add widget to the user interface context.add_widget(self._widget) def shutdown_plugin(self): # TODO unregister all publishers here pass 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
def __init__(self, context): super(Ros2KnowledgeGraph, self).__init__(context) self._node = context.node self._logger = self._node.get_logger().get_child( 'ros2_knowledge_graph_viewer.ros2_knowledge_graph.Ros2KnowledgeGraph' ) self.setObjectName('Ros2KnowledgeGraph') self._ros2_knowledge_graph = Ros2KnowledgeGraphImpl() self._current_dotcode = None self._widget = QWidget() self.dotcode_factory = PydotFactory() self.dotcode_generator = Ros2KnowledgeGraphDotcodeGenerator() self.dot_to_qt = DotToQtGenerator() _, package_path = get_resource('packages', 'ros2_knowledge_graph_viewer') ui_file = os.path.join(package_path, 'share', 'ros2_knowledge_graph_viewer', 'resource', 'Ros2KnowledgeGraph.ui') loadUi(ui_file, self._widget, {'InteractiveGraphicsView': InteractiveGraphicsView}) self._widget.setObjectName('Ros2KnowledgeGraphUi') if context.serial_number() > 1: self._widget.setWindowTitle(self._widget.windowTitle() + (' (%d)' % context.serial_number())) self._scene = QGraphicsScene() self._scene.setBackgroundBrush(Qt.white) self._widget.graphics_view.setScene(self._scene) self._widget.save_as_svg_push_button.setIcon( QIcon.fromTheme('document-save-as')) self._widget.save_as_svg_push_button.pressed.connect(self._save_svg) self._widget.save_as_image_push_button.setIcon( QIcon.fromTheme('image')) self._widget.save_as_image_push_button.pressed.connect( self._save_image) self._update_ros2_knowledge_graph() self._deferred_fit_in_view.connect(self._fit_in_view, Qt.QueuedConnection) self._deferred_fit_in_view.emit() context.add_widget(self._widget) self._updateTimer = QtCore.QTimer() self._updateTimer.timeout.connect(self.do_update) self._updateTimer.start(10)
def __init__(self, frame_editor): self.editor = frame_editor self.editor.observers.append(self) self.old_frame = None self.layout = QtWidgets.QGridLayout() self.widget = QWidget() self.widget.setLayout(self.layout) self.mesh_label = QtWidgets.QLineEdit("File:") self.mesh_label.setSizePolicy(QtWidgets.QSizePolicy.Ignored, QtWidgets.QSizePolicy.Fixed) self.mesh_button = QtWidgets.QPushButton("Open") self.mesh_button.clicked.connect(self.btn_open_mesh_clicked) self.diameter_label = QtWidgets.QLabel("Diameter:") self.diameter_spinbox = QtWidgets.QDoubleSpinBox() self.diameter_spinbox.editingFinished.connect(self.diameter_changed) self.length_label = QtWidgets.QLabel("Length:") self.length_spinbox = QtWidgets.QDoubleSpinBox() self.length_spinbox.editingFinished.connect(self.length_changed) self.width_label = QtWidgets.QLabel("Width:") self.width_spinbox = QtWidgets.QDoubleSpinBox() self.width_spinbox.editingFinished.connect(self.width_changed) self.height_label = QtWidgets.QLabel("Height:") self.height_spinbox = QtWidgets.QDoubleSpinBox() self.height_spinbox.editingFinished.connect(self.height_changed) self.color_label = QtWidgets.QLabel() self.color_label.setAutoFillBackground(True) self.update_color_label(None) self.color_button = QtWidgets.QPushButton("Set Color") self.color_button.clicked.connect(self.btn_color_clicked) self.layout.addWidget(self.mesh_label, 0, 0) self.layout.addWidget(self.mesh_button, 0, 1) self.layout.addWidget(self.diameter_label, 1, 0) self.layout.addWidget(self.diameter_spinbox, 1, 1) self.layout.addWidget(self.length_label, 2, 0) self.layout.addWidget(self.length_spinbox, 2, 1) self.layout.addWidget(self.width_label, 3, 0) self.layout.addWidget(self.width_spinbox, 3, 1) self.layout.addWidget(self.height_label, 4, 0) self.layout.addWidget(self.height_spinbox, 4, 1) self.layout.addWidget(self.color_label, 5, 0) self.layout.addWidget(self.color_button, 5, 1) self.update_widget(None)
def __init__(self, context): '''init initializes the widget and sets up our subscriber, publisher and event handlers''' super(PlexilPlanSelectionGUI, self).__init__(context) self.setObjectName('PlexilPlanSelectionGUI') # Process standalone plugin command-line arguments parser = ArgumentParser() parser.add_argument("-q", "--quiet", action="store_true", dest="quiet", help="Put plugin in silent mode") args, unknowns = parser.parse_known_args(context.argv()) # Find resources and Create QWidget self._widget = QWidget() ui_file = os.path.join(rospkg.RosPack().get_path('ow_plexil'), 'rqt_plexil_plan_selection', 'resource', 'plexil_plan_selection.ui') loadUi(ui_file, self._widget) self._widget.setObjectName('PlexilPlanSelectionUI') if context.serial_number() > 1: self._widget.setWindowTitle(self._widget.windowTitle() + (' (%d)' % context.serial_number())) context.add_widget(self._widget) #set window icon icon = os.path.join(rospkg.RosPack().get_path('ow_plexil'), 'rqt_plexil_plan_selection', 'resource', 'icon.png') self._widget.setWindowIcon(QIcon(icon)) #pub and sub setup self.status_publisher = rospy.Publisher('plexil_plan_selection_status', String, queue_size=20) self.status_subscriber = rospy.Subscriber('plexil_plan_selection_status', String, self.status_callback) #client placeholder self.plan_select_client = None #Qt signal to modify GUI from callback self.monitor_signal[str].connect(self.monitor_status) #populates the plan list, shows different plans based off of what launch file is running if rospy.get_param('owlat_flag', False): owlat_plan_dir = os.path.join(rospkg.RosPack().get_path('ow_plexil'), 'src', 'plans', 'owlat_plans') self.populate_plan_list(owlat_plan_dir) else: ow_plan_dir = os.path.join(rospkg.RosPack().get_path('ow_plexil'), 'src', 'plans') self.populate_plan_list(ow_plan_dir) #sets up tables self._widget.sentPlansTable.setSizeAdjustPolicy(QAbstractScrollArea.AdjustToContents) self._widget.planQueueTable.setSizeAdjustPolicy(QAbstractScrollArea.AdjustToContents) self._widget.sentPlansTable.insertColumn(0) self._widget.sentPlansTable.insertColumn(1) self._widget.planQueueTable.insertColumn(0) #sets up event listeners self._widget.addButton.clicked[bool].connect(self.handle_add_button_clicked) self._widget.removeButton.clicked[bool].connect(self.handle_remove_button_clicked) self._widget.upButton.clicked[bool].connect(self.handle_up_button_clicked) self._widget.downButton.clicked[bool].connect(self.handle_down_button_clicked) self._widget.sendButton.clicked[bool].connect(self.handle_send_button_clicked) self._widget.resetButton.clicked[bool].connect(self.handle_reset_button_clicked)
class MyPlugin(Plugin): def __init__(self, context): super(MyPlugin, self).__init__(context) # Give QObjects reasonable names self.setObjectName('MyPlugin') rp = rospkg.RosPack() # Process standalone plugin command-line arguments from argparse import ArgumentParser parser = ArgumentParser() # Add argument(s) to the parser. parser.add_argument("-q", "--quiet", action="store_true", dest="quiet", help="Put plugin in silent mode") args, unknowns = parser.parse_known_args(context.argv()) if not args.quiet: print 'arguments: ', args print 'unknowns: ', unknowns # Create QWidget self._widget = QWidget() # Get path to UI file which is a sibling of this file # in this example the .ui and .py file are in the same folder ui_file = os.path.join(rp.get_path('rqt_mypkg'), 'resource', 'MyPlugin.ui') # Extend the widget with all attributes and children from UI file loadUi(ui_file, self._widget) # Give QObjects reasonable names self._widget.setObjectName('MyPluginUi') # Show _widget.windowTitle on left-top of each plugin (when # it's set in _widget). This is useful when you open multiple # plugins at once. Also if you open multiple instances of your # plugin at once, these lines add number to make it easy to # tell from pane to pane. if context.serial_number() > 1: self._widget.setWindowTitle(self._widget.windowTitle() + (' (%d)' % context.serial_number())) # Add widget to the user interface context.add_widget(self._widget) def shutdown_plugin(self): # TODO unregister all publishers here pass 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
def __init__(self, context): super(PyConsole, self).__init__(context) self.setObjectName('PyConsole') self._context = context self._use_spyderlib = _has_spyderlib self._console_widget = None self._widget = QWidget() self._widget.setLayout(QVBoxLayout()) self._widget.layout().setContentsMargins(0, 0, 0, 0) if context.serial_number() > 1: self._widget.setWindowTitle(self._widget.windowTitle() + (' (%d)' % context.serial_number())) self._context.add_widget(self._widget)
class NodeSelection(QWidget): def __init__(self, parent): super(NodeSelection, self).__init__() self.parent_widget = parent self.selected_nodes = [] self.setWindowTitle("Select the nodes you want to record") self.resize(500, 700) self.area = QScrollArea(self) self.main_widget = QWidget(self.area) self.ok_button = QPushButton("Done", self) self.ok_button.clicked.connect(self.onButtonClicked) self.ok_button.setEnabled(False) self.main_vlayout = QVBoxLayout(self) self.main_vlayout.addWidget(self.area) self.main_vlayout.addWidget(self.ok_button) self.setLayout(self.main_vlayout) self.selection_vlayout = QVBoxLayout(self) self.node_list = rosnode.get_node_names() self.node_list.sort() for node in self.node_list: self.addCheckBox(node) self.main_widget.setLayout(self.selection_vlayout) self.show() def addCheckBox(self, node): item = QCheckBox(node, self) item.stateChanged.connect(lambda x: self.updateNode(x, node)) self.selection_vlayout.addWidget(item) def updateNode(self, state, node): if state == Qt.Checked: self.selected_nodes.append(node) else: self.selected_nodes.remove(node) if len(self.selected_nodes) > 0: self.ok_button.setEnabled(True) else: self.ok_button.setEnabled(False) def onButtonClicked(self): master = rosgraph.Master('rqt_bag_recorder') state = master.getSystemState() subs = [t for t, l in state[1] if len([node_name for node_name in self.selected_nodes if node_name in l]) > 0] for topic in subs: self.parent_widget.changeTopicCheckState(topic, Qt.Checked) self.parent_widget.updateList(Qt.Checked, topic) self.close()
class Visualizer(Plugin): def __init__(self, context): super(Visualizer, self).__init__(context) # Give QObjects reasonable names self.setObjectName('Visualizer') # Process standalone plugin command-line arguments # from argparse import ArgumentParser # parser = ArgumentParser() # Add argument(s) to the parser. # parser.add_argument("-q", "--quiet", action="store_true", # dest="quiet", # help="Put plugin in silent mode") # args, unknowns = parser.parse_known_args(context.argv()) # if not args.quiet: # print 'arguments: ', args # print 'unknowns: ', unknowns # Create QWidget self._widget = QWidget() # Get path to UI file which should be in the "resource" folder of this package ui_file = os.path.join(rospkg.RosPack().get_path('consai2_gui'), 'resource', 'Visualizer.ui') # Extend the widget with all attributes and children from UI file loadUi(ui_file, self._widget, {"PaintWidget": PaintWidget}) # Give QObjects reasonable names self._widget.setObjectName('VisualizerUi') # Show _widget.windowTitle on left-top of each plugin (when # it's set in _widget). This is useful when you open multiple # plugins at once. Also if you open multiple instances of your # plugin at once, these lines add number to make it easy to # tell from pane to pane. if context.serial_number() > 1: self._widget.setWindowTitle(self._widget.windowTitle() + (' (%d)' % context.serial_number())) # Add widget to the user interface context.add_widget(self._widget) self._redraw_timer = QTimer() self._redraw_timer.setInterval(16) self._redraw_timer.timeout.connect(self._widget.update) self._redraw_timer.start() def shutdown_plugin(self): pass def save_settings(self, plugin_settings, instance_settings): pass def restore_settings(self, plugin_settings, instance_settings): pass
def __init__(self, context): super(CameraViewer, self).__init__(context) # Give QObjects reasonable names self.setObjectName('CameraViewer') # Process standalone plugin command-line arguments from argparse import ArgumentParser parser = ArgumentParser() # Add argument(s) to the parser. parser.add_argument("-q", "--quiet", action="store_true", dest="quiet", help="Put plugin in silent mode") # args, unknowns = parser.parse_known_args(context.argv()) # if not args.quiet: # print 'arguments: ', args # print 'unknowns: ', unknowns # Create QWidget self._widget = QWidget() # Get path to UI file which should be in the "resource" folder of this package ui_file = os.path.join(rospkg.RosPack().get_path('rqt_drone_teleop'), 'resource', 'CamViewer.ui') # Extend the widget with all attributes and children from UI file loadUi(ui_file, self._widget) # Give QObjects reasonable names self._widget.setObjectName('CamViewerUi') # Show _widget.windowTitle on left-top of each plugin (when # it's set in _widget). This is useful when you open multiple # plugins at once. Also if you open multiple instances of your # plugin at once, these lines add number to make it easy to # tell from pane to pane. if context.serial_number() > 1: self._widget.setWindowTitle(self._widget.windowTitle() + (' (%d)' % context.serial_number())) # Add widget to the user interface context.add_widget(self._widget) self.bridge = CvBridge() # Add Subscibers cam_frontal_topic = rospy.get_param('cam_frontal_topic', '/iris/cam_frontal/image_raw') cam_ventral_topic = rospy.get_param('cam_ventral_topic', '/iris/cam_ventral/image_raw') rospy.Subscriber(cam_frontal_topic, Image, self.cam_frontal_cb) rospy.Subscriber(cam_ventral_topic, Image, self.cam_ventral_cb) rospy.Subscriber('interface/filtered_img', Image, self.filtered_img_cb) rospy.Subscriber('interface/threshed_img', Image, self.threshed_img_cb)
def __init__(self, parent, updater, config, nodename): super(TabGroup, self).__init__(updater, config, nodename) self.parent = parent if not self.parent.tab_bar: self.parent.tab_bar = QTabWidget() # Don't process wheel events when not focused self.parent.tab_bar.tabBar().installEventFilter(self) self.wid = QWidget() self.wid.setLayout(self.grid) parent.tab_bar.addTab(self.wid, self.param_name)
def __init__(self, context): super(MotorlabGUI, self).__init__(context) self.setObjectName('MotorlabGUI') # self._publisher = None self._publisher = rospy.Publisher("PCMsg", MotorLab_PC, queue_size = 2) self._widget = QWidget() rp = rospkg.RosPack() ui_file = os.path.join(rp.get_path('rqt_motorlab_gui'), 'resource', 'MotorlabGUI.ui') loadUi(ui_file, self._widget) self._widget.setObjectName('MotorlabGUIUi') if context.serial_number() > 1: self._widget.setWindowTitle(self._widget.windowTitle() + (' (%d)' % context.serial_number())) context.add_widget(self._widget) self.PC_to_Arduino = MotorLab_PC() self.PC_to_Arduino.stepper_angle = 0 self.PC_to_Arduino.motor_position_checked = 0 self.PC_to_Arduino.motor_speed_checked = 0 self.PC_to_Arduino.servo_checked = 0 self.PC_to_Arduino.thermistor_checked = 0 self.PC_to_Arduino.light_gate_checked = 0 self.PC_to_Arduino.ir_checked = 0 self.PC_to_Arduino.ultra_checked = 0 self.PC_to_Arduino.motor_velocity = 0 self.PC_to_Arduino.motor_angle = 0 self.text_field_angle = 0 self.text_field_motor_velocity= 0 self.text_field_motor_angle = 0 self._widget.set_stepper.textChanged.connect(self._on_set_stepper_changed) self._widget.send_stepper.pressed.connect(self._on_send_stepper_pressed) self._widget.set_motor_velocity.textChanged.connect(self._on_set_motor_velocity) self._widget.send_motor_velocity.pressed.connect(self._on_send_motor_velocity) self._widget.set_motor_angle.textChanged.connect(self._on_set_motor_angle) self._widget.send_motor_angle.pressed.connect(self._on_send_motor_angle) self._widget.motor_position_checkbox.clicked.connect(self._on_motor_position_checkbox_clicked) self._widget.motor_speed_checkbox.clicked.connect(self._on_motor_speed_checkbox_clicked) self._widget.servo_checkbox.clicked.connect(self._on_servo_checkbox_clicked) self._widget.thermistor_checkbox.clicked.connect(self._on_thermistor_checkbox_clicked) self._widget.light_gate_checkbox.clicked.connect(self._on_light_gate_checkbox_clicked) self._widget.ir_checkbox.clicked.connect(self._on_ir_checkbox_clicked) self._widget.ultra_checkbox.clicked.connect(self._on_ultra_checkbox_clicked)
class MissionModePlugin(Plugin): def __init__(self, context): super(MissionModePlugin, self).__init__(context) # Give QObjects reasonable names self.setObjectName('MissionModePlugin') # Create QWidget self._widget = QWidget() rp = rospkg.RosPack() # Get path to UI file which should be in the "resource" folder of this package ui_file = os.path.join(rp.get_path('behavior_selector'), 'resource', 'MissionModePlugin.ui') # Extend the widget with all attributes and children from UI file loadUi(ui_file, self._widget) # Give QObjects reasonable names self._widget.setObjectName('MissionModePluginUi') # Show _widget.windowTitle on left-top of each plugin (when # it's set in _widget). This is useful when you open multiple # plugins at once. Also if you open multiple instances of your # plugin at once, these lines add number to make it easy to # tell from pane to pane. if context.serial_number() > 1: self._widget.setWindowTitle(self._widget.windowTitle() + (' (%d)' % context.serial_number())) # Add widget to the user interface context.add_widget(self._widget) self._widget.start_push_button.pressed.connect(self._on_start_pressed) self._widget.end_push_button.pressed.connect(self._on_end_pressed) self._widget.stop_push_button.pressed.connect(self._on_stop_pressed) def _on_start_pressed(self): mode = START self._change_mode(mode) def _on_end_pressed(self): mode = END self._change_mode(mode) def _on_stop_pressed(self): mode = KILL self._change_mode(mode) def _change_mode(self, mode): rospy.wait_for_service('change_mode', 1) try: mm = rospy.ServiceProxy('change_mode', MissionModeChange) mm(mode) except rospy.ServiceException as e: print("Service call failed: %s" % e)
def process(self, action): """ :param action: action to execute, ''QAction'' :raises: when it doesn't recognice the action passed in, ''Exception'' """ if action == self._reset_timeline: self.timeline._timeline_frame.reset_timeline() elif action == self._play_all: self.timeline.toggle_play_all() elif action == self._publish_all: for topic in self.timeline._timeline_frame.topics: if not self.timeline.start_publishing(topic): break elif action == self._publish_none: for topic in self.timeline._timeline_frame.topics: if not self.timeline.stop_publishing(topic): break elif action == self._thumbnail_show_action: self.timeline._timeline_frame.set_renderers_active(True) elif action == self._thumbnail_hide_action: self.timeline._timeline_frame.set_renderers_active(False) elif action in self._thumbnail_actions: if self.timeline._timeline_frame.is_renderer_active(action.text()): self.timeline._timeline_frame.set_renderer_active( action.text(), False) else: self.timeline._timeline_frame.set_renderer_active( action.text(), True) elif action in self._topic_actions + self._type_actions: popup_name = action.parentWidget().title() + '__' + action.text() if popup_name not in self.timeline.popups: frame = QWidget() layout = QVBoxLayout() frame.setLayout(layout) frame.resize(640, 480) viewer_type = action.data() frame.setObjectName(popup_name) view = viewer_type(self.timeline, frame) self.timeline.popups.add(popup_name) self.timeline.get_context().add_widget(frame) self.timeline.add_view(action.parentWidget().title(), view, frame) frame.show() elif action in self._publish_actions: if self.timeline.is_publishing(action.text()): self.timeline.stop_publishing(action.text()) else: self.timeline.start_publishing(action.text()) else: raise Exception('Unknown action in TimelinePopupMenu.process')
def __init__(self, context): super(MyPlugin, self).__init__(context) # Give QObjects reasonable names self.setObjectName('MyPlugin') # Process standalone plugin command-line arguments from argparse import ArgumentParser parser = ArgumentParser() # Add argument(s) to the parser. parser.add_argument("-q", "--quiet", action="store_true", dest="quiet", help="Put plugin in silent mode") args, unknowns = parser.parse_known_args(context.argv()) if not args.quiet: print 'arguments: ', args print 'unknowns: ', unknowns # Create QWidget self._widget = QWidget() # Get path to UI file which should be in the "resource" folder of this package ui_file = os.path.join(rospkg.RosPack().get_path('pressure_controller_setup'), 'resource', 'MyPlugin.ui') # Extend the widget with all attributes and children from UI file loadUi(ui_file, self._widget) # Give QObjects reasonable names self._widget.setObjectName('Set Pressures') self.settings=self.get_settings() self.init_sliders() self._client = actionlib.SimpleActionClient('pressure_control', pressure_controller_ros.msg.CommandAction) self._client_connected=self._client.wait_for_server(timeout=rospy.rostime.Duration(1)) if not self._client_connected: print("No command server avaiable... changes will not be sent") self.set_graph_state(True) self.send_channel_state(0,self.settings['channel_states'][0]) # Show _widget.windowTitle on left-top of each plugin (when # it's set in _widget). This is useful when you open multiple # plugins at once. Also if you open multiple instances of your # plugin at once, these lines add number to make it easy to # tell from pane to pane. if context.serial_number() > 1: self._widget.setWindowTitle(self._widget.windowTitle() + (' (%d)' % context.serial_number())) # Add widget to the user interface context.add_widget(self._widget)
def _init_plugin(self, context): self.setObjectName("DSD-Visualization") self._widget = QWidget() self._widget.setObjectName(self.objectName()) # load qt ui definition from file rp = rospkg.RosPack() ui_file = os.path.join( rp.get_path("dynamic_stack_decider_visualization"), "resource", "StackmachineViz.ui") loadUi(ui_file, self._widget, {"InteractiveGraphicsView": InteractiveGraphicsView}) # initialize qt scene self._scene = QGraphicsScene() self._scene.setBackgroundBrush(Qt.white) self._widget.graphics_view.setScene(self._scene) # Bind fit-in-view button self._widget.fit_in_view_push_button.setIcon( QIcon.fromTheme('zoom-original')) self._widget.fit_in_view_push_button.pressed.connect(self.fit_in_view) # Fit-in-view on checkbox toggle self._widget.auto_fit_graph_check_box.toggled.connect(self.fit_in_view) # Freezing def toggle_freeze(): self.freeze = not self.freeze self.refresh() self._widget.freeze_push_button.toggled.connect(toggle_freeze) # Exporting and importing self._widget.save_as_svg_push_button.pressed.connect( self.save_svg_to_file) # Fill choices for dsd_selector and bind on_select self._widget.dsd_selector_combo_box.addItem("Select DSD...") for choice in self.locations: self._widget.dsd_selector_combo_box.addItem(choice['display_name']) self._widget.dsd_selector_combo_box.currentTextChanged.connect( self.set_dsd) context.add_widget(self._widget) # Start a timer that calls back every 100 ms self._timer_id = self.startTimer(100)
def __init__(self, context): super(SpeechStatusPlugin, self).__init__(context) self.setObjectName('SpeechStatusPlugin') self._widget = QWidget() if context.serial_number() > 1: self._widget.setWindowTitle(self._widget.windowTitle() + (' (%d)' % context.serial_number())) ui_file = os.path.join(rospkg.RosPack().get_path('rqt_speech_status'), 'resource', 'speech_widget.ui') loadUi(ui_file, self._widget) context.add_widget(self._widget) file_live = os.path.join( rospkg.RosPack().get_path('rqt_speech_status'), 'resource', 'microphone.png') file_mute = os.path.join( rospkg.RosPack().get_path('rqt_speech_status'), 'resource', 'muted.png') file_silency = os.path.join( rospkg.RosPack().get_path('rqt_speech_status'), 'resource', 'silence-face.png') file_speech = os.path.join( rospkg.RosPack().get_path('rqt_speech_status'), 'resource', 'surprise-face.png') self.img_mute = QPixmap(file_mute).scaled(160, 160) self.img_live = QPixmap(file_live).scaled(160, 160) self.img_silency = QPixmap(file_silency).scaled(160, 160) self.img_speech = QPixmap(file_speech).scaled(160, 160) self._widget.imgRecognition.setPixmap(self.img_live) self._widget.imgSilency.setPixmap(self.img_silency) self.signal_render_recog_status = SignalRender() self.signal_render_recog_status.renderSignal.connect( self.render_recog_status) self.signal_render_silency_status = SignalRender() self.signal_render_silency_status.renderSignal.connect( self.render_silency_status) rospy.Subscriber('enable_recognition', Bool, self.handle_enable_recognition) rospy.Subscriber('start_of_speech', Empty, self.handle_start_speech) rospy.Subscriber('end_of_speech', Empty, self.handle_end_speech) rospy.Subscriber('silency_detected', Empty, self.handle_silency_detection)
class JoyVis(Plugin): def __init__(self, context): super(JoyVis, self).__init__(context) self.setObjectName('Joy') from argparse import ArgumentParser parser = ArgumentParser() parser.add_argument("-q", "--quiet", action="store_true", dest="quiet", help="Put plugin in silent mode") args, unknowns = parser.parse_known_args(context.argv()) self._widget = QWidget() ui_file = os.path.join(rospkg.RosPack().get_path('rqt_joy'), 'resource', 'Joy.ui') loadUi(ui_file, self._widget) self._widget.setObjectName('JoyUi') if context.serial_number() > 1: self._widget.setWindowTitle(self._widget.windowTitle() + (' (%d)' % context.serial_number())) context.add_widget(self._widget) self._widget.joy_1_x.setValue(0) self._widget.joy_1_y.setValue(0) rospy.Subscriber("joy", Joy, self.joyMessageCallback) def shutdown_plugin(self): pass def save_settings(self, plugin_settings, instance_settings): pass def restore_settings(self, plugin_settings, instance_settings): pass def joyMessageCallback(self, joy): self._widget.joy_1_x.setValue(joy.axes[0] * 100) self._widget.joy_1_y.setValue(joy.axes[1] * 100)
def __init__(self, context): super(DriverStationMain, self).__init__(context) # Give QObjects reasonable names self.setObjectName('MainWindow') # Process standalone plugin command-line arguments from argparse import ArgumentParser parser = ArgumentParser() # Add argument(s) to the parser. parser.add_argument("-q", "--quiet", action="store_true", dest="quiet", help="Put plugin in silent mode") args, unknowns = parser.parse_known_args(context.argv()) if not args.quiet: print 'arguments: ', args print 'unknowns: ', unknowns # Create QWidget self._widget = QWidget() # Get path to UI file which should be in the "resource" folder of this package ui_file = os.path.join(rospkg.RosPack().get_path('rqt_ds'), 'resource', 'driver-station.ui') # Extend the widget with all attributes and children from UI file loadUi(ui_file, self._widget) # Give QObjects reasonable names self._widget.setObjectName('DriverStationWidget') # Show _widget.windowTitle on left-top of each plugin (when # it's set in _widget). This is useful when you open multiple # plugins at once. Also if you open multiple instances of your # plugin at once, these lines add number to make it easy to # tell from pane to pane. if context.serial_number() > 1: self._widget.setWindowTitle(self._widget.windowTitle() + (' (%d)' % context.serial_number())) # Add widget to the user interface context.add_widget(self._widget) '''def clock_thread(): while(True): # TODO: Change the way this works - current you have to ctrl + z stop the thread # This will probably make more sense when I figure out message listeners delta=str(datetime.datetime.now()-self.startTime) self._widget.elapsedTimeText.setText(delta[-12:]) time.sleep(0.1)''' #self._widget.testButton.clicked.connect(self.test) '''testValue = True # TODO Theoretically, this is a boolean telling us whether we have comms
def __init__(self, context): super(Commander, self).__init__(context) # Give QObjects reasonable names self.setObjectName('MantisCommander') rp = rospkg.RosPack() # Process standalone plugin command-line arguments #from argparse import ArgumentParser #parser = ArgumentParser() # Add argument(s) to the parser. #parser.add_argument("-q", "--quiet", action="store_true", # dest="quiet", # help="Put plugin in silent mode") #args, unknowns = parser.parse_known_args(context.argv()) #if not args.quiet: # print 'arguments: ', args # print 'unknowns: ', unknowns # Create QWidget self._widget = QWidget() # Get path to UI file which is a sibling of this file # in this example the .ui and .py file are in the same folder ui_file = os.path.join(rp.get_path('rqt_contrail_commander'), 'resource', 'ContrailCommander.ui') # Extend the widget with all attributes and children from UI file loadUi(ui_file, self._widget) # Give QObjects reasonable names self._widget.setObjectName('ContrailCommanderUi') # Show _widget.windowTitle on left-top of each plugin (when # it's set in _widget). This is useful when you open multiple # plugins at once. Also if you open multiple instances of your # plugin at once, these lines add number to make it easy to # tell from pane to pane.ns if context.serial_number() > 1: self._widget.setWindowTitle(self._widget.windowTitle() + (' (%d)' % context.serial_number())) # Add widget to the user interface context.add_widget(self._widget) self._widget.textbox_pose.textChanged.connect(self.pose_changed) self._widget.textbox_contrail.textChanged.connect(self.contrail_changed) self._widget.button_send_command.clicked.connect(self.button_send_command_pressed) self.has_pose = False self.isready = False self.current_pose = None self.sub_pose = None self.sub_isready = None self.client_base = None
def __init__(self, context): super(RosBagToDataset, self).__init__(context) self.initialized = False self._current_topic_list = [] self._topics = {} self._tree_items = {} self._column_index = {} for column_name in self._column_names: self._column_index[column_name] = len(self._column_index) self.setObjectName('RosBagToDataset') self._widget = QWidget() rp = rospkg.RosPack() ui_file = os.path.join(rp.get_path('rqt_bag_to_dataset'), 'resource', 'RosBagToDataset.ui') loadUi(ui_file, self._widget) self._widget.setObjectName('RosBagToDatasetUi') if context.serial_number() > 1: self._widget.setWindowTitle(self._widget.windowTitle() + (' (%d)' % context.serial_number())) self._widget.topics_tree_widget.sortByColumn(0, Qt.AscendingOrder) self._widget.load_bag_push_button.setIcon( QIcon.fromTheme('document-open')) self._widget.load_bag_push_button.pressed.connect(self._load_bag) # self._widget.debug_button.setIcon(QIcon.fromTheme('applications-development')) # self._widget.debug_button.pressed.connect(self._debug_function) # self._widget.input_conf_push_button.setIcon(QIcon.fromTheme('document-new')) # self._widget.input_conf_push_button.pressed.connect(self._configue_inputs) # self._widget.output_conf_push_button.setIcon(QIcon.fromTheme('applications-other')) # self._widget.output_conf_push_button.pressed.connect(self._configue_outputs) # self._widget.check_conf_push_button.setIcon(QIcon.fromTheme('applications-science')) # self._widget.check_conf_push_button.pressed.connect(self._check_config) self._widget.save_dls_push_button.setIcon( QIcon.fromTheme('document-save-as')) self._widget.save_dls_push_button.pressed.connect(self._save_dataset) context.add_widget(self._widget) self._force_refresh = False
def __init__(self, reconf, node_name): """ :type reconf: dynamic_reconfigure.client :type node_name: str """ group_desc = reconf.get_group_descriptions() logging.debug('ParamClientWidget.group_desc=%s', group_desc) super(ParamClientWidget, self).__init__(ParamUpdater(reconf), group_desc, node_name) # Save and load buttons self.button_widget = QWidget(self) self.button_header = QHBoxLayout(self.button_widget) self.button_header.setContentsMargins(QMargins(0, 0, 0, 0)) self.load_button = QPushButton() self.save_button = QPushButton() self.load_button.setIcon(QIcon.fromTheme('document-open')) self.save_button.setIcon(QIcon.fromTheme('document-save')) self.load_button.clicked[bool].connect(self._handle_load_clicked) self.save_button.clicked[bool].connect(self._handle_save_clicked) self.button_header.addWidget(self.save_button) self.button_header.addWidget(self.load_button) self.setMinimumWidth(150) self.reconf = reconf self.updater.start() self.reconf.config_callback = self.config_callback self._node_grn = node_name
def _unload_jtc(self): # Stop updating the joint positions try: self.jointStateChanged.disconnect(self._on_joint_state_change) except: pass # Reset ROS interfaces self._unregister_state_sub() self._unregister_cmd_pub() # Clear joint widgets # NOTE: Implementation is a workaround for: # https://bugreports.qt-project.org/browse/QTBUG-15990 :( layout = self._widget.joint_group.layout() if layout is not None: while layout.count(): layout.takeAt(0).widget().deleteLater() # Delete existing layout by reparenting to temporary QWidget().setLayout(layout) self._widget.joint_group.setLayout(QFormLayout()) # Reset joint data self._joint_names = [] self._joint_pos = {} # Enforce monitor mode (sending commands disabled) self._widget.enable_button.setChecked(False)
def __init__(self): super(TopicSelection, self).__init__() master = rosgraph.Master('rqt_bag_recorder') self.setWindowTitle("Select the topics you want to record") self.resize(500, 700) self.topic_list = [] self.selected_topics = [] self.items_list = [] self.area = QScrollArea(self) self.main_widget = QWidget(self.area) self.ok_button = QPushButton("Record", self) self.ok_button.clicked.connect(self.onButtonClicked) self.ok_button.setEnabled(False) self.main_vlayout = QVBoxLayout(self) self.main_vlayout.addWidget(self.area) self.main_vlayout.addWidget(self.ok_button) self.setLayout(self.main_vlayout) self.selection_vlayout = QVBoxLayout(self) self.item_all = QCheckBox("All", self) self.item_all.stateChanged.connect(self.updateList) self.selection_vlayout.addWidget(self.item_all) topic_data_list = master.getPublishedTopics('') topic_data_list.sort() for topic, datatype in topic_data_list: self.addCheckBox(topic) self.main_widget.setLayout(self.selection_vlayout) self.area.setWidget(self.main_widget) self.show()
def __init__(self): super(GantryCraneWidget, self).__init__() self.setObjectName('GantryCraneWidget') # Create QWidget self._widget = QWidget() # Get path to UI file which should be in the "resource" folder of this package ui_file = os.path.join(rospkg.RosPack().get_path('rqt_gantry_crane'), 'resource', 'GantryCrane.ui') # Extend the widget with all attributes and children from UI file loadUi(ui_file, self) self.set_target_mark = rospy.ServiceProxy('gazebo/set_model_state', SetModelState) ## Signals & Slots self.ctrlButton_acker.clicked.connect(self.on_ctrlButton_acker_clicked) # self.ctrlButton_lqr.clicked.connect(self.on_ctrlButton_lqr_clicked) self.pos_cmd_slider.valueChanged.connect( self.on_pos_cmd_slider_changed) # self.pos_cmd_slider.sliderReleased.connect(self.on_pos_cmd_slider_released) self.posButton_L.clicked.connect(self.on_posButton_L_clicked) self.posButton_0.clicked.connect(self.on_posButton_0_clicked) self.posButton_R.clicked.connect(self.on_posButton_R_clicked) self.pos_cmd_pub = rospy.Publisher('/gantry_crane/pos_cmd', Point, queue_size=1)
def __init__(self, context): super(RosTfTree, self).__init__(context) self.initialized = False self.setObjectName('RosTfTree') self._current_dotcode = None self._widget = QWidget() # factory builds generic dotcode items self.dotcode_factory = PydotFactory() # self.dotcode_factory = PygraphvizFactory() # generator builds rosgraph self.dotcode_generator = RosTfTreeDotcodeGenerator() self.tf2_buffer_ = tf2_ros.Buffer() self.tf2_listener_ = tf2_ros.TransformListener(self.tf2_buffer_) # dot_to_qt transforms into Qt elements using dot layout self.dot_to_qt = DotToQtGenerator() rp = rospkg.RosPack() ui_file = os.path.join(rp.get_path('rqt_tf_tree'), 'resource', 'RosTfTree.ui') loadUi(ui_file, self._widget, {'InteractiveGraphicsView': InteractiveGraphicsView}) self._widget.setObjectName('RosTfTreeUi') if context.serial_number() > 1: self._widget.setWindowTitle(self._widget.windowTitle() + (' (%d)' % context.serial_number())) self._scene = QGraphicsScene() self._scene.setBackgroundBrush(Qt.white) self._widget.graphics_view.setScene(self._scene) self._widget.refresh_graph_push_button.setIcon(QIcon.fromTheme('view-refresh')) self._widget.refresh_graph_push_button.pressed.connect(self._update_tf_graph) self._widget.highlight_connections_check_box.toggled.connect(self._redraw_graph_view) self._widget.auto_fit_graph_check_box.toggled.connect(self._redraw_graph_view) self._widget.fit_in_view_push_button.setIcon(QIcon.fromTheme('zoom-original')) self._widget.fit_in_view_push_button.pressed.connect(self._fit_in_view) self._widget.load_dot_push_button.setIcon(QIcon.fromTheme('document-open')) self._widget.load_dot_push_button.pressed.connect(self._load_dot) self._widget.save_dot_push_button.setIcon(QIcon.fromTheme('document-save-as')) self._widget.save_dot_push_button.pressed.connect(self._save_dot) self._widget.save_as_svg_push_button.setIcon(QIcon.fromTheme('document-save-as')) self._widget.save_as_svg_push_button.pressed.connect(self._save_svg) self._widget.save_as_image_push_button.setIcon(QIcon.fromTheme('image-x-generic')) self._widget.save_as_image_push_button.pressed.connect(self._save_image) self._deferred_fit_in_view.connect(self._fit_in_view, Qt.QueuedConnection) self._deferred_fit_in_view.emit() context.add_widget(self._widget) self._force_refresh = False
def __init__(self, context): super(RqtLgsvlSimulatorConfiguratorPlugin, self).__init__(context) rospack = rospkg.RosPack() self.settings = QSettings(rospack.get_path('lgsvl_simulator_bridge')+"/config/setting.dat",QSettings.IniFormat) # Give QObjects reasonable names self.setObjectName('RqtLgsvlSimulatorConfiguratorPlugin') # Process standalone plugin command-line arguments from argparse import ArgumentParser parser = ArgumentParser() # Add argument(s) to the parser parser.add_argument("-q", "--quiet", action="store_true", dest="quiet", help="Put plugin in silent mode") args, unknowns = parser.parse_known_args(context.argv()) if not args.quiet: print 'arguments: ', args print 'unknowns: ', unknowns # Create QWidget self._widget = QWidget() # Get path to UI file which should be in the "resource" folder of this package ui_file = os.path.join(rospkg.RosPack().get_path('lgsvl_simulator_bridge'), 'resource', 'LgsvlSimulatorConfigratorPlugin.ui') # Extend the widget with all atrributes and children from UI File loadUi(ui_file, self._widget) # Give QObjects reasonable names self._widget.setObjectName('RqtLgsvlSimulatorConfiguratorPluginUi') # Show _widget.windowTitle on left-top of each plugin(when it's set in _widget). # This is useful when you open multiple plugins aat once. Also if you open multiple # instances of your plugin at once, these lines add number to make it easy to # tell from pane to pane. if context.serial_number() > 1: self._widget.setWindowTitle(self._widget.windowTitle() + (' %d' % context.serial_number())) # Add widget to the user interface self.settings.beginGroup("simulator_params") context.add_widget(self._widget) ip = self.settings.value('ip') if ip != None: self._widget.ip_box.setText(ip) port = self.settings.value('port') if port != None: self._widget.port_box.setText(port) config_path = self.settings.value('config_path') if config_path != None: self._widget.configpath_box.setText(config_path) self.settings.endGroup() self.json_dict = {} self.instance_id = "" self.is_remote = False self._widget.button_config_ref.clicked[bool].connect(self._handle_config_ref_button_clicked) self._widget.button_config.clicked[bool].connect(self._handle_config_button_clicked) self._widget.launch_button.clicked[bool].connect(self._handle_launch_button_clicked) self._widget.terminate_button.clicked[bool].connect(self._handle_terminate_button_clicked)
def __init__(self, context): super(Overview, self).__init__(context) self.__tfListener = tf.TransformListener() self.__copterFrame = "base_link" self.__worldFrame = "world" # Give QObjects reasonable names self.setObjectName('simple_position_control_gui') # Process standalone plugin command-line arguments from argparse import ArgumentParser parser = ArgumentParser() # Add argument(s) to the parser. parser.add_argument("-c", "--copterFrame", dest="copterFrame", help="Specify the copter frame") parser.add_argument("-w", "--worldFrame", dest="worldFrame", help="Specify the world frame") args, unknowns = parser.parse_known_args(context.argv()) if args.copterFrame: self.__copterFrame = args.copterFrame rospy.loginfo("using %s as copter frame", self.__copterFrame) if args.worldFrame: self.__worldFrame = args.worldFrame rospy.loginfo("using %s as world frame", self.__worldFrame) # Create QWidget self._widget = QWidget() # Get path to UI file which should be in the "resource" folder of this node ui_file = os.path.join(rospkg.RosPack().get_path('position_controller'), 'src', 'rqt_control_gui', 'resource', 'overview.ui') # Extend the widget with all attributes and children from UI file loadUi(ui_file, self._widget) # Give QObjects reasonable names self._widget.setObjectName('OverviewUI') # Show _widget.windowTitle on left-top of each plugin (when # it's set in _widget). This is useful when you open multiple # plugins at once. Also if you open multiple instances of your # plugin at once, these lines add number to make it easy to # tell from pane to pane. if context.serial_number() > 1: self._widget.setWindowTitle(self._widget.windowTitle() + (' (%d)' % context.serial_number())) # Add widget to the user interface context.add_widget(self._widget) self._widget.forwardButton.clicked.connect(self.goForward) self._widget.backwardButton.clicked.connect(self.goBackward) self._widget.leftButton.clicked.connect(self.goLeft) self._widget.rightButton.clicked.connect(self.goRight) self._widget.rotateButton.clicked.connect(self.rotate) self._widget.landButton.clicked.connect(self.land) self._widget.startButton.clicked.connect(self.start) self._widget.absoluteControlButton.clicked.connect(self.absoluteControl) self._widget.tfButton.clicked.connect(self.goToTF) self.__statusLabel = self._widget.statusLabel
class TabGroup(GroupWidget): def __init__(self, parent, updater, config, nodename): super(TabGroup, self).__init__(updater, config, nodename) self.parent = parent if not self.parent.tab_bar: self.parent.tab_bar = QTabWidget() self.wid = QWidget() self.wid.setLayout(self.grid) parent.tab_bar.addTab(self.wid, self.param_name) def display(self, grid): if not self.parent.tab_bar_shown: grid.addRow(self.parent.tab_bar) self.parent.tab_bar_shown = True def close(self): super(TabGroup, self).close() self.parent.tab_bar = None self.parent.tab_bar_shown = False
def __init__(self, context): super(MyPlugin, self).__init__(context) # Give QObjects reasonable names self.setObjectName('MyPlugin') rospy.loginfo("Remora: ECU Console") # Process standalone plugin command-line arguments from argparse import ArgumentParser parser = ArgumentParser() # Add argument(s) to the parser. parser.add_argument("-q", "--quiet", action="store_true", dest="quiet", help="Put plugin in silent mode") args, unknowns = parser.parse_known_args(context.argv()) if not args.quiet: print 'arguments: ', args print 'unknowns: ', unknowns # Create QWidget self._widget = QWidget() # Get path to UI file which is a sibling of this file # in this example the .ui and .py file are in the same folder ui_file = os.path.join(os.path.dirname(os.path.realpath(__file__)), 'ecu_console.ui') # Extend the widget with all attributes and children from UI file loadUi(ui_file, self._widget) # Give QObjects reasonable names self._widget.setObjectName('MyPluginUi') # Show _widget.windowTitle on left-top of each plugin (when # it's set in _widget). This is useful when you open multiple # plugins at once. Also if you open multiple instances of your # plugin at once, these lines add number to make it easy to # tell from pane to pane. self._widget.setWindowTitle('ECU') if context.serial_number() > 1: self._widget.setWindowTitle(self._widget.windowTitle()+(' (%d)'% context.serial_number())) # Add widget to the user interface context.add_widget(self._widget) self.firstStatusMsg = False # Register all subsribers here self.intTempSub_ = rospy.Subscriber('/sunfish/ecu/int_temp', Temperature, self.callback_IntTemp) self.extTempSub_ = rospy.Subscriber('/sunfish/ecu/ext_temp', Temperature, self.callback_ExtTemp) self.depthSub_ = rospy.Subscriber('/sunfish/ecu/depth', Depth, self.callback_Depth) self.insSub_ = rospy.Subscriber('/sunfish/ecu/INS', INS, self.callback_INS) self.magFieldSub_ = rospy.Subscriber('/sunfish/ecu/MST', MagField, self.callback_MagField) self.statusSub_ = rospy.Subscriber('/sunfish/ecu/status', Status, self.callback_Status) return
def __init__(self, context): super(MyPlugin, self).__init__(context) # Give QObjects reasonable names self.setObjectName('MyPlugin') rospy.loginfo("Remora: Basic Controller Online") # Process standalone plugin command-line arguments from argparse import ArgumentParser parser = ArgumentParser() # Add argument(s) to the parser. parser.add_argument("-q", "--quiet", action="store_true", dest="quiet", help="Put plugin in silent mode") args, unknowns = parser.parse_known_args(context.argv()) if not args.quiet: print 'arguments: ', args print 'unknowns: ', unknowns # Create QWidget self._widget = QWidget() # Get path to UI file which is a sibling of this file # in this example the .ui and .py file are in the same folder ui_file = os.path.join(os.path.dirname(os.path.realpath(__file__)), 'remora_gui.ui') # Extend the widget with all attributes and children from UI file loadUi(ui_file, self._widget) # Give QObjects reasonable names self._widget.setObjectName('MyPluginUi') # Show _widget.windowTitle on left-top of each plugin (when # it's set in _widget). This is useful when you open multiple # plugins at once. Also if you open multiple instances of your # plugin at once, these lines add number to make it easy to # tell from pane to pane. self._widget.setWindowTitle('Basic Console') if context.serial_number() > 1: self._widget.setWindowTitle(self._widget.windowTitle()+(' (%d)'% context.serial_number())) # Add widget to the user interface context.add_widget(self._widget) # Register all subsribers here return
def __init__(self, context): super(LevelSelectorPlugin, self).__init__(context) # Give QObjects reasonable names self.setObjectName('LevelSelectorPlugin') # Create QWidget self._widget = QWidget() self._widget.setFont(QFont("Times", 15, QFont.Bold)) self._button_layout = QVBoxLayout(self._widget) self.buttons = [] self.text_label = QLabel("Waiting for MultiLevelMapData...", self._widget) self._button_layout.addWidget(self.text_label) self._widget.setObjectName('LevelSelectorPluginUI') if context.serial_number() > 1: self._widget.setWindowTitle(self._widget.windowTitle() + (' (%d)' % context.serial_number())) context.add_widget(self._widget) self.button_signal.connect(self.update_buttons) self.button_status_signal.connect(self.update_button_status) # Subscribe to the multi level map data to get information about all the maps. self.multimap_subscriber = rospy.Subscriber("map_metadata", MultiLevelMapData, self.process_multimap) self.levels = [] self.current_level = None rospy.loginfo('level selector: subscribed to maps') # Subscribe to the current level we are on. self.status_subscriber = None # Create a service proxy to change the current level. self.level_selector_proxy = rospy.ServiceProxy("level_mux/change_current_level", ChangeCurrentLevel) self.level_selector_proxy.wait_for_service() rospy.loginfo('level selector: found "level_mux/change_current_level" service')
def __init__(self, parent): super(NodeSelection, self).__init__() self.parent_widget = parent self.selected_nodes = [] self.setWindowTitle("Select the nodes you want to record") self.resize(500, 700) self.area = QScrollArea(self) self.main_widget = QWidget(self.area) self.ok_button = QPushButton("Done", self) self.ok_button.clicked.connect(self.onButtonClicked) self.ok_button.setEnabled(False) self.main_vlayout = QVBoxLayout(self) self.main_vlayout.addWidget(self.area) self.main_vlayout.addWidget(self.ok_button) self.setLayout(self.main_vlayout) self.selection_vlayout = QVBoxLayout(self) self.node_list = rosnode.get_node_names() self.node_list.sort() for node in self.node_list: self.addCheckBox(node) self.main_widget.setLayout(self.selection_vlayout) self.show()
class JointTrajectoryController(Plugin): """ Graphical frontend for a C{JointTrajectoryController}. There are two modes for interacting with a controller: 1. B{Monitor mode} Joint displays are updated with the state reported by the controller. This is a read-only mode and does I{not} send control commands. Every time a new controller is selected, it starts in monitor mode for safety reasons. 2. B{Control mode} Joint displays update the control command that is sent to the controller. Commands are sent periodically evan if the displays are not being updated by the user. To control the aggressiveness of the motions, the maximum speed of the sent commands can be scaled down using the C{Speed scaling control} This plugin is able to detect and keep track of all active controller managers, as well as the JointTrajectoryControllers that are I{running} in each controller manager. For a controller to be compatible with this plugin, it must comply with the following requisites: - The controller type contains the C{JointTrajectoryController} substring, e.g., C{position_controllers/JointTrajectoryController} - The controller exposes the C{command} and C{state} topics in its ROS interface. Additionally, there must be a URDF loaded with a valid joint limit specification, namely position (when applicable) and velocity limits. A reference implementation of the C{JointTrajectoryController} is available in the C{joint_trajectory_controller} ROS package. """ _cmd_pub_freq = 10.0 # Hz _widget_update_freq = 30.0 # Hz _ctrlrs_update_freq = 1 # Hz _min_traj_dur = 5.0 / _cmd_pub_freq # Minimum trajectory duration jointStateChanged = Signal([dict]) def __init__(self, context): super(JointTrajectoryController, self).__init__(context) self.setObjectName('JointTrajectoryController') # Create QWidget and extend it with all the attributes and children # from the UI file self._widget = QWidget() rp = rospkg.RosPack() ui_file = os.path.join(rp.get_path('rqt_joint_trajectory_controller'), 'resource', 'joint_trajectory_controller.ui') loadUi(ui_file, self._widget) self._widget.setObjectName('JointTrajectoryControllerUi') # Setup speed scaler speed_scaling = DoubleEditor(1.0, 100.0) speed_scaling.spin_box.setSuffix('%') speed_scaling.spin_box.setValue(50.0) speed_scaling.spin_box.setDecimals(0) speed_scaling.setEnabled(False) self._widget.speed_scaling_layout.addWidget(speed_scaling) self._speed_scaling_widget = speed_scaling speed_scaling.valueChanged.connect(self._on_speed_scaling_change) self._on_speed_scaling_change(speed_scaling.value()) # Show _widget.windowTitle on left-top of each plugin (when # it's set in _widget). This is useful when you open multiple # plugins at once. Also if you open multiple instances of your # plugin at once, these lines add number to make it easy to # tell from pane to pane. if context.serial_number() > 1: self._widget.setWindowTitle(self._widget.windowTitle() + (' (%d)' % context.serial_number())) # Add widget to the user interface context.add_widget(self._widget) # Initialize members self._jtc_name = [] # Name of selected joint trajectory controller self._cm_ns = [] # Namespace of the selected controller manager self._joint_pos = {} # name->pos map for joints of selected controller self._joint_names = [] # Ordered list of selected controller joints self._robot_joint_limits = {} # Lazily evaluated on first use # Timer for sending commands to active controller self._update_cmd_timer = QTimer(self) self._update_cmd_timer.setInterval(1000.0 / self._cmd_pub_freq) self._update_cmd_timer.timeout.connect(self._update_cmd_cb) # Timer for updating the joint widgets from the controller state self._update_act_pos_timer = QTimer(self) self._update_act_pos_timer.setInterval(1000.0 / self._widget_update_freq) self._update_act_pos_timer.timeout.connect(self._update_joint_widgets) # Timer for controller manager updates self._list_cm = ControllerManagerLister() self._update_cm_list_timer = QTimer(self) self._update_cm_list_timer.setInterval(1000.0 / self._ctrlrs_update_freq) self._update_cm_list_timer.timeout.connect(self._update_cm_list) self._update_cm_list_timer.start() # Timer for running controller updates self._update_jtc_list_timer = QTimer(self) self._update_jtc_list_timer.setInterval(1000.0 / self._ctrlrs_update_freq) self._update_jtc_list_timer.timeout.connect(self._update_jtc_list) self._update_jtc_list_timer.start() # Signal connections w = self._widget w.enable_button.toggled.connect(self._on_jtc_enabled) w.jtc_combo.currentIndexChanged[str].connect(self._on_jtc_change) w.cm_combo.currentIndexChanged[str].connect(self._on_cm_change) self._cmd_pub = None # Controller command publisher self._state_sub = None # Controller state subscriber self._list_controllers = None def shutdown_plugin(self): self._update_cmd_timer.stop() self._update_act_pos_timer.stop() self._update_cm_list_timer.stop() self._update_jtc_list_timer.stop() self._unregister_state_sub() self._unregister_cmd_pub() def save_settings(self, plugin_settings, instance_settings): instance_settings.set_value('cm_ns', self._cm_ns) instance_settings.set_value('jtc_name', self._jtc_name) def restore_settings(self, plugin_settings, instance_settings): # Restore last session's controller_manager, if present self._update_cm_list() cm_ns = instance_settings.value('cm_ns') cm_combo = self._widget.cm_combo cm_list = [cm_combo.itemText(i) for i in range(cm_combo.count())] try: idx = cm_list.index(cm_ns) cm_combo.setCurrentIndex(idx) # Resore last session's controller, if running self._update_jtc_list() jtc_name = instance_settings.value('jtc_name') jtc_combo = self._widget.jtc_combo jtc_list = [jtc_combo.itemText(i) for i in range(jtc_combo.count())] try: idx = jtc_list.index(jtc_name) jtc_combo.setCurrentIndex(idx) except (ValueError): pass except (ValueError): pass # def trigger_configuration(self): # Comment in to signal that the plugin has a way to configure # This will enable a setting button (gear icon) in each dock widget # title bar # Usually used to open a modal configuration dialog def _update_cm_list(self): update_combo(self._widget.cm_combo, self._list_cm()) def _update_jtc_list(self): # Clear controller list if no controller information is available if not self._list_controllers: self._widget.jtc_combo.clear() return # List of running controllers with a valid joint limits specification # for _all_ their joints running_jtc = self._running_jtc_info() if running_jtc and not self._robot_joint_limits: self._robot_joint_limits = get_joint_limits() # Lazy evaluation valid_jtc = [] for jtc_info in running_jtc: has_limits = all(name in self._robot_joint_limits for name in _jtc_joint_names(jtc_info)) if has_limits: valid_jtc.append(jtc_info); valid_jtc_names = [data.name for data in valid_jtc] # Update widget update_combo(self._widget.jtc_combo, sorted(valid_jtc_names)) def _on_speed_scaling_change(self, val): self._speed_scale = val / self._speed_scaling_widget.slider.maximum() def _on_joint_state_change(self, actual_pos): assert(len(actual_pos) == len(self._joint_pos)) for name in actual_pos.keys(): self._joint_pos[name]['position'] = actual_pos[name] def _on_cm_change(self, cm_ns): self._cm_ns = cm_ns if cm_ns: self._list_controllers = ControllerLister(cm_ns) # NOTE: Clear below is important, as different controller managers # might have controllers with the same name but different # configurations. Clearing forces controller re-discovery self._widget.jtc_combo.clear() self._update_jtc_list() else: self._list_controllers = None def _on_jtc_change(self, jtc_name): self._unload_jtc() self._jtc_name = jtc_name if self._jtc_name: self._load_jtc() def _on_jtc_enabled(self, val): # Don't allow enabling if there are no controllers selected if not self._jtc_name: self._widget.enable_button.setChecked(False) return # Enable/disable joint displays for joint_widget in self._joint_widgets(): joint_widget.setEnabled(val) # Enable/disable speed scaling self._speed_scaling_widget.setEnabled(val) if val: # Widgets send desired position commands to controller self._update_act_pos_timer.stop() self._update_cmd_timer.start() else: # Controller updates widgets with actual position self._update_cmd_timer.stop() self._update_act_pos_timer.start() def _load_jtc(self): # Initialize joint data corresponding to selected controller running_jtc = self._running_jtc_info() self._joint_names = next(_jtc_joint_names(x) for x in running_jtc if x.name == self._jtc_name) for name in self._joint_names: self._joint_pos[name] = {} # Update joint display try: layout = self._widget.joint_group.layout() for name in self._joint_names: limits = self._robot_joint_limits[name] joint_widget = DoubleEditor(limits['min_position'], limits['max_position']) layout.addRow(name, joint_widget) # NOTE: Using partial instead of a lambda because lambdas # "will not evaluate/look up the argument values before it is # effectively called, breaking situations like using a loop # variable inside it" from functools import partial par = partial(self._update_single_cmd_cb, name=name) joint_widget.valueChanged.connect(par) except: # TODO: Can we do better than swallow the exception? from sys import exc_info print 'Unexpected error:', exc_info()[0] # Enter monitor mode (sending commands disabled) self._on_jtc_enabled(False) # Setup ROS interfaces jtc_ns = _resolve_controller_ns(self._cm_ns, self._jtc_name) state_topic = jtc_ns + '/state' cmd_topic = jtc_ns + '/command' self._state_sub = rospy.Subscriber(state_topic, JointTrajectoryControllerState, self._state_cb, queue_size=1) self._cmd_pub = rospy.Publisher(cmd_topic, JointTrajectory, queue_size=1) # Start updating the joint positions self.jointStateChanged.connect(self._on_joint_state_change) def _unload_jtc(self): # Stop updating the joint positions try: self.jointStateChanged.disconnect(self._on_joint_state_change) except: pass # Reset ROS interfaces self._unregister_state_sub() self._unregister_cmd_pub() # Clear joint widgets # NOTE: Implementation is a workaround for: # https://bugreports.qt-project.org/browse/QTBUG-15990 :( layout = self._widget.joint_group.layout() if layout is not None: while layout.count(): layout.takeAt(0).widget().deleteLater() # Delete existing layout by reparenting to temporary QWidget().setLayout(layout) self._widget.joint_group.setLayout(QFormLayout()) # Reset joint data self._joint_names = [] self._joint_pos = {} # Enforce monitor mode (sending commands disabled) self._widget.enable_button.setChecked(False) def _running_jtc_info(self): from controller_manager_msgs.utils\ import filter_by_type, filter_by_state controller_list = self._list_controllers() jtc_list = filter_by_type(controller_list, 'JointTrajectoryController', match_substring=True) running_jtc_list = filter_by_state(jtc_list, 'running') return running_jtc_list def _unregister_cmd_pub(self): if self._cmd_pub is not None: self._cmd_pub.unregister() self._cmd_pub = None def _unregister_state_sub(self): if self._state_sub is not None: self._state_sub.unregister() self._state_sub = None def _state_cb(self, msg): actual_pos = {} for i in range(len(msg.joint_names)): joint_name = msg.joint_names[i] joint_pos = msg.actual.positions[i] actual_pos[joint_name] = joint_pos self.jointStateChanged.emit(actual_pos) def _update_single_cmd_cb(self, val, name): self._joint_pos[name]['command'] = val def _update_cmd_cb(self): dur = [] traj = JointTrajectory() traj.joint_names = self._joint_names point = JointTrajectoryPoint() for name in traj.joint_names: pos = self._joint_pos[name]['position'] cmd = pos try: cmd = self._joint_pos[name]['command'] except (KeyError): pass max_vel = self._robot_joint_limits[name]['max_velocity'] dur.append(max(abs(cmd - pos) / max_vel, self._min_traj_dur)) point.positions.append(cmd) point.time_from_start = rospy.Duration(max(dur) / self._speed_scale) traj.points.append(point) self._cmd_pub.publish(traj) def _update_joint_widgets(self): joint_widgets = self._joint_widgets() for id in range(len(joint_widgets)): joint_name = self._joint_names[id] try: joint_pos = self._joint_pos[joint_name]['position'] joint_widgets[id].setValue(joint_pos) except (KeyError): pass # Can happen when first connected to controller def _joint_widgets(self): # TODO: Cache instead of compute every time? widgets = [] layout = self._widget.joint_group.layout() for row_id in range(layout.rowCount()): widgets.append(layout.itemAt(row_id, QFormLayout.FieldRole).widget()) return widgets
def __init__(self, context): super(JointTrajectoryController, self).__init__(context) self.setObjectName('JointTrajectoryController') # Create QWidget and extend it with all the attributes and children # from the UI file self._widget = QWidget() rp = rospkg.RosPack() ui_file = os.path.join(rp.get_path('rqt_joint_trajectory_controller'), 'resource', 'joint_trajectory_controller.ui') loadUi(ui_file, self._widget) self._widget.setObjectName('JointTrajectoryControllerUi') # Setup speed scaler speed_scaling = DoubleEditor(1.0, 100.0) speed_scaling.spin_box.setSuffix('%') speed_scaling.spin_box.setValue(50.0) speed_scaling.spin_box.setDecimals(0) speed_scaling.setEnabled(False) self._widget.speed_scaling_layout.addWidget(speed_scaling) self._speed_scaling_widget = speed_scaling speed_scaling.valueChanged.connect(self._on_speed_scaling_change) self._on_speed_scaling_change(speed_scaling.value()) # Show _widget.windowTitle on left-top of each plugin (when # it's set in _widget). This is useful when you open multiple # plugins at once. Also if you open multiple instances of your # plugin at once, these lines add number to make it easy to # tell from pane to pane. if context.serial_number() > 1: self._widget.setWindowTitle(self._widget.windowTitle() + (' (%d)' % context.serial_number())) # Add widget to the user interface context.add_widget(self._widget) # Initialize members self._jtc_name = [] # Name of selected joint trajectory controller self._cm_ns = [] # Namespace of the selected controller manager self._joint_pos = {} # name->pos map for joints of selected controller self._joint_names = [] # Ordered list of selected controller joints self._robot_joint_limits = {} # Lazily evaluated on first use # Timer for sending commands to active controller self._update_cmd_timer = QTimer(self) self._update_cmd_timer.setInterval(1000.0 / self._cmd_pub_freq) self._update_cmd_timer.timeout.connect(self._update_cmd_cb) # Timer for updating the joint widgets from the controller state self._update_act_pos_timer = QTimer(self) self._update_act_pos_timer.setInterval(1000.0 / self._widget_update_freq) self._update_act_pos_timer.timeout.connect(self._update_joint_widgets) # Timer for controller manager updates self._list_cm = ControllerManagerLister() self._update_cm_list_timer = QTimer(self) self._update_cm_list_timer.setInterval(1000.0 / self._ctrlrs_update_freq) self._update_cm_list_timer.timeout.connect(self._update_cm_list) self._update_cm_list_timer.start() # Timer for running controller updates self._update_jtc_list_timer = QTimer(self) self._update_jtc_list_timer.setInterval(1000.0 / self._ctrlrs_update_freq) self._update_jtc_list_timer.timeout.connect(self._update_jtc_list) self._update_jtc_list_timer.start() # Signal connections w = self._widget w.enable_button.toggled.connect(self._on_jtc_enabled) w.jtc_combo.currentIndexChanged[str].connect(self._on_jtc_change) w.cm_combo.currentIndexChanged[str].connect(self._on_cm_change) self._cmd_pub = None # Controller command publisher self._state_sub = None # Controller state subscriber self._list_controllers = None
def __init__(self, context): super(RobotSteering, self).__init__(context) self.setObjectName('RobotSteering') self._publisher = None self._widget = QWidget() rp = rospkg.RosPack() ui_file = os.path.join(rp.get_path('rqt_robot_steering'), 'resource', 'RobotSteering.ui') loadUi(ui_file, self._widget) self._widget.setObjectName('RobotSteeringUi') if context.serial_number() > 1: self._widget.setWindowTitle(self._widget.windowTitle() + (' (%d)' % context.serial_number())) context.add_widget(self._widget) self._widget.topic_line_edit.textChanged.connect(self._on_topic_changed) self._widget.stop_push_button.pressed.connect(self._on_stop_pressed) self._widget.x_linear_slider.valueChanged.connect(self._on_x_linear_slider_changed) self._widget.z_angular_slider.valueChanged.connect(self._on_z_angular_slider_changed) self._widget.increase_x_linear_push_button.pressed.connect(self._on_strong_increase_x_linear_pressed) self._widget.reset_x_linear_push_button.pressed.connect(self._on_reset_x_linear_pressed) self._widget.decrease_x_linear_push_button.pressed.connect(self._on_strong_decrease_x_linear_pressed) self._widget.increase_z_angular_push_button.pressed.connect(self._on_strong_increase_z_angular_pressed) self._widget.reset_z_angular_push_button.pressed.connect(self._on_reset_z_angular_pressed) self._widget.decrease_z_angular_push_button.pressed.connect(self._on_strong_decrease_z_angular_pressed) self._widget.max_x_linear_double_spin_box.valueChanged.connect(self._on_max_x_linear_changed) self._widget.min_x_linear_double_spin_box.valueChanged.connect(self._on_min_x_linear_changed) self._widget.max_z_angular_double_spin_box.valueChanged.connect(self._on_max_z_angular_changed) self._widget.min_z_angular_double_spin_box.valueChanged.connect(self._on_min_z_angular_changed) self.shortcut_w = QShortcut(QKeySequence(Qt.Key_W), self._widget) self.shortcut_w.setContext(Qt.ApplicationShortcut) self.shortcut_w.activated.connect(self._on_increase_x_linear_pressed) self.shortcut_x = QShortcut(QKeySequence(Qt.Key_X), self._widget) self.shortcut_x.setContext(Qt.ApplicationShortcut) self.shortcut_x.activated.connect(self._on_reset_x_linear_pressed) self.shortcut_s = QShortcut(QKeySequence(Qt.Key_S), self._widget) self.shortcut_s.setContext(Qt.ApplicationShortcut) self.shortcut_s.activated.connect(self._on_decrease_x_linear_pressed) self.shortcut_a = QShortcut(QKeySequence(Qt.Key_A), self._widget) self.shortcut_a.setContext(Qt.ApplicationShortcut) self.shortcut_a.activated.connect(self._on_increase_z_angular_pressed) self.shortcut_z = QShortcut(QKeySequence(Qt.Key_Z), self._widget) self.shortcut_z.setContext(Qt.ApplicationShortcut) self.shortcut_z.activated.connect(self._on_reset_z_angular_pressed) self.shortcut_d = QShortcut(QKeySequence(Qt.Key_D), self._widget) self.shortcut_d.setContext(Qt.ApplicationShortcut) self.shortcut_d.activated.connect(self._on_decrease_z_angular_pressed) self.shortcut_shift_w = QShortcut(QKeySequence(Qt.SHIFT + Qt.Key_W), self._widget) self.shortcut_shift_w.setContext(Qt.ApplicationShortcut) self.shortcut_shift_w.activated.connect(self._on_strong_increase_x_linear_pressed) self.shortcut_shift_x = QShortcut(QKeySequence(Qt.SHIFT + Qt.Key_X), self._widget) self.shortcut_shift_x.setContext(Qt.ApplicationShortcut) self.shortcut_shift_x.activated.connect(self._on_reset_x_linear_pressed) self.shortcut_shift_s = QShortcut(QKeySequence(Qt.SHIFT + Qt.Key_S), self._widget) self.shortcut_shift_s.setContext(Qt.ApplicationShortcut) self.shortcut_shift_s.activated.connect(self._on_strong_decrease_x_linear_pressed) self.shortcut_shift_a = QShortcut(QKeySequence(Qt.SHIFT + Qt.Key_A), self._widget) self.shortcut_shift_a.setContext(Qt.ApplicationShortcut) self.shortcut_shift_a.activated.connect(self._on_strong_increase_z_angular_pressed) self.shortcut_shift_z = QShortcut(QKeySequence(Qt.SHIFT + Qt.Key_Z), self._widget) self.shortcut_shift_z.setContext(Qt.ApplicationShortcut) self.shortcut_shift_z.activated.connect(self._on_reset_z_angular_pressed) self.shortcut_shift_d = QShortcut(QKeySequence(Qt.SHIFT + Qt.Key_D), self._widget) self.shortcut_shift_d.setContext(Qt.ApplicationShortcut) self.shortcut_shift_d.activated.connect(self._on_strong_decrease_z_angular_pressed) self.shortcut_space = QShortcut(QKeySequence(Qt.Key_Space), self._widget) self.shortcut_space.setContext(Qt.ApplicationShortcut) self.shortcut_space.activated.connect(self._on_stop_pressed) self.shortcut_space = QShortcut(QKeySequence(Qt.SHIFT + Qt.Key_Space), self._widget) self.shortcut_space.setContext(Qt.ApplicationShortcut) self.shortcut_space.activated.connect(self._on_stop_pressed) self._widget.stop_push_button.setToolTip(self._widget.stop_push_button.toolTip() + ' ' + self.tr('([Shift +] Space)')) self._widget.increase_x_linear_push_button.setToolTip(self._widget.increase_x_linear_push_button.toolTip() + ' ' + self.tr('([Shift +] W)')) self._widget.reset_x_linear_push_button.setToolTip(self._widget.reset_x_linear_push_button.toolTip() + ' ' + self.tr('([Shift +] X)')) self._widget.decrease_x_linear_push_button.setToolTip(self._widget.decrease_x_linear_push_button.toolTip() + ' ' + self.tr('([Shift +] S)')) self._widget.increase_z_angular_push_button.setToolTip(self._widget.increase_z_angular_push_button.toolTip() + ' ' + self.tr('([Shift +] A)')) self._widget.reset_z_angular_push_button.setToolTip(self._widget.reset_z_angular_push_button.toolTip() + ' ' + self.tr('([Shift +] Z)')) self._widget.decrease_z_angular_push_button.setToolTip(self._widget.decrease_z_angular_push_button.toolTip() + ' ' + self.tr('([Shift +] D)')) # timer to consecutively send twist messages self._update_parameter_timer = QTimer(self) self._update_parameter_timer.timeout.connect(self._on_parameter_changed) self._update_parameter_timer.start(100) self.zero_cmd_sent = False
class RosPackGraph(Plugin): _deferred_fit_in_view = Signal() def __init__(self, context): super(RosPackGraph, self).__init__(context) self.initialized = False self._current_dotcode = None self._update_thread = WorkerThread(self._update_thread_run, self._update_finished) self._nodes = {} self._edges = {} self._options = {} self._options_serialized = '' self.setObjectName('RosPackGraph') rospack = rospkg.RosPack() rosstack = rospkg.RosStack() # factory builds generic dotcode items self.dotcode_factory = PydotFactory() # self.dotcode_factory = PygraphvizFactory() # generator builds rosgraph self.dotcode_generator = RosPackageGraphDotcodeGenerator(rospack, rosstack) # dot_to_qt transforms into Qt elements using dot layout self.dot_to_qt = DotToQtGenerator() self._widget = QWidget() rp = rospkg.RosPack() ui_file = os.path.join(rp.get_path('rqt_dep'), 'resource', 'RosPackGraph.ui') loadUi(ui_file, self._widget, {'InteractiveGraphicsView': InteractiveGraphicsView}) self._widget.setObjectName('RosPackGraphUi') if context.serial_number() > 1: self._widget.setWindowTitle(self._widget.windowTitle() + (' (%d)' % context.serial_number())) self._scene = QGraphicsScene() self._scene.setBackgroundBrush(Qt.white) self._widget.graphics_view.setScene(self._scene) self._widget.depth_combo_box.insertItem(0, self.tr('infinite'), -1) self._widget.depth_combo_box.insertItem(1, self.tr('1'), 2) self._widget.depth_combo_box.insertItem(2, self.tr('2'), 3) self._widget.depth_combo_box.insertItem(3, self.tr('3'), 4) self._widget.depth_combo_box.insertItem(4, self.tr('4'), 5) self._widget.depth_combo_box.currentIndexChanged.connect(self._refresh_rospackgraph) self._widget.directions_combo_box.insertItem(0, self.tr('depends'), 0) self._widget.directions_combo_box.insertItem(1, self.tr('depends_on'), 1) self._widget.directions_combo_box.insertItem(2, self.tr('both'), 2) self._widget.directions_combo_box.currentIndexChanged.connect(self._refresh_rospackgraph) self._widget.package_type_combo_box.insertItem(0, self.tr('wet & dry'), 3) self._widget.package_type_combo_box.insertItem(1, self.tr('wet only'), 2) self._widget.package_type_combo_box.insertItem(2, self.tr('dry only'), 1) self._widget.package_type_combo_box.currentIndexChanged.connect(self._refresh_rospackgraph) completionmodel = StackageCompletionModel(self._widget.filter_line_edit, rospack, rosstack) completer = RepeatedWordCompleter(completionmodel, self) completer.setCompletionMode(QCompleter.PopupCompletion) completer.setWrapAround(True) completer.setCaseSensitivity(Qt.CaseInsensitive) self._widget.filter_line_edit.editingFinished.connect(self._refresh_rospackgraph) self._widget.filter_line_edit.setCompleter(completer) self._widget.filter_line_edit.selectionChanged.connect(self._clear_filter) self._widget.with_stacks_check_box.clicked.connect(self._refresh_rospackgraph) self._widget.mark_check_box.clicked.connect(self._refresh_rospackgraph) self._widget.colorize_check_box.clicked.connect(self._refresh_rospackgraph) self._widget.hide_transitives_check_box.clicked.connect(self._refresh_rospackgraph) self._widget.refresh_graph_push_button.setIcon(QIcon.fromTheme('view-refresh')) self._widget.refresh_graph_push_button.pressed.connect(self._update_rospackgraph) self._widget.highlight_connections_check_box.toggled.connect(self._refresh_rospackgraph) self._widget.auto_fit_graph_check_box.toggled.connect(self._refresh_rospackgraph) self._widget.fit_in_view_push_button.setIcon(QIcon.fromTheme('zoom-original')) self._widget.fit_in_view_push_button.pressed.connect(self._fit_in_view) self._widget.load_dot_push_button.setIcon(QIcon.fromTheme('document-open')) self._widget.load_dot_push_button.pressed.connect(self._load_dot) self._widget.save_dot_push_button.setIcon(QIcon.fromTheme('document-save-as')) self._widget.save_dot_push_button.pressed.connect(self._save_dot) self._widget.save_as_svg_push_button.setIcon(QIcon.fromTheme('document-save-as')) self._widget.save_as_svg_push_button.pressed.connect(self._save_svg) self._widget.save_as_image_push_button.setIcon(QIcon.fromTheme('image')) self._widget.save_as_image_push_button.pressed.connect(self._save_image) self._deferred_fit_in_view.connect(self._fit_in_view, Qt.QueuedConnection) self._deferred_fit_in_view.emit() context.add_widget(self._widget) # If in either of following case, this turnes True # - 1st filtering key is already input by user # - filtering key is restored self._filtering_started = False def shutdown_plugin(self): self._update_thread.kill() def save_settings(self, plugin_settings, instance_settings): instance_settings.set_value('depth_combo_box_index', self._widget.depth_combo_box.currentIndex()) instance_settings.set_value('directions_combo_box_index', self._widget.directions_combo_box.currentIndex()) instance_settings.set_value('package_type_combo_box', self._widget.package_type_combo_box.currentIndex()) instance_settings.set_value('filter_line_edit_text', self._widget.filter_line_edit.text()) instance_settings.set_value('with_stacks_state', self._widget.with_stacks_check_box.isChecked()) instance_settings.set_value('hide_transitives_state', self._widget.hide_transitives_check_box.isChecked()) instance_settings.set_value('mark_state', self._widget.mark_check_box.isChecked()) instance_settings.set_value('colorize_state', self._widget.colorize_check_box.isChecked()) instance_settings.set_value('auto_fit_graph_check_box_state', self._widget.auto_fit_graph_check_box.isChecked()) instance_settings.set_value('highlight_connections_check_box_state', self._widget.highlight_connections_check_box.isChecked()) def restore_settings(self, plugin_settings, instance_settings): _str_filter = instance_settings.value('filter_line_edit_text', '') if (_str_filter == None or _str_filter == '') and \ not self._filtering_started: _str_filter = '(Separate pkgs by comma)' else: self._filtering_started = True self._widget.depth_combo_box.setCurrentIndex(int(instance_settings.value('depth_combo_box_index', 0))) self._widget.directions_combo_box.setCurrentIndex(int(instance_settings.value('directions_combo_box_index', 0))) self._widget.package_type_combo_box.setCurrentIndex(int(instance_settings.value('package_type_combo_box', 0))) self._widget.filter_line_edit.setText(_str_filter) self._widget.with_stacks_check_box.setChecked(instance_settings.value('with_stacks_state', True) in [True, 'true']) self._widget.mark_check_box.setChecked(instance_settings.value('mark_state', True) in [True, 'true']) self._widget.colorize_check_box.setChecked(instance_settings.value('colorize_state', False) in [True, 'true']) self._widget.hide_transitives_check_box.setChecked(instance_settings.value('hide_transitives_state', False) in [True, 'true']) self._widget.auto_fit_graph_check_box.setChecked(instance_settings.value('auto_fit_graph_check_box_state', True) in [True, 'true']) self._widget.highlight_connections_check_box.setChecked(instance_settings.value('highlight_connections_check_box_state', True) in [True, 'true']) self.initialized = True self._refresh_rospackgraph() def _update_rospackgraph(self): # re-enable controls customizing fetched ROS graph self._widget.depth_combo_box.setEnabled(True) self._widget.directions_combo_box.setEnabled(True) self._widget.package_type_combo_box.setEnabled(True) self._widget.filter_line_edit.setEnabled(True) self._widget.with_stacks_check_box.setEnabled(True) self._widget.mark_check_box.setEnabled(True) self._widget.colorize_check_box.setEnabled(True) self._widget.hide_transitives_check_box.setEnabled(True) self._refresh_rospackgraph(force_update=True) def _update_options(self): self._options['depth'] = self._widget.depth_combo_box.itemData(self._widget.depth_combo_box.currentIndex()) self._options['directions'] = self._widget.directions_combo_box.itemData(self._widget.directions_combo_box.currentIndex()) self._options['package_types'] = self._widget.package_type_combo_box.itemData(self._widget.package_type_combo_box.currentIndex()) self._options['with_stacks'] = self._widget.with_stacks_check_box.isChecked() self._options['mark_selected'] = self._widget.mark_check_box.isChecked() self._options['hide_transitives'] = self._widget.hide_transitives_check_box.isChecked() # TODO: Allow different color themes self._options['colortheme'] = True if self._widget.colorize_check_box.isChecked() else None self._options['names'] = self._widget.filter_line_edit.text().split(',') if self._options['names'] == [u'None']: self._options['names'] = [] self._options['highlight_level'] = 3 if self._widget.highlight_connections_check_box.isChecked() else 1 self._options['auto_fit'] = self._widget.auto_fit_graph_check_box.isChecked() def _refresh_rospackgraph(self, force_update=False): if not self.initialized: return self._update_thread.kill() self._update_options() # avoid update if options did not change and force_update is not set new_options_serialized = pickle.dumps(self._options) if new_options_serialized == self._options_serialized and not force_update: return self._options_serialized = pickle.dumps(self._options) self._scene.setBackgroundBrush(Qt.lightGray) self._update_thread.start() # this runs in a non-gui thread, so don't access widgets here directly def _update_thread_run(self): self._update_graph(self._generate_dotcode()) @Slot() def _update_finished(self): self._scene.setBackgroundBrush(Qt.white) self._redraw_graph_scene() # this runs in a non-gui thread, so don't access widgets here directly def _generate_dotcode(self): includes = [] excludes = [] for name in self._options['names']: if name.strip().startswith('-'): excludes.append(name.strip()[1:]) else: includes.append(name.strip()) # orientation = 'LR' descendants = True ancestors = True if self._options['directions'] == 1: descendants = False if self._options['directions'] == 0: ancestors = False return self.dotcode_generator.generate_dotcode(dotcode_factory=self.dotcode_factory, selected_names=includes, excludes=excludes, depth=self._options['depth'], with_stacks=self._options['with_stacks'], descendants=descendants, ancestors=ancestors, mark_selected=self._options['mark_selected'], colortheme=self._options['colortheme'], hide_transitives=self._options['hide_transitives'], hide_wet=self._options['package_types'] == 1, hide_dry=self._options['package_types'] == 2) # this runs in a non-gui thread, so don't access widgets here directly def _update_graph(self, dotcode): self._current_dotcode = dotcode self._nodes, self._edges = self.dot_to_qt.dotcode_to_qt_items(self._current_dotcode, self._options['highlight_level']) def _generate_tool_tip(self, url): if url is not None and ':' in url: item_type, item_path = url.split(':', 1) if item_type == 'node': tool_tip = 'Node:\n %s' % (item_path) service_names = rosservice.get_service_list(node=item_path) if service_names: tool_tip += '\nServices:' for service_name in service_names: try: service_type = rosservice.get_service_type(service_name) tool_tip += '\n %s [%s]' % (service_name, service_type) except rosservice.ROSServiceIOException as e: tool_tip += '\n %s' % (e) return tool_tip elif item_type == 'topic': topic_type, topic_name, _ = rostopic.get_topic_type(item_path) return 'Topic:\n %s\nType:\n %s' % (topic_name, topic_type) return url def _redraw_graph_scene(self): # remove items in order to not garbage nodes which will be continued to be used for item in self._scene.items(): self._scene.removeItem(item) self._scene.clear() for node_item in self._nodes.values(): self._scene.addItem(node_item) for edge_items in self._edges.values(): for edge_item in edge_items: edge_item.add_to_scene(self._scene) self._scene.setSceneRect(self._scene.itemsBoundingRect()) if self._options['auto_fit']: self._fit_in_view() def _load_dot(self, file_name=None): if file_name is None: file_name, _ = QFileDialog.getOpenFileName(self._widget, self.tr('Open graph from file'), None, self.tr('DOT graph (*.dot)')) if file_name is None or file_name == '': return try: fh = open(file_name, 'rb') dotcode = fh.read() fh.close() except IOError: return # disable controls customizing fetched ROS graph self._widget.depth_combo_box.setEnabled(False) self._widget.directions_combo_box.setEnabled(False) self._widget.package_type_combo_box.setEnabled(False) self._widget.filter_line_edit.setEnabled(False) self._widget.with_stacks_check_box.setEnabled(False) self._widget.mark_check_box.setEnabled(False) self._widget.colorize_check_box.setEnabled(False) self._widget.hide_transitives_check_box.setEnabled(False) self._update_graph(dotcode) self._redraw_graph_scene() @Slot() def _fit_in_view(self): self._widget.graphics_view.fitInView(self._scene.itemsBoundingRect(), Qt.KeepAspectRatio) def _save_dot(self): file_name, _ = QFileDialog.getSaveFileName(self._widget, self.tr('Save as DOT'), 'rospackgraph.dot', self.tr('DOT graph (*.dot)')) if file_name is None or file_name == '': return handle = QFile(file_name) if not handle.open(QIODevice.WriteOnly | QIODevice.Text): return handle.write(self._current_dotcode) handle.close() def _save_svg(self): file_name, _ = QFileDialog.getSaveFileName(self._widget, self.tr('Save as SVG'), 'rospackgraph.svg', self.tr('Scalable Vector Graphic (*.svg)')) if file_name is None or file_name == '': return generator = QSvgGenerator() generator.setFileName(file_name) generator.setSize((self._scene.sceneRect().size() * 2.0).toSize()) painter = QPainter(generator) painter.setRenderHint(QPainter.Antialiasing) self._scene.render(painter) painter.end() def _save_image(self): file_name, _ = QFileDialog.getSaveFileName(self._widget, self.tr('Save as image'), 'rospackgraph.png', self.tr('Image (*.bmp *.jpg *.png *.tiff)')) if file_name is None or file_name == '': return img = QImage((self._scene.sceneRect().size() * 2.0).toSize(), QImage.Format_ARGB32_Premultiplied) painter = QPainter(img) painter.setRenderHint(QPainter.Antialiasing) self._scene.render(painter) painter.end() img.save(file_name) def _clear_filter(self): if not self._filtering_started: self._widget.filter_line_edit.setText('') self._filtering_started = True
class Top(Plugin): NODE_FIELDS = [ 'pid', 'get_cpu_percent', 'get_memory_percent', 'get_num_threads'] OUT_FIELDS = ['node_name', 'pid', 'cpu_percent', 'memory_percent', 'num_threads' ] FORMAT_STRS = ['%s', '%s', '%0.2f', '%0.2f', '%s' ] NODE_LABELS = ['Node', 'PID', 'CPU %', 'Mem %', 'Num Threads' ] SORT_TYPE = [str, str, float, float, float ] TOOLTIPS = { 0: ('cmdline', lambda x: '\n'.join(textwrap.wrap(' '.join(x)))), 3: ('memory_info', lambda x: ('Resident: %0.2f MiB, Virtual: %0.2f MiB' % (x[0]/2**20, x[1]/2**20))) } _node_info = NodeInfo() name_filter = re.compile('') def __init__(self, context): super(Top, self).__init__(context) # Give QObjects reasonable names self.setObjectName('Top') # Process standalone plugin command-line arguments from argparse import ArgumentParser parser = ArgumentParser() # Add argument(s) to the parser. parser.add_argument("-q", "--quiet", action="store_true", dest="quiet", help="Put plugin in silent mode") args, unknowns = parser.parse_known_args(context.argv()) # if not args.quiet: # print 'arguments: ', args # print 'unknowns: ', unknowns self._selected_node = '' self._selected_node_lock = RLock() # Setup the toolbar self._toolbar = QToolBar() self._filter_box = QLineEdit() self._regex_box = QCheckBox() self._regex_box.setText('regex') self._toolbar.addWidget(QLabel('Filter')) self._toolbar.addWidget(self._filter_box) self._toolbar.addWidget(self._regex_box) self._filter_box.returnPressed.connect(self.update_filter) self._regex_box.stateChanged.connect(self.update_filter) # Create a container widget and give it a layout self._container = QWidget() self._container.setWindowTitle('Process Monitor') self._layout = QVBoxLayout() self._container.setLayout(self._layout) self._layout.addWidget(self._toolbar) # Create the table widget self._table_widget = QTreeWidget() self._table_widget.setObjectName('TopTable') self._table_widget.setColumnCount(len(self.NODE_LABELS)) self._table_widget.setHeaderLabels(self.NODE_LABELS) self._table_widget.itemClicked.connect(self._tableItemClicked) self._table_widget.setSortingEnabled(True) self._table_widget.setAlternatingRowColors(True) self._layout.addWidget(self._table_widget) context.add_widget(self._container) # Add a button for killing nodes self._kill_button = QPushButton('Kill Node') self._layout.addWidget(self._kill_button) self._kill_button.clicked.connect(self._kill_node) # Update twice since the first cpu% lookup will always return 0 self.update_table() self.update_table() self._table_widget.resizeColumnToContents(0) # Start a timer to trigger updates self._update_timer = QTimer() self._update_timer.setInterval(1000) self._update_timer.timeout.connect(self.update_table) self._update_timer.start() def _tableItemClicked(self, item, column): with self._selected_node_lock: self._selected_node = item.text(0) def update_filter(self, *args): if self._regex_box.isChecked(): expr = self._filter_box.text() else: expr = re.escape(self._filter_box.text()) self.name_filter = re.compile(expr) self.update_table() def _kill_node(self): self._node_info.kill_node(self._selected_node) def update_one_item(self, row, info): twi = TopWidgetItem() for col, field in enumerate(self.OUT_FIELDS): val = info[field] twi.setText(col, self.FORMAT_STRS[col] % val) self._table_widget.insertTopLevelItem(row, twi) for col, (key, func) in self.TOOLTIPS.items(): twi.setToolTip(col, func(info[key])) with self._selected_node_lock: if twi.text(0) == self._selected_node: twi.setSelected(True) twi.setHidden(len(self.name_filter.findall(info['node_name'])) == 0) def update_table(self): self._table_widget.clear() infos = self._node_info.get_all_node_fields(self.NODE_FIELDS) for nx, info in enumerate(infos): self.update_one_item(nx, info) def shutdown_plugin(self): self._update_timer.stop() def save_settings(self, plugin_settings, instance_settings): instance_settings.set_value('filter_text', self._filter_box.text()) instance_settings.set_value('is_regex', int(self._regex_box.checkState())) def restore_settings(self, plugin_settings, instance_settings): self._filter_box.setText(instance_settings.value('filter_text')) is_regex_int = instance_settings.value('is_regex') if is_regex_int: self._regex_box.setCheckState(Qt.CheckState(is_regex_int)) else: self._regex_box.setCheckState(Qt.CheckState(0)) self.update_filter()
def __init__(self, context): super(RosGraph, self).__init__(context) self.initialized = False self.setObjectName('RosGraph') self._graph = None self._current_dotcode = None self._widget = QWidget() # factory builds generic dotcode items self.dotcode_factory = PydotFactory() # self.dotcode_factory = PygraphvizFactory() # generator builds rosgraph self.dotcode_generator = RosGraphDotcodeGenerator() # dot_to_qt transforms into Qt elements using dot layout self.dot_to_qt = DotToQtGenerator() rp = rospkg.RosPack() ui_file = os.path.join(rp.get_path('rqt_graph'), 'resource', 'RosGraph.ui') loadUi(ui_file, self._widget, {'InteractiveGraphicsView': InteractiveGraphicsView}) self._widget.setObjectName('RosGraphUi') if context.serial_number() > 1: self._widget.setWindowTitle(self._widget.windowTitle() + (' (%d)' % context.serial_number())) self._scene = QGraphicsScene() self._scene.setBackgroundBrush(Qt.white) self._widget.graphics_view.setScene(self._scene) self._widget.graph_type_combo_box.insertItem(0, self.tr('Nodes only'), NODE_NODE_GRAPH) self._widget.graph_type_combo_box.insertItem(1, self.tr('Nodes/Topics (active)'), NODE_TOPIC_GRAPH) self._widget.graph_type_combo_box.insertItem(2, self.tr('Nodes/Topics (all)'), NODE_TOPIC_ALL_GRAPH) self._widget.graph_type_combo_box.setCurrentIndex(0) self._widget.graph_type_combo_box.currentIndexChanged.connect(self._refresh_rosgraph) self.node_completionmodel = NamespaceCompletionModel(self._widget.filter_line_edit, False) completer = RepeatedWordCompleter(self.node_completionmodel, self) completer.setCompletionMode(QCompleter.PopupCompletion) completer.setWrapAround(True) completer.setCaseSensitivity(Qt.CaseInsensitive) self._widget.filter_line_edit.editingFinished.connect(self._refresh_rosgraph) self._widget.filter_line_edit.setCompleter(completer) self.topic_completionmodel = NamespaceCompletionModel(self._widget.topic_filter_line_edit, False) topic_completer = RepeatedWordCompleter(self.topic_completionmodel, self) topic_completer.setCompletionMode(QCompleter.PopupCompletion) topic_completer.setWrapAround(True) topic_completer.setCaseSensitivity(Qt.CaseInsensitive) self._widget.topic_filter_line_edit.editingFinished.connect(self._refresh_rosgraph) self._widget.topic_filter_line_edit.setCompleter(topic_completer) self._widget.namespace_cluster_check_box.clicked.connect(self._refresh_rosgraph) self._widget.actionlib_check_box.clicked.connect(self._refresh_rosgraph) self._widget.dead_sinks_check_box.clicked.connect(self._refresh_rosgraph) self._widget.leaf_topics_check_box.clicked.connect(self._refresh_rosgraph) self._widget.quiet_check_box.clicked.connect(self._refresh_rosgraph) self._widget.refresh_graph_push_button.setIcon(QIcon.fromTheme('view-refresh')) self._widget.refresh_graph_push_button.pressed.connect(self._update_rosgraph) self._widget.highlight_connections_check_box.toggled.connect(self._redraw_graph_view) self._widget.auto_fit_graph_check_box.toggled.connect(self._redraw_graph_view) self._widget.fit_in_view_push_button.setIcon(QIcon.fromTheme('zoom-original')) self._widget.fit_in_view_push_button.pressed.connect(self._fit_in_view) self._widget.load_dot_push_button.setIcon(QIcon.fromTheme('document-open')) self._widget.load_dot_push_button.pressed.connect(self._load_dot) self._widget.save_dot_push_button.setIcon(QIcon.fromTheme('document-save-as')) self._widget.save_dot_push_button.pressed.connect(self._save_dot) self._widget.save_as_svg_push_button.setIcon(QIcon.fromTheme('document-save-as')) self._widget.save_as_svg_push_button.pressed.connect(self._save_svg) self._widget.save_as_image_push_button.setIcon(QIcon.fromTheme('image')) self._widget.save_as_image_push_button.pressed.connect(self._save_image) self._update_rosgraph() self._deferred_fit_in_view.connect(self._fit_in_view, Qt.QueuedConnection) self._deferred_fit_in_view.emit() context.add_widget(self._widget)
class RosGraph(Plugin): _deferred_fit_in_view = Signal() def __init__(self, context): super(RosGraph, self).__init__(context) self.initialized = False self.setObjectName('RosGraph') self._graph = None self._current_dotcode = None self._widget = QWidget() # factory builds generic dotcode items self.dotcode_factory = PydotFactory() # self.dotcode_factory = PygraphvizFactory() # generator builds rosgraph self.dotcode_generator = RosGraphDotcodeGenerator() # dot_to_qt transforms into Qt elements using dot layout self.dot_to_qt = DotToQtGenerator() rp = rospkg.RosPack() ui_file = os.path.join(rp.get_path('rqt_graph'), 'resource', 'RosGraph.ui') loadUi(ui_file, self._widget, {'InteractiveGraphicsView': InteractiveGraphicsView}) self._widget.setObjectName('RosGraphUi') if context.serial_number() > 1: self._widget.setWindowTitle(self._widget.windowTitle() + (' (%d)' % context.serial_number())) self._scene = QGraphicsScene() self._scene.setBackgroundBrush(Qt.white) self._widget.graphics_view.setScene(self._scene) self._widget.graph_type_combo_box.insertItem(0, self.tr('Nodes only'), NODE_NODE_GRAPH) self._widget.graph_type_combo_box.insertItem(1, self.tr('Nodes/Topics (active)'), NODE_TOPIC_GRAPH) self._widget.graph_type_combo_box.insertItem(2, self.tr('Nodes/Topics (all)'), NODE_TOPIC_ALL_GRAPH) self._widget.graph_type_combo_box.setCurrentIndex(0) self._widget.graph_type_combo_box.currentIndexChanged.connect(self._refresh_rosgraph) self.node_completionmodel = NamespaceCompletionModel(self._widget.filter_line_edit, False) completer = RepeatedWordCompleter(self.node_completionmodel, self) completer.setCompletionMode(QCompleter.PopupCompletion) completer.setWrapAround(True) completer.setCaseSensitivity(Qt.CaseInsensitive) self._widget.filter_line_edit.editingFinished.connect(self._refresh_rosgraph) self._widget.filter_line_edit.setCompleter(completer) self.topic_completionmodel = NamespaceCompletionModel(self._widget.topic_filter_line_edit, False) topic_completer = RepeatedWordCompleter(self.topic_completionmodel, self) topic_completer.setCompletionMode(QCompleter.PopupCompletion) topic_completer.setWrapAround(True) topic_completer.setCaseSensitivity(Qt.CaseInsensitive) self._widget.topic_filter_line_edit.editingFinished.connect(self._refresh_rosgraph) self._widget.topic_filter_line_edit.setCompleter(topic_completer) self._widget.namespace_cluster_check_box.clicked.connect(self._refresh_rosgraph) self._widget.actionlib_check_box.clicked.connect(self._refresh_rosgraph) self._widget.dead_sinks_check_box.clicked.connect(self._refresh_rosgraph) self._widget.leaf_topics_check_box.clicked.connect(self._refresh_rosgraph) self._widget.quiet_check_box.clicked.connect(self._refresh_rosgraph) self._widget.refresh_graph_push_button.setIcon(QIcon.fromTheme('view-refresh')) self._widget.refresh_graph_push_button.pressed.connect(self._update_rosgraph) self._widget.highlight_connections_check_box.toggled.connect(self._redraw_graph_view) self._widget.auto_fit_graph_check_box.toggled.connect(self._redraw_graph_view) self._widget.fit_in_view_push_button.setIcon(QIcon.fromTheme('zoom-original')) self._widget.fit_in_view_push_button.pressed.connect(self._fit_in_view) self._widget.load_dot_push_button.setIcon(QIcon.fromTheme('document-open')) self._widget.load_dot_push_button.pressed.connect(self._load_dot) self._widget.save_dot_push_button.setIcon(QIcon.fromTheme('document-save-as')) self._widget.save_dot_push_button.pressed.connect(self._save_dot) self._widget.save_as_svg_push_button.setIcon(QIcon.fromTheme('document-save-as')) self._widget.save_as_svg_push_button.pressed.connect(self._save_svg) self._widget.save_as_image_push_button.setIcon(QIcon.fromTheme('image')) self._widget.save_as_image_push_button.pressed.connect(self._save_image) self._update_rosgraph() self._deferred_fit_in_view.connect(self._fit_in_view, Qt.QueuedConnection) self._deferred_fit_in_view.emit() context.add_widget(self._widget) def save_settings(self, plugin_settings, instance_settings): instance_settings.set_value('graph_type_combo_box_index', self._widget.graph_type_combo_box.currentIndex()) instance_settings.set_value('filter_line_edit_text', self._widget.filter_line_edit.text()) instance_settings.set_value('topic_filter_line_edit_text', self._widget.topic_filter_line_edit.text()) instance_settings.set_value('namespace_cluster_check_box_state', self._widget.namespace_cluster_check_box.isChecked()) instance_settings.set_value('actionlib_check_box_state', self._widget.actionlib_check_box.isChecked()) instance_settings.set_value('dead_sinks_check_box_state', self._widget.dead_sinks_check_box.isChecked()) instance_settings.set_value('leaf_topics_check_box_state', self._widget.leaf_topics_check_box.isChecked()) instance_settings.set_value('quiet_check_box_state', self._widget.quiet_check_box.isChecked()) instance_settings.set_value('auto_fit_graph_check_box_state', self._widget.auto_fit_graph_check_box.isChecked()) instance_settings.set_value('highlight_connections_check_box_state', self._widget.highlight_connections_check_box.isChecked()) def restore_settings(self, plugin_settings, instance_settings): self._widget.graph_type_combo_box.setCurrentIndex(int(instance_settings.value('graph_type_combo_box_index', 0))) self._widget.filter_line_edit.setText(instance_settings.value('filter_line_edit_text', '/')) self._widget.topic_filter_line_edit.setText(instance_settings.value('topic_filter_line_edit_text', '/')) self._widget.namespace_cluster_check_box.setChecked(instance_settings.value('namespace_cluster_check_box_state', True) in [True, 'true']) self._widget.actionlib_check_box.setChecked(instance_settings.value('actionlib_check_box_state', True) in [True, 'true']) self._widget.dead_sinks_check_box.setChecked(instance_settings.value('dead_sinks_check_box_state', True) in [True, 'true']) self._widget.leaf_topics_check_box.setChecked(instance_settings.value('leaf_topics_check_box_state', True) in [True, 'true']) self._widget.quiet_check_box.setChecked(instance_settings.value('quiet_check_box_state', True) in [True, 'true']) self._widget.auto_fit_graph_check_box.setChecked(instance_settings.value('auto_fit_graph_check_box_state', True) in [True, 'true']) self._widget.highlight_connections_check_box.setChecked(instance_settings.value('highlight_connections_check_box_state', True) in [True, 'true']) self.initialized = True self._refresh_rosgraph() def _update_rosgraph(self): # re-enable controls customizing fetched ROS graph self._widget.graph_type_combo_box.setEnabled(True) self._widget.filter_line_edit.setEnabled(True) self._widget.topic_filter_line_edit.setEnabled(True) self._widget.namespace_cluster_check_box.setEnabled(True) self._widget.actionlib_check_box.setEnabled(True) self._widget.dead_sinks_check_box.setEnabled(True) self._widget.leaf_topics_check_box.setEnabled(True) self._widget.quiet_check_box.setEnabled(True) self._graph = rosgraph.impl.graph.Graph() self._graph.set_master_stale(5.0) self._graph.set_node_stale(5.0) self._graph.update() self.node_completionmodel.refresh(self._graph.nn_nodes) self.topic_completionmodel.refresh(self._graph.nt_nodes) self._refresh_rosgraph() def _refresh_rosgraph(self): if not self.initialized: return self._update_graph_view(self._generate_dotcode()) def _generate_dotcode(self): ns_filter = self._widget.filter_line_edit.text() topic_filter = self._widget.topic_filter_line_edit.text() graph_mode = self._widget.graph_type_combo_box.itemData(self._widget.graph_type_combo_box.currentIndex()) orientation = 'LR' if self._widget.namespace_cluster_check_box.isChecked(): namespace_cluster = 1 else: namespace_cluster = 0 accumulate_actions = self._widget.actionlib_check_box.isChecked() hide_dead_end_topics = self._widget.dead_sinks_check_box.isChecked() hide_single_connection_topics = self._widget.leaf_topics_check_box.isChecked() quiet = self._widget.quiet_check_box.isChecked() return self.dotcode_generator.generate_dotcode( rosgraphinst=self._graph, ns_filter=ns_filter, topic_filter=topic_filter, graph_mode=graph_mode, hide_single_connection_topics=hide_single_connection_topics, hide_dead_end_topics=hide_dead_end_topics, cluster_namespaces_level=namespace_cluster, accumulate_actions=accumulate_actions, dotcode_factory=self.dotcode_factory, orientation=orientation, quiet=quiet) def _update_graph_view(self, dotcode): if dotcode == self._current_dotcode: return self._current_dotcode = dotcode self._redraw_graph_view() def _generate_tool_tip(self, url): if url is not None and ':' in url: item_type, item_path = url.split(':', 1) if item_type == 'node': tool_tip = 'Node:\n %s' % (item_path) service_names = rosservice.get_service_list(node=item_path) if service_names: tool_tip += '\nServices:' for service_name in service_names: try: service_type = rosservice.get_service_type(service_name) tool_tip += '\n %s [%s]' % (service_name, service_type) except rosservice.ROSServiceIOException as e: tool_tip += '\n %s' % (e) return tool_tip elif item_type == 'topic': topic_type, topic_name, _ = rostopic.get_topic_type(item_path) return 'Topic:\n %s\nType:\n %s' % (topic_name, topic_type) return url def _redraw_graph_view(self): self._scene.clear() if self._widget.highlight_connections_check_box.isChecked(): highlight_level = 3 else: highlight_level = 1 # layout graph and create qt items (nodes, edges) = self.dot_to_qt.dotcode_to_qt_items(self._current_dotcode, highlight_level=highlight_level, same_label_siblings=True) for node_item in nodes.itervalues(): self._scene.addItem(node_item) for edge_items in edges.itervalues(): for edge_item in edge_items: edge_item.add_to_scene(self._scene) self._scene.setSceneRect(self._scene.itemsBoundingRect()) if self._widget.auto_fit_graph_check_box.isChecked(): self._fit_in_view() def _load_dot(self, file_name=None): if file_name is None: file_name, _ = QFileDialog.getOpenFileName(self._widget, self.tr('Open graph from file'), None, self.tr('DOT graph (*.dot)')) if file_name is None or file_name == '': return try: fh = open(file_name, 'rb') dotcode = fh.read() fh.close() except IOError: return # disable controls customizing fetched ROS graph self._widget.graph_type_combo_box.setEnabled(False) self._widget.filter_line_edit.setEnabled(False) self._widget.topic_filter_line_edit.setEnabled(False) self._widget.namespace_cluster_check_box.setEnabled(False) self._widget.actionlib_check_box.setEnabled(False) self._widget.dead_sinks_check_box.setEnabled(False) self._widget.leaf_topics_check_box.setEnabled(False) self._widget.quiet_check_box.setEnabled(False) self._update_graph_view(dotcode) def _fit_in_view(self): self._widget.graphics_view.fitInView(self._scene.itemsBoundingRect(), Qt.KeepAspectRatio) def _save_dot(self): file_name, _ = QFileDialog.getSaveFileName(self._widget, self.tr('Save as DOT'), 'rosgraph.dot', self.tr('DOT graph (*.dot)')) if file_name is None or file_name == '': return handle = QFile(file_name) if not handle.open(QIODevice.WriteOnly | QIODevice.Text): return handle.write(self._current_dotcode) handle.close() def _save_svg(self): file_name, _ = QFileDialog.getSaveFileName(self._widget, self.tr('Save as SVG'), 'rosgraph.svg', self.tr('Scalable Vector Graphic (*.svg)')) if file_name is None or file_name == '': return generator = QSvgGenerator() generator.setFileName(file_name) generator.setSize((self._scene.sceneRect().size() * 2.0).toSize()) painter = QPainter(generator) painter.setRenderHint(QPainter.Antialiasing) self._scene.render(painter) painter.end() def _save_image(self): file_name, _ = QFileDialog.getSaveFileName(self._widget, self.tr('Save as image'), 'rosgraph.png', self.tr('Image (*.bmp *.jpg *.png *.tiff)')) if file_name is None or file_name == '': return img = QImage((self._scene.sceneRect().size() * 2.0).toSize(), QImage.Format_ARGB32_Premultiplied) painter = QPainter(img) painter.setRenderHint(QPainter.Antialiasing) self._scene.render(painter) painter.end() img.save(file_name)
def __init__(self, context): super(ControllerManager, self).__init__(context) self.setObjectName('ControllerManager') # Create QWidget and extend it with all the attributes and children # from the UI file self._widget = QWidget() rp = rospkg.RosPack() ui_file = os.path.join(rp.get_path('rqt_controller_manager'), 'resource', 'controller_manager.ui') loadUi(ui_file, self._widget) self._widget.setObjectName('ControllerManagerUi') # Pop-up that displays controller information self._popup_widget = QWidget() ui_file = os.path.join(rp.get_path('rqt_controller_manager'), 'resource', 'controller_info.ui') loadUi(ui_file, self._popup_widget) self._popup_widget.setObjectName('ControllerInfoUi') # Show _widget.windowTitle on left-top of each plugin (when # it's set in _widget). This is useful when you open multiple # plugins at once. Also if you open multiple instances of your # plugin at once, these lines add number to make it easy to # tell from pane to pane. if context.serial_number() > 1: self._widget.setWindowTitle(self._widget.windowTitle() + (' (%d)' % context.serial_number())) # Add widget to the user interface context.add_widget(self._widget) # Initialize members self._cm_ns = [] # Namespace of the selected controller manager self._controllers = [] # State of each controller self._table_model = None self._controller_lister = None # Controller manager service proxies self._load_srv = None self._unload_srv = None self._switch_srv = None # Controller state icons rospack = rospkg.RosPack() path = rospack.get_path('rqt_controller_manager') self._icons = {'running': QIcon(path + '/resource/led_green.png'), 'stopped': QIcon(path + '/resource/led_red.png'), 'uninitialized': QIcon(path + '/resource/led_off.png')} # Controllers display table_view = self._widget.table_view table_view.setContextMenuPolicy(Qt.CustomContextMenu) table_view.customContextMenuRequested.connect(self._on_ctrl_menu) table_view.doubleClicked.connect(self._on_ctrl_info) header = table_view.horizontalHeader() header.setSectionResizeMode(QHeaderView.ResizeToContents) header.setContextMenuPolicy(Qt.CustomContextMenu) header.customContextMenuRequested.connect(self._on_header_menu) # Timer for controller manager updates self._list_cm = ControllerManagerLister() self._update_cm_list_timer = QTimer(self) self._update_cm_list_timer.setInterval(1000.0 / self._cm_update_freq) self._update_cm_list_timer.timeout.connect(self._update_cm_list) self._update_cm_list_timer.start() # Timer for running controller updates self._update_ctrl_list_timer = QTimer(self) self._update_ctrl_list_timer.setInterval(1000.0 / self._cm_update_freq) self._update_ctrl_list_timer.timeout.connect(self._update_controllers) self._update_ctrl_list_timer.start() # Signal connections w = self._widget w.cm_combo.currentIndexChanged[str].connect(self._on_cm_change)
class ControllerManager(Plugin): """ Graphical frontend for managing ros_control controllers. """ _cm_update_freq = 1 # Hz def __init__(self, context): super(ControllerManager, self).__init__(context) self.setObjectName('ControllerManager') # Create QWidget and extend it with all the attributes and children # from the UI file self._widget = QWidget() rp = rospkg.RosPack() ui_file = os.path.join(rp.get_path('rqt_controller_manager'), 'resource', 'controller_manager.ui') loadUi(ui_file, self._widget) self._widget.setObjectName('ControllerManagerUi') # Pop-up that displays controller information self._popup_widget = QWidget() ui_file = os.path.join(rp.get_path('rqt_controller_manager'), 'resource', 'controller_info.ui') loadUi(ui_file, self._popup_widget) self._popup_widget.setObjectName('ControllerInfoUi') # Show _widget.windowTitle on left-top of each plugin (when # it's set in _widget). This is useful when you open multiple # plugins at once. Also if you open multiple instances of your # plugin at once, these lines add number to make it easy to # tell from pane to pane. if context.serial_number() > 1: self._widget.setWindowTitle(self._widget.windowTitle() + (' (%d)' % context.serial_number())) # Add widget to the user interface context.add_widget(self._widget) # Initialize members self._cm_ns = [] # Namespace of the selected controller manager self._controllers = [] # State of each controller self._table_model = None self._controller_lister = None # Controller manager service proxies self._load_srv = None self._unload_srv = None self._switch_srv = None # Controller state icons rospack = rospkg.RosPack() path = rospack.get_path('rqt_controller_manager') self._icons = {'running': QIcon(path + '/resource/led_green.png'), 'stopped': QIcon(path + '/resource/led_red.png'), 'uninitialized': QIcon(path + '/resource/led_off.png')} # Controllers display table_view = self._widget.table_view table_view.setContextMenuPolicy(Qt.CustomContextMenu) table_view.customContextMenuRequested.connect(self._on_ctrl_menu) table_view.doubleClicked.connect(self._on_ctrl_info) header = table_view.horizontalHeader() header.setSectionResizeMode(QHeaderView.ResizeToContents) header.setContextMenuPolicy(Qt.CustomContextMenu) header.customContextMenuRequested.connect(self._on_header_menu) # Timer for controller manager updates self._list_cm = ControllerManagerLister() self._update_cm_list_timer = QTimer(self) self._update_cm_list_timer.setInterval(1000.0 / self._cm_update_freq) self._update_cm_list_timer.timeout.connect(self._update_cm_list) self._update_cm_list_timer.start() # Timer for running controller updates self._update_ctrl_list_timer = QTimer(self) self._update_ctrl_list_timer.setInterval(1000.0 / self._cm_update_freq) self._update_ctrl_list_timer.timeout.connect(self._update_controllers) self._update_ctrl_list_timer.start() # Signal connections w = self._widget w.cm_combo.currentIndexChanged[str].connect(self._on_cm_change) def shutdown_plugin(self): self._update_cm_list_timer.stop() self._update_ctrl_list_timer.stop() self._popup_widget.hide() def save_settings(self, plugin_settings, instance_settings): instance_settings.set_value('cm_ns', self._cm_ns) def restore_settings(self, plugin_settings, instance_settings): # Restore last session's controller_manager, if present self._update_cm_list() cm_ns = instance_settings.value('cm_ns') cm_combo = self._widget.cm_combo cm_list = [cm_combo.itemText(i) for i in range(cm_combo.count())] try: idx = cm_list.index(cm_ns) cm_combo.setCurrentIndex(idx) except (ValueError): pass # def trigger_configuration(self): # Comment in to signal that the plugin has a way to configure # This will enable a setting button (gear icon) in each dock widget # title bar # Usually used to open a modal configuration dialog def _update_cm_list(self): update_combo(self._widget.cm_combo, self._list_cm()) def _on_cm_change(self, cm_ns): self._cm_ns = cm_ns # Setup services for communicating with the selected controller manager self._set_cm_services(cm_ns) # Controller lister for the selected controller manager if cm_ns: self._controller_lister = ControllerLister(cm_ns) self._update_controllers() else: self._controller_lister = None def _set_cm_services(self, cm_ns): if cm_ns: # NOTE: Persistent services are used for performance reasons. # If the controller manager dies, we detect it and disconnect from # it anyway load_srv_name = _append_ns(cm_ns, 'load_controller') self._load_srv = rospy.ServiceProxy(load_srv_name, LoadController, persistent=True) unload_srv_name = _append_ns(cm_ns, 'unload_controller') self._unload_srv = rospy.ServiceProxy(unload_srv_name, UnloadController, persistent=True) switch_srv_name = _append_ns(cm_ns, 'switch_controller') self._switch_srv = rospy.ServiceProxy(switch_srv_name, SwitchController, persistent=True) else: self._load_srv = None self._unload_srv = None self._switch_srv = None def _update_controllers(self): # Find controllers associated to the selected controller manager controllers = self._list_controllers() # Update controller display, if necessary if self._controllers != controllers: self._controllers = controllers self._show_controllers() # NOTE: Model is recomputed from scratch def _list_controllers(self): """ @return List of controllers associated to a controller manager namespace. Contains both stopped/running controllers, as returned by the C{list_controllers} service, plus uninitialized controllers with configurations loaded in the parameter server. @rtype [str] """ if not self._cm_ns: return [] # Add loaded controllers first controllers = self._controller_lister() # Append potential controller configs found in the parameter server all_ctrls_ns = _resolve_controllers_ns(self._cm_ns) for name in get_rosparam_controller_names(all_ctrls_ns): add_ctrl = not any(name == ctrl.name for ctrl in controllers) if add_ctrl: type_str = _rosparam_controller_type(all_ctrls_ns, name) uninit_ctrl = ControllerState(name=name, type=type_str, state='uninitialized') controllers.append(uninit_ctrl) return controllers def _show_controllers(self): table_view = self._widget.table_view self._table_model = ControllerTable(self._controllers, self._icons) table_view.setModel(self._table_model) def _on_ctrl_menu(self, pos): # Get data of selected controller row = self._widget.table_view.rowAt(pos.y()) if row < 0: return # Cursor is not under a valid item ctrl = self._controllers[row] # Show context menu menu = QMenu(self._widget.table_view) if ctrl.state == 'running': action_stop = menu.addAction(self._icons['stopped'], 'Stop') action_kill = menu.addAction(self._icons['uninitialized'], 'Stop and Unload') elif ctrl.state == 'stopped': action_start = menu.addAction(self._icons['running'], 'Start') action_unload = menu.addAction(self._icons['uninitialized'], 'Unload') elif ctrl.state == 'uninitialized': action_load = menu.addAction(self._icons['stopped'], 'Load') action_spawn = menu.addAction(self._icons['running'], 'Load and Start') action = menu.exec_(self._widget.table_view.mapToGlobal(pos)) # Evaluate user action if ctrl.state == 'running': if action is action_stop: self._stop_controller(ctrl.name) elif action is action_kill: self._stop_controller(ctrl.name) self._unload_controller(ctrl.name) elif ctrl.state == 'stopped': if action is action_start: self._start_controller(ctrl.name) elif action is action_unload: self._unload_controller(ctrl.name) elif ctrl.state == 'uninitialized': if action is action_load: self._load_controller(ctrl.name) if action is action_spawn: self._load_controller(ctrl.name) self._start_controller(ctrl.name) def _on_ctrl_info(self, index): popup = self._popup_widget ctrl = self._controllers[index.row()] popup.ctrl_name.setText(ctrl.name) popup.ctrl_type.setText(ctrl.type) res_model = QStandardItemModel() model_root = QStandardItem('Claimed Resources') res_model.appendRow(model_root) for hw_res in ctrl.claimed_resources: hw_iface_item = QStandardItem(hw_res.hardware_interface) model_root.appendRow(hw_iface_item) for res in hw_res.resources: res_item = QStandardItem(res) hw_iface_item.appendRow(res_item) popup.resource_tree.setModel(res_model) popup.resource_tree.setItemDelegate(FontDelegate(popup.resource_tree)) popup.resource_tree.expandAll() popup.move(QCursor.pos()) popup.show() def _on_header_menu(self, pos): header = self._widget.table_view.horizontalHeader() # Show context menu menu = QMenu(self._widget.table_view) action_toggle_auto_resize = menu.addAction('Toggle Auto-Resize') action = menu.exec_(header.mapToGlobal(pos)) # Evaluate user action if action is action_toggle_auto_resize: if header.resizeMode(0) == QHeaderView.ResizeToContents: header.setSectionResizeMode(QHeaderView.Interactive) else: header.setSectionResizeMode(QHeaderView.ResizeToContents) def _load_controller(self, name): self._load_srv.call(LoadControllerRequest(name=name)) def _unload_controller(self, name): self._unload_srv.call(UnloadControllerRequest(name=name)) def _start_controller(self, name): strict = SwitchControllerRequest.STRICT req = SwitchControllerRequest(start_controllers=[name], stop_controllers=[], strictness=strict) self._switch_srv.call(req) def _stop_controller(self, name): strict = SwitchControllerRequest.STRICT req = SwitchControllerRequest(start_controllers=[], stop_controllers=[name], strictness=strict) self._switch_srv.call(req)
class RobotSteering(Plugin): slider_factor = 1000.0 def __init__(self, context): super(RobotSteering, self).__init__(context) self.setObjectName('RobotSteering') self._publisher = None self._widget = QWidget() rp = rospkg.RosPack() ui_file = os.path.join(rp.get_path('rqt_robot_steering'), 'resource', 'RobotSteering.ui') loadUi(ui_file, self._widget) self._widget.setObjectName('RobotSteeringUi') if context.serial_number() > 1: self._widget.setWindowTitle(self._widget.windowTitle() + (' (%d)' % context.serial_number())) context.add_widget(self._widget) self._widget.topic_line_edit.textChanged.connect(self._on_topic_changed) self._widget.stop_push_button.pressed.connect(self._on_stop_pressed) self._widget.x_linear_slider.valueChanged.connect(self._on_x_linear_slider_changed) self._widget.z_angular_slider.valueChanged.connect(self._on_z_angular_slider_changed) self._widget.increase_x_linear_push_button.pressed.connect(self._on_strong_increase_x_linear_pressed) self._widget.reset_x_linear_push_button.pressed.connect(self._on_reset_x_linear_pressed) self._widget.decrease_x_linear_push_button.pressed.connect(self._on_strong_decrease_x_linear_pressed) self._widget.increase_z_angular_push_button.pressed.connect(self._on_strong_increase_z_angular_pressed) self._widget.reset_z_angular_push_button.pressed.connect(self._on_reset_z_angular_pressed) self._widget.decrease_z_angular_push_button.pressed.connect(self._on_strong_decrease_z_angular_pressed) self._widget.max_x_linear_double_spin_box.valueChanged.connect(self._on_max_x_linear_changed) self._widget.min_x_linear_double_spin_box.valueChanged.connect(self._on_min_x_linear_changed) self._widget.max_z_angular_double_spin_box.valueChanged.connect(self._on_max_z_angular_changed) self._widget.min_z_angular_double_spin_box.valueChanged.connect(self._on_min_z_angular_changed) self.shortcut_w = QShortcut(QKeySequence(Qt.Key_W), self._widget) self.shortcut_w.setContext(Qt.ApplicationShortcut) self.shortcut_w.activated.connect(self._on_increase_x_linear_pressed) self.shortcut_x = QShortcut(QKeySequence(Qt.Key_X), self._widget) self.shortcut_x.setContext(Qt.ApplicationShortcut) self.shortcut_x.activated.connect(self._on_reset_x_linear_pressed) self.shortcut_s = QShortcut(QKeySequence(Qt.Key_S), self._widget) self.shortcut_s.setContext(Qt.ApplicationShortcut) self.shortcut_s.activated.connect(self._on_decrease_x_linear_pressed) self.shortcut_a = QShortcut(QKeySequence(Qt.Key_A), self._widget) self.shortcut_a.setContext(Qt.ApplicationShortcut) self.shortcut_a.activated.connect(self._on_increase_z_angular_pressed) self.shortcut_z = QShortcut(QKeySequence(Qt.Key_Z), self._widget) self.shortcut_z.setContext(Qt.ApplicationShortcut) self.shortcut_z.activated.connect(self._on_reset_z_angular_pressed) self.shortcut_d = QShortcut(QKeySequence(Qt.Key_D), self._widget) self.shortcut_d.setContext(Qt.ApplicationShortcut) self.shortcut_d.activated.connect(self._on_decrease_z_angular_pressed) self.shortcut_shift_w = QShortcut(QKeySequence(Qt.SHIFT + Qt.Key_W), self._widget) self.shortcut_shift_w.setContext(Qt.ApplicationShortcut) self.shortcut_shift_w.activated.connect(self._on_strong_increase_x_linear_pressed) self.shortcut_shift_x = QShortcut(QKeySequence(Qt.SHIFT + Qt.Key_X), self._widget) self.shortcut_shift_x.setContext(Qt.ApplicationShortcut) self.shortcut_shift_x.activated.connect(self._on_reset_x_linear_pressed) self.shortcut_shift_s = QShortcut(QKeySequence(Qt.SHIFT + Qt.Key_S), self._widget) self.shortcut_shift_s.setContext(Qt.ApplicationShortcut) self.shortcut_shift_s.activated.connect(self._on_strong_decrease_x_linear_pressed) self.shortcut_shift_a = QShortcut(QKeySequence(Qt.SHIFT + Qt.Key_A), self._widget) self.shortcut_shift_a.setContext(Qt.ApplicationShortcut) self.shortcut_shift_a.activated.connect(self._on_strong_increase_z_angular_pressed) self.shortcut_shift_z = QShortcut(QKeySequence(Qt.SHIFT + Qt.Key_Z), self._widget) self.shortcut_shift_z.setContext(Qt.ApplicationShortcut) self.shortcut_shift_z.activated.connect(self._on_reset_z_angular_pressed) self.shortcut_shift_d = QShortcut(QKeySequence(Qt.SHIFT + Qt.Key_D), self._widget) self.shortcut_shift_d.setContext(Qt.ApplicationShortcut) self.shortcut_shift_d.activated.connect(self._on_strong_decrease_z_angular_pressed) self.shortcut_space = QShortcut(QKeySequence(Qt.Key_Space), self._widget) self.shortcut_space.setContext(Qt.ApplicationShortcut) self.shortcut_space.activated.connect(self._on_stop_pressed) self.shortcut_space = QShortcut(QKeySequence(Qt.SHIFT + Qt.Key_Space), self._widget) self.shortcut_space.setContext(Qt.ApplicationShortcut) self.shortcut_space.activated.connect(self._on_stop_pressed) self._widget.stop_push_button.setToolTip(self._widget.stop_push_button.toolTip() + ' ' + self.tr('([Shift +] Space)')) self._widget.increase_x_linear_push_button.setToolTip(self._widget.increase_x_linear_push_button.toolTip() + ' ' + self.tr('([Shift +] W)')) self._widget.reset_x_linear_push_button.setToolTip(self._widget.reset_x_linear_push_button.toolTip() + ' ' + self.tr('([Shift +] X)')) self._widget.decrease_x_linear_push_button.setToolTip(self._widget.decrease_x_linear_push_button.toolTip() + ' ' + self.tr('([Shift +] S)')) self._widget.increase_z_angular_push_button.setToolTip(self._widget.increase_z_angular_push_button.toolTip() + ' ' + self.tr('([Shift +] A)')) self._widget.reset_z_angular_push_button.setToolTip(self._widget.reset_z_angular_push_button.toolTip() + ' ' + self.tr('([Shift +] Z)')) self._widget.decrease_z_angular_push_button.setToolTip(self._widget.decrease_z_angular_push_button.toolTip() + ' ' + self.tr('([Shift +] D)')) # timer to consecutively send twist messages self._update_parameter_timer = QTimer(self) self._update_parameter_timer.timeout.connect(self._on_parameter_changed) self._update_parameter_timer.start(100) self.zero_cmd_sent = False @Slot(str) def _on_topic_changed(self, topic): topic = str(topic) self._unregister_publisher() try: self._publisher = rospy.Publisher(topic, Twist, queue_size=10) except TypeError: self._publisher = rospy.Publisher(topic, Twist) def _on_stop_pressed(self): self._widget.x_linear_slider.setValue(0) self._widget.z_angular_slider.setValue(0) def _on_x_linear_slider_changed(self): self._widget.current_x_linear_label.setText('%0.2f m/s' % (self._widget.x_linear_slider.value() / RobotSteering.slider_factor)) self._on_parameter_changed() def _on_z_angular_slider_changed(self): self._widget.current_z_angular_label.setText('%0.2f rad/s' % (self._widget.z_angular_slider.value() / RobotSteering.slider_factor)) self._on_parameter_changed() def _on_increase_x_linear_pressed(self): self._widget.x_linear_slider.setValue(self._widget.x_linear_slider.value() + self._widget.x_linear_slider.singleStep()) def _on_reset_x_linear_pressed(self): self._widget.x_linear_slider.setValue(0) def _on_decrease_x_linear_pressed(self): self._widget.x_linear_slider.setValue(self._widget.x_linear_slider.value() - self._widget.x_linear_slider.singleStep()) def _on_increase_z_angular_pressed(self): self._widget.z_angular_slider.setValue(self._widget.z_angular_slider.value() + self._widget.z_angular_slider.singleStep()) def _on_reset_z_angular_pressed(self): self._widget.z_angular_slider.setValue(0) def _on_decrease_z_angular_pressed(self): self._widget.z_angular_slider.setValue(self._widget.z_angular_slider.value() - self._widget.z_angular_slider.singleStep()) def _on_max_x_linear_changed(self, value): self._widget.x_linear_slider.setMaximum(value * RobotSteering.slider_factor) def _on_min_x_linear_changed(self, value): self._widget.x_linear_slider.setMinimum(value * RobotSteering.slider_factor) def _on_max_z_angular_changed(self, value): self._widget.z_angular_slider.setMaximum(value * RobotSteering.slider_factor) def _on_min_z_angular_changed(self, value): self._widget.z_angular_slider.setMinimum(value * RobotSteering.slider_factor) def _on_strong_increase_x_linear_pressed(self): self._widget.x_linear_slider.setValue(self._widget.x_linear_slider.value() + self._widget.x_linear_slider.pageStep()) def _on_strong_decrease_x_linear_pressed(self): self._widget.x_linear_slider.setValue(self._widget.x_linear_slider.value() - self._widget.x_linear_slider.pageStep()) def _on_strong_increase_z_angular_pressed(self): self._widget.z_angular_slider.setValue(self._widget.z_angular_slider.value() + self._widget.z_angular_slider.pageStep()) def _on_strong_decrease_z_angular_pressed(self): self._widget.z_angular_slider.setValue(self._widget.z_angular_slider.value() - self._widget.z_angular_slider.pageStep()) def _on_parameter_changed(self): self._send_twist(self._widget.x_linear_slider.value() / RobotSteering.slider_factor, self._widget.z_angular_slider.value() / RobotSteering.slider_factor) def _send_twist(self, x_linear, z_angular): if self._publisher is None: return twist = Twist() twist.linear.x = x_linear twist.linear.y = 0 twist.linear.z = 0 twist.angular.x = 0 twist.angular.y = 0 twist.angular.z = z_angular # Only send the zero command once so other devices can take control if x_linear == 0 and z_angular == 0: if not self.zero_cmd_sent: self.zero_cmd_sent = True self._publisher.publish(twist) else: self.zero_cmd_sent = False self._publisher.publish(twist) def _unregister_publisher(self): if self._publisher is not None: self._publisher.unregister() self._publisher = None def shutdown_plugin(self): self._update_parameter_timer.stop() self._unregister_publisher() def save_settings(self, plugin_settings, instance_settings): instance_settings.set_value('topic' , self._widget.topic_line_edit.text()) instance_settings.set_value('vx_max', self._widget.max_x_linear_double_spin_box.value()) instance_settings.set_value('vx_min', self._widget.min_x_linear_double_spin_box.value()) instance_settings.set_value('vw_max', self._widget.max_z_angular_double_spin_box.value()) instance_settings.set_value('vw_min', self._widget.min_z_angular_double_spin_box.value()) def restore_settings(self, plugin_settings, instance_settings): value = instance_settings.value('topic', "/cmd_vel") value = rospy.get_param("~default_topic", value) self._widget.topic_line_edit.setText(value) value = self._widget.max_x_linear_double_spin_box.value() value = instance_settings.value( 'vx_max', value) value = rospy.get_param("~default_vx_max", value) self._widget.max_x_linear_double_spin_box.setValue(float(value)) value = self._widget.min_x_linear_double_spin_box.value() value = instance_settings.value( 'vx_min', value) value = rospy.get_param("~default_vx_min", value) self._widget.min_x_linear_double_spin_box.setValue(float(value)) value = self._widget.max_z_angular_double_spin_box.value() value = instance_settings.value( 'vw_max', value) value = rospy.get_param("~default_vw_max", value) self._widget.max_z_angular_double_spin_box.setValue(float(value)) value = self._widget.min_z_angular_double_spin_box.value() value = instance_settings.value( 'vw_min', value) value = rospy.get_param("~default_vw_min", value) self._widget.min_z_angular_double_spin_box.setValue(float(value))
def __init__(self, context): super(RosPackGraph, self).__init__(context) self.initialized = False self._current_dotcode = None self._update_thread = WorkerThread(self._update_thread_run, self._update_finished) self._nodes = {} self._edges = {} self._options = {} self._options_serialized = '' self.setObjectName('RosPackGraph') rospack = rospkg.RosPack() rosstack = rospkg.RosStack() # factory builds generic dotcode items self.dotcode_factory = PydotFactory() # self.dotcode_factory = PygraphvizFactory() # generator builds rosgraph self.dotcode_generator = RosPackageGraphDotcodeGenerator(rospack, rosstack) # dot_to_qt transforms into Qt elements using dot layout self.dot_to_qt = DotToQtGenerator() self._widget = QWidget() rp = rospkg.RosPack() ui_file = os.path.join(rp.get_path('rqt_dep'), 'resource', 'RosPackGraph.ui') loadUi(ui_file, self._widget, {'InteractiveGraphicsView': InteractiveGraphicsView}) self._widget.setObjectName('RosPackGraphUi') if context.serial_number() > 1: self._widget.setWindowTitle(self._widget.windowTitle() + (' (%d)' % context.serial_number())) self._scene = QGraphicsScene() self._scene.setBackgroundBrush(Qt.white) self._widget.graphics_view.setScene(self._scene) self._widget.depth_combo_box.insertItem(0, self.tr('infinite'), -1) self._widget.depth_combo_box.insertItem(1, self.tr('1'), 2) self._widget.depth_combo_box.insertItem(2, self.tr('2'), 3) self._widget.depth_combo_box.insertItem(3, self.tr('3'), 4) self._widget.depth_combo_box.insertItem(4, self.tr('4'), 5) self._widget.depth_combo_box.currentIndexChanged.connect(self._refresh_rospackgraph) self._widget.directions_combo_box.insertItem(0, self.tr('depends'), 0) self._widget.directions_combo_box.insertItem(1, self.tr('depends_on'), 1) self._widget.directions_combo_box.insertItem(2, self.tr('both'), 2) self._widget.directions_combo_box.currentIndexChanged.connect(self._refresh_rospackgraph) self._widget.package_type_combo_box.insertItem(0, self.tr('wet & dry'), 3) self._widget.package_type_combo_box.insertItem(1, self.tr('wet only'), 2) self._widget.package_type_combo_box.insertItem(2, self.tr('dry only'), 1) self._widget.package_type_combo_box.currentIndexChanged.connect(self._refresh_rospackgraph) completionmodel = StackageCompletionModel(self._widget.filter_line_edit, rospack, rosstack) completer = RepeatedWordCompleter(completionmodel, self) completer.setCompletionMode(QCompleter.PopupCompletion) completer.setWrapAround(True) completer.setCaseSensitivity(Qt.CaseInsensitive) self._widget.filter_line_edit.editingFinished.connect(self._refresh_rospackgraph) self._widget.filter_line_edit.setCompleter(completer) self._widget.filter_line_edit.selectionChanged.connect(self._clear_filter) self._widget.with_stacks_check_box.clicked.connect(self._refresh_rospackgraph) self._widget.mark_check_box.clicked.connect(self._refresh_rospackgraph) self._widget.colorize_check_box.clicked.connect(self._refresh_rospackgraph) self._widget.hide_transitives_check_box.clicked.connect(self._refresh_rospackgraph) self._widget.refresh_graph_push_button.setIcon(QIcon.fromTheme('view-refresh')) self._widget.refresh_graph_push_button.pressed.connect(self._update_rospackgraph) self._widget.highlight_connections_check_box.toggled.connect(self._refresh_rospackgraph) self._widget.auto_fit_graph_check_box.toggled.connect(self._refresh_rospackgraph) self._widget.fit_in_view_push_button.setIcon(QIcon.fromTheme('zoom-original')) self._widget.fit_in_view_push_button.pressed.connect(self._fit_in_view) self._widget.load_dot_push_button.setIcon(QIcon.fromTheme('document-open')) self._widget.load_dot_push_button.pressed.connect(self._load_dot) self._widget.save_dot_push_button.setIcon(QIcon.fromTheme('document-save-as')) self._widget.save_dot_push_button.pressed.connect(self._save_dot) self._widget.save_as_svg_push_button.setIcon(QIcon.fromTheme('document-save-as')) self._widget.save_as_svg_push_button.pressed.connect(self._save_svg) self._widget.save_as_image_push_button.setIcon(QIcon.fromTheme('image')) self._widget.save_as_image_push_button.pressed.connect(self._save_image) self._deferred_fit_in_view.connect(self._fit_in_view, Qt.QueuedConnection) self._deferred_fit_in_view.emit() context.add_widget(self._widget) # If in either of following case, this turnes True # - 1st filtering key is already input by user # - filtering key is restored self._filtering_started = False
class RqtLgsvlSimulatorConfiguratorPlugin(Plugin): def __init__(self, context): super(RqtLgsvlSimulatorConfiguratorPlugin, self).__init__(context) rospack = rospkg.RosPack() self.settings = QSettings(rospack.get_path('lgsvl_simulator_bridge')+"/config/setting.dat",QSettings.IniFormat) # Give QObjects reasonable names self.setObjectName('RqtLgsvlSimulatorConfiguratorPlugin') # Process standalone plugin command-line arguments from argparse import ArgumentParser parser = ArgumentParser() # Add argument(s) to the parser parser.add_argument("-q", "--quiet", action="store_true", dest="quiet", help="Put plugin in silent mode") args, unknowns = parser.parse_known_args(context.argv()) if not args.quiet: print 'arguments: ', args print 'unknowns: ', unknowns # Create QWidget self._widget = QWidget() # Get path to UI file which should be in the "resource" folder of this package ui_file = os.path.join(rospkg.RosPack().get_path('lgsvl_simulator_bridge'), 'resource', 'LgsvlSimulatorConfigratorPlugin.ui') # Extend the widget with all atrributes and children from UI File loadUi(ui_file, self._widget) # Give QObjects reasonable names self._widget.setObjectName('RqtLgsvlSimulatorConfiguratorPluginUi') # Show _widget.windowTitle on left-top of each plugin(when it's set in _widget). # This is useful when you open multiple plugins aat once. Also if you open multiple # instances of your plugin at once, these lines add number to make it easy to # tell from pane to pane. if context.serial_number() > 1: self._widget.setWindowTitle(self._widget.windowTitle() + (' %d' % context.serial_number())) # Add widget to the user interface self.settings.beginGroup("simulator_params") context.add_widget(self._widget) ip = self.settings.value('ip') if ip != None: self._widget.ip_box.setText(ip) port = self.settings.value('port') if port != None: self._widget.port_box.setText(port) config_path = self.settings.value('config_path') if config_path != None: self._widget.configpath_box.setText(config_path) self.settings.endGroup() self.json_dict = {} self.instance_id = "" self.is_remote = False self._widget.button_config_ref.clicked[bool].connect(self._handle_config_ref_button_clicked) self._widget.button_config.clicked[bool].connect(self._handle_config_button_clicked) self._widget.launch_button.clicked[bool].connect(self._handle_launch_button_clicked) self._widget.terminate_button.clicked[bool].connect(self._handle_terminate_button_clicked) def shutdown_plugin(self): # TODO unregister all publishers here pass def save_settings(self, plugin_settings, instance_settings): # TODO save intrinsic configuration, usually using: # instance_settings.get_value(k, v) pass def restore_settings(self, pluign_settings, instance_settings): # TODO restore intrinsic configuration, usually using: # v = instance_settings.value(k) pass def _handle_launch_button_clicked(self): if str(self._widget.ip_box.text()) == "localhost" or str(self._widget.ip_box.text()) == "0.0.0.0" or str(self._widget.ip_box.text()) == "127.0.0.1": cmd = ["roslaunch","lgsvl_simulator_bridge","lgsvl_simulator.launch"] self.proc = subprocess.Popen(cmd, stdout=subprocess.PIPE) self._widget.launch_button.setStyleSheet("background-color: #8fb8e0") self._widget.terminate_button.setStyleSheet("background-color: #FFFFFF") self.is_remote = False return else: cmd = ["roslaunch","lgsvl_simulator_bridge","bridge.launch"] self.proc = subprocess.Popen(cmd, stdout=subprocess.PIPE) address = "http://" + self._widget.ip_box.text() + ":" + self._widget.port_box.text()+"/simulator/launch" self.settings.beginGroup("simulator_params") self.settings.setValue("ip", self._widget.ip_box.text()) self.settings.setValue("port", self._widget.port_box.text()) self.settings.endGroup() try: response = requests.post(address,json=self.json_dict) self.instance_id = response.json()[u'instance_id'] except: self._widget.launch_button.setStyleSheet("background-color: #F5A9A9") return self.is_remote = False self._widget.launch_button.setStyleSheet("background-color: #8fb8e0") self._widget.terminate_button.setStyleSheet("background-color: #FFFFFF") def _handle_config_ref_button_clicked(self): rospack = rospkg.RosPack() fname = QFileDialog.getOpenFileName(self._widget, 'Open file', rospack.get_path('lgsvl_simulator_bridge')+'/config') self._widget.configpath_box.setText(fname[0]) def _handle_config_button_clicked(self): path = self._widget.configpath_box.text() try: f = open(path, "r+") self.json_dict = json.load(f) self.settings.beginGroup("simulator_params") self.settings.setValue("config_path", path) self.settings.endGroup() except: self._widget.button_config.setStyleSheet("background-color: #F5A9A9") return self._widget.button_config.setStyleSheet("background-color: #8fb8e0") def _handle_terminate_button_clicked(self): address = "http://" + self._widget.ip_box.text() + ":" + self._widget.port_box.text()+"/simulator/terminate" self.settings.beginGroup("simulator_params") self.settings.setValue("ip", self._widget.ip_box.text()) self.settings.setValue("port", self._widget.port_box.text()) self.settings.endGroup() if self.instance_id == "" and self.is_remote == True: return if self.is_remote == True: try: response = requests.post(address,json={u'instance_id':self.instance_id}) except: self._widget.terminate_button.setStyleSheet("background-color: #F5A9A9") return try: self.proc.terminate() except: self._widget.terminate_button.setStyleSheet("background-color: #F5A9A9") return self._widget.terminate_button.setStyleSheet("background-color: #8fb8e0") self._widget.launch_button.setStyleSheet("background-color: #FFFFFF")
def __init__(self, context): super(Top, self).__init__(context) # Give QObjects reasonable names self.setObjectName('Top') # Process standalone plugin command-line arguments from argparse import ArgumentParser parser = ArgumentParser() # Add argument(s) to the parser. parser.add_argument("-q", "--quiet", action="store_true", dest="quiet", help="Put plugin in silent mode") args, unknowns = parser.parse_known_args(context.argv()) # if not args.quiet: # print 'arguments: ', args # print 'unknowns: ', unknowns self._selected_node = '' self._selected_node_lock = RLock() # Setup the toolbar self._toolbar = QToolBar() self._filter_box = QLineEdit() self._regex_box = QCheckBox() self._regex_box.setText('regex') self._toolbar.addWidget(QLabel('Filter')) self._toolbar.addWidget(self._filter_box) self._toolbar.addWidget(self._regex_box) self._filter_box.returnPressed.connect(self.update_filter) self._regex_box.stateChanged.connect(self.update_filter) # Create a container widget and give it a layout self._container = QWidget() self._container.setWindowTitle('Process Monitor') self._layout = QVBoxLayout() self._container.setLayout(self._layout) self._layout.addWidget(self._toolbar) # Create the table widget self._table_widget = QTreeWidget() self._table_widget.setObjectName('TopTable') self._table_widget.setColumnCount(len(self.NODE_LABELS)) self._table_widget.setHeaderLabels(self.NODE_LABELS) self._table_widget.itemClicked.connect(self._tableItemClicked) self._table_widget.setSortingEnabled(True) self._table_widget.setAlternatingRowColors(True) self._layout.addWidget(self._table_widget) context.add_widget(self._container) # Add a button for killing nodes self._kill_button = QPushButton('Kill Node') self._layout.addWidget(self._kill_button) self._kill_button.clicked.connect(self._kill_node) # Update twice since the first cpu% lookup will always return 0 self.update_table() self.update_table() self._table_widget.resizeColumnToContents(0) # Start a timer to trigger updates self._update_timer = QTimer() self._update_timer.setInterval(1000) self._update_timer.timeout.connect(self.update_table) self._update_timer.start()
def __init__(self, context, node=None): """ This class is intended to be called by rqt plugin framework class. Currently (12/12/2012) the whole widget is splitted into 2 panes: one on left allows you to choose the node(s) you work on. Right side pane lets you work with the parameters associated with the node(s) you select on the left. (12/27/2012) Despite the pkg name is changed to rqt_reconfigure to reflect the available functionality, file & class names remain 'param', expecting all the parameters will become handle-able. """ super(ParamWidget, self).__init__() self.setObjectName(self._TITLE_PLUGIN) self.setWindowTitle(self._TITLE_PLUGIN) rp = rospkg.RosPack() #TODO: .ui file needs to replace the GUI components declaration # below. For unknown reason, referring to another .ui files # from a .ui that is used in this class failed. So for now, # I decided not use .ui in this class. # If someone can tackle this I'd appreciate. _hlayout_top = QHBoxLayout(self) _hlayout_top.setContentsMargins(QMargins(0, 0, 0, 0)) self._splitter = QSplitter(self) _hlayout_top.addWidget(self._splitter) _vlayout_nodesel_widget = QWidget() _vlayout_nodesel_side = QVBoxLayout() _hlayout_filter_widget = QWidget(self) _hlayout_filter = QHBoxLayout() self._text_filter = TextFilter() self.filter_lineedit = TextFilterWidget(self._text_filter, rp) self.filterkey_label = QLabel("&Filter key:") self.filterkey_label.setBuddy(self.filter_lineedit) _hlayout_filter.addWidget(self.filterkey_label) _hlayout_filter.addWidget(self.filter_lineedit) _hlayout_filter_widget.setLayout(_hlayout_filter) self._nodesel_widget = NodeSelectorWidget(self, rp, self.sig_sysmsg) _vlayout_nodesel_side.addWidget(_hlayout_filter_widget) _vlayout_nodesel_side.addWidget(self._nodesel_widget) _vlayout_nodesel_side.setSpacing(1) _vlayout_nodesel_widget.setLayout(_vlayout_nodesel_side) reconf_widget = ParameditWidget(rp) self._splitter.insertWidget(0, _vlayout_nodesel_widget) self._splitter.insertWidget(1, reconf_widget) # 1st column, _vlayout_nodesel_widget, to minimize width. # 2nd col to keep the possible max width. self._splitter.setStretchFactor(0, 0) self._splitter.setStretchFactor(1, 1) # Signal from paramedit widget to node selector widget. reconf_widget.sig_node_disabled_selected.connect( self._nodesel_widget.node_deselected) # Pass name of node to editor widget self._nodesel_widget.sig_node_selected.connect( reconf_widget.show_reconf) if not node: title = self._TITLE_PLUGIN else: title = self._TITLE_PLUGIN + ' %s' % node self.setObjectName(title) #Connect filter signal-slots. self._text_filter.filter_changed_signal.connect( self._filter_key_changed) # Open any clients indicated from command line self.sig_selected.connect(self._nodesel_widget.node_selected) for rn in [rospy.resolve_name(c) for c in context.argv()]: if rn in self._nodesel_widget.get_paramitems(): self.sig_selected.emit(rn) else: rospy.logwarn('Could not find a dynamic reconfigure client named \'%s\'', str(rn))
class PyConsole(Plugin): """ Plugin providing an interactive Python console """ def __init__(self, context): super(PyConsole, self).__init__(context) self.setObjectName('PyConsole') self._context = context self._use_spyderlib = _has_spyderlib self._console_widget = None self._widget = QWidget() self._widget.setLayout(QVBoxLayout()) self._widget.layout().setContentsMargins(0, 0, 0, 0) if context.serial_number() > 1: self._widget.setWindowTitle(self._widget.windowTitle() + (' (%d)' % context.serial_number())) self._context.add_widget(self._widget) def _switch_console_widget(self): self._widget.layout().removeWidget(self._console_widget) self.shutdown_console_widget() if _has_spyderlib and self._use_spyderlib: self._console_widget = SpyderConsoleWidget(self._context) self._widget.setWindowTitle('SpyderConsole') else: self._console_widget = PyConsoleWidget(self._context) self._widget.setWindowTitle('PyConsole') if self._context.serial_number() > 1: self._widget.setWindowTitle(self._widget.windowTitle() + (' (%d)' % self._context.serial_number())) self._widget.layout().addWidget(self._console_widget) def save_settings(self, plugin_settings, instance_settings): instance_settings.set_value('use_spyderlib', self._use_spyderlib) def restore_settings(self, plugin_settings, instance_settings): self._use_spyderlib = _has_spyderlib and (instance_settings.value('use_spyderlib', True) in [True, 'true']) self._switch_console_widget() def trigger_configuration(self): options = [ {'title': 'SpyderConsole', 'description': 'Advanced Python console with tab-completion (needs spyderlib to be installed).', 'enabled': _has_spyderlib}, {'title': 'PyConsole', 'description': 'Simple Python console.'}, ] dialog = SimpleSettingsDialog(title='PyConsole Options') dialog.add_exclusive_option_group(title='Console Type', options=options, selected_index=int(not self._use_spyderlib)) console_type = dialog.get_settings()[0] new_use_spyderlib = {0: True, 1: False}.get(console_type['selected_index'], self._use_spyderlib) if self._use_spyderlib != new_use_spyderlib: self._use_spyderlib = new_use_spyderlib self._switch_console_widget() def shutdown_console_widget(self): if self._console_widget is not None and hasattr(self._console_widget, 'shutdown'): self._console_widget.shutdown() def shutdown_plugin(self): self.shutdown_console_widget()
class TopicSelection(QWidget): recordSettingsSelected = Signal(bool, list) def __init__(self): super(TopicSelection, self).__init__() master = rosgraph.Master('rqt_bag_recorder') self.setWindowTitle("Select the topics you want to record") self.resize(500, 700) self.topic_list = [] self.selected_topics = [] self.items_list = [] self.area = QScrollArea(self) self.main_widget = QWidget(self.area) self.ok_button = QPushButton("Record", self) self.ok_button.clicked.connect(self.onButtonClicked) self.ok_button.setEnabled(False) self.main_vlayout = QVBoxLayout(self) self.main_vlayout.addWidget(self.area) self.main_vlayout.addWidget(self.ok_button) self.setLayout(self.main_vlayout) self.selection_vlayout = QVBoxLayout(self) self.item_all = QCheckBox("All", self) self.item_all.stateChanged.connect(self.updateList) self.selection_vlayout.addWidget(self.item_all) topic_data_list = master.getPublishedTopics('') topic_data_list.sort() for topic, datatype in topic_data_list: self.addCheckBox(topic) self.main_widget.setLayout(self.selection_vlayout) self.area.setWidget(self.main_widget) self.show() def addCheckBox(self, topic): self.topic_list.append(topic) item = QCheckBox(topic, self) item.stateChanged.connect(lambda x: self.updateList(x,topic)) self.items_list.append(item) self.selection_vlayout.addWidget(item) def updateList(self, state, topic = None): if topic is None: # The "All" checkbox was checked / unchecked if state == Qt.Checked: self.item_all.setTristate(False) for item in self.items_list: if item.checkState() == Qt.Unchecked: item.setCheckState(Qt.Checked) elif state == Qt.Unchecked: self.item_all.setTristate(False) for item in self.items_list: if item.checkState() == Qt.Checked: item.setCheckState(Qt.Unchecked) else: if state == Qt.Checked: self.selected_topics.append(topic) else: self.selected_topics.remove(topic) if self.item_all.checkState()==Qt.Checked: self.item_all.setCheckState(Qt.PartiallyChecked) if self.selected_topics == []: self.ok_button.setEnabled(False) else: self.ok_button.setEnabled(True) def onButtonClicked(self): self.close() self.recordSettingsSelected.emit((self.item_all.checkState() == Qt.Checked), self.selected_topics)