32 from python_qt_binding
import loadUi
33 from python_qt_binding.QtCore
import QAbstractTableModel, QModelIndex, Qt,\
34 QTimer, QVariant, Signal
35 from python_qt_binding.QtWidgets
import QWidget, QFormLayout, QHeaderView,\
36 QMenu, QStyledItemDelegate
37 from python_qt_binding.QtGui
import QCursor, QFont, QIcon, QStandardItem,\
41 from controller_manager_msgs.msg
import ControllerState
43 from controller_manager_msgs.utils\
44 import ControllerLister, ControllerManagerLister,\
45 get_rosparam_controller_names
47 from update_combo
import update_combo
52 Graphical frontend for managing ros_control controllers. 57 super(ControllerManager, self).
__init__(context)
58 self.setObjectName(
'ControllerManager')
64 ui_file = os.path.join(rp.get_path(
'rqt_controller_manager'),
66 'controller_manager.ui')
68 self._widget.setObjectName(
'ControllerManagerUi')
72 ui_file = os.path.join(rp.get_path(
'rqt_controller_manager'),
76 self._popup_widget.setObjectName(
'ControllerInfoUi')
83 if context.serial_number() > 1:
84 self._widget.setWindowTitle(self._widget.windowTitle() +
85 (
' (%d)' % context.serial_number()))
87 context.add_widget(self.
_widget)
101 rospack = rospkg.RosPack()
102 path = rospack.get_path(
'rqt_controller_manager')
103 self.
_icons = {
'running': QIcon(path +
'/resource/led_green.png'),
104 'stopped': QIcon(path +
'/resource/led_red.png'),
105 'uninitialized': QIcon(path +
'/resource/led_off.png')}
108 table_view = self._widget.table_view
109 table_view.setContextMenuPolicy(Qt.CustomContextMenu)
110 table_view.customContextMenuRequested.connect(self.
_on_ctrl_menu)
114 header = table_view.horizontalHeader()
115 header.setSectionResizeMode(QHeaderView.ResizeToContents)
116 header.setContextMenuPolicy(Qt.CustomContextMenu)
122 self._update_cm_list_timer.setInterval(1000.0 /
125 self._update_cm_list_timer.start()
129 self._update_ctrl_list_timer.setInterval(1000.0 /
132 self._update_ctrl_list_timer.start()
136 w.cm_combo.currentIndexChanged[str].connect(self.
_on_cm_change)
139 self._update_cm_list_timer.stop()
140 self._update_ctrl_list_timer.stop()
141 self._popup_widget.hide()
144 instance_settings.set_value(
'cm_ns', self.
_cm_ns)
149 cm_ns = instance_settings.value(
'cm_ns')
150 cm_combo = self._widget.cm_combo
151 cm_list = [cm_combo.itemText(i)
for i
in range(cm_combo.count())]
153 idx = cm_list.index(cm_ns)
154 cm_combo.setCurrentIndex(idx)
185 load_srv_name =
_append_ns(cm_ns,
'load_controller')
186 self.
_load_srv = rospy.ServiceProxy(load_srv_name,
189 unload_srv_name =
_append_ns(cm_ns,
'unload_controller')
190 self.
_unload_srv = rospy.ServiceProxy(unload_srv_name,
193 switch_srv_name =
_append_ns(cm_ns,
'switch_controller')
194 self.
_switch_srv = rospy.ServiceProxy(switch_srv_name,
213 @return List of controllers associated to a controller manager 214 namespace. Contains both stopped/running controllers, as returned by 215 the C{list_controllers} service, plus uninitialized controllers with 216 configurations loaded in the parameter server. 227 for name
in get_rosparam_controller_names(all_ctrls_ns):
228 add_ctrl =
not any(name == ctrl.name
for ctrl
in controllers)
231 uninit_ctrl = ControllerState(name=name,
233 state=
'uninitialized')
234 controllers.append(uninit_ctrl)
238 table_view = self._widget.table_view
244 row = self._widget.table_view.rowAt(pos.y())
251 menu = QMenu(self._widget.table_view)
252 if ctrl.state ==
'running':
253 action_stop = menu.addAction(self.
_icons[
'stopped'],
'Stop')
254 action_kill = menu.addAction(self.
_icons[
'uninitialized'],
256 elif ctrl.state ==
'stopped':
257 action_start = menu.addAction(self.
_icons[
'running'],
'Start')
258 action_unload = menu.addAction(self.
_icons[
'uninitialized'],
260 elif ctrl.state ==
'uninitialized':
261 action_load = menu.addAction(self.
_icons[
'stopped'],
'Load')
262 action_spawn = menu.addAction(self.
_icons[
'running'],
265 action = menu.exec_(self._widget.table_view.mapToGlobal(pos))
268 if ctrl.state ==
'running':
269 if action
is action_stop:
271 elif action
is action_kill:
274 elif ctrl.state ==
'stopped':
275 if action
is action_start:
277 elif action
is action_unload:
279 elif ctrl.state ==
'uninitialized':
280 if action
is action_load:
282 if action
is action_spawn:
290 popup.ctrl_name.setText(ctrl.name)
291 popup.ctrl_type.setText(ctrl.type)
293 res_model = QStandardItemModel()
294 model_root = QStandardItem(
'Claimed Resources')
295 res_model.appendRow(model_root)
296 for hw_res
in ctrl.claimed_resources:
297 hw_iface_item = QStandardItem(hw_res.hardware_interface)
298 model_root.appendRow(hw_iface_item)
299 for res
in hw_res.resources:
300 res_item = QStandardItem(res)
301 hw_iface_item.appendRow(res_item)
303 popup.resource_tree.setModel(res_model)
304 popup.resource_tree.setItemDelegate(
FontDelegate(popup.resource_tree))
305 popup.resource_tree.expandAll()
306 popup.move(QCursor.pos())
310 header = self._widget.table_view.horizontalHeader()
313 menu = QMenu(self._widget.table_view)
314 action_toggle_auto_resize = menu.addAction(
'Toggle Auto-Resize')
315 action = menu.exec_(header.mapToGlobal(pos))
318 if action
is action_toggle_auto_resize:
319 if header.resizeMode(0) == QHeaderView.ResizeToContents:
320 header.setSectionResizeMode(QHeaderView.Interactive)
322 header.setSectionResizeMode(QHeaderView.ResizeToContents)
325 self._load_srv.call(LoadControllerRequest(name=name))
328 self._unload_srv.call(UnloadControllerRequest(name=name))
331 strict = SwitchControllerRequest.STRICT
332 req = SwitchControllerRequest(start_controllers=[name],
335 self._switch_srv.call(req)
338 strict = SwitchControllerRequest.STRICT
339 req = SwitchControllerRequest(start_controllers=[],
340 stop_controllers=[name],
342 self._switch_srv.call(req)
347 Model containing controller information for tabular display. 349 The model allows display of basic read-only information like controller 352 def __init__(self, controller_info, icons, parent=None):
353 QAbstractTableModel.__init__(self, parent)
358 return len(self.
_data)
364 if orientation == Qt.Horizontal
and role == Qt.DisplayRole:
373 if not index.isValid():
376 ctrl = self.
_data[index.row()]
378 if role == Qt.DisplayRole:
379 if index.column() == 0:
381 elif index.column() == 1:
384 if role == Qt.DecorationRole:
385 if index.column() == 0:
386 return self.
_icons[ctrl.state]
388 if role == Qt.FontRole:
389 if index.column() == 0:
394 if role == Qt.TextAlignmentRole:
395 if index.column() == 1:
396 return Qt.AlignCenter
401 Simple delegate for customizing font weight and italization when 402 displaying resources claimed by a controller 404 def paint(self, painter, option, index):
405 if not index.parent().isValid():
407 option.font.setWeight(QFont.Bold)
408 if index.parent().isValid()
and not index.parent().parent().isValid():
410 option.font.setItalic(
True)
411 option.font.setWeight(QFont.Bold)
412 QStyledItemDelegate.paint(self, painter, option, index)
417 Resolve the namespace containing controller configurations from that of 418 the controller manager. 419 Controllers are assumed to live one level above the controller 422 >>> _resolve_controller_ns('/path/to/controller_manager') 425 In the particular case in which the controller manager is not 426 namespaced, the controller is assumed to live in the root namespace 428 >>> _resolve_controller_ns('/') 430 >>> _resolve_controller_ns('') 432 @param cm_ns Controller manager namespace (can be an empty string) 434 @return Controllers namespace 437 ns = cm_ns.rsplit(
'/', 1)[0]
445 Append a sub-namespace (suffix) to the input namespace 446 @param in_ns Input namespace 448 @return Suffix namespace 460 Get a controller's type from its ROS parameter server configuration 461 @param ctrls_ns Namespace where controllers should be located 463 @param ctrl_name Controller name 465 @return Controller type 468 type_param =
_append_ns(ctrls_ns, ctrl_name) +
'/type' 469 return rospy.get_param(type_param)
def _unload_controller(self, name)
def rowCount(self, parent)
def shutdown_plugin(self)
def _resolve_controllers_ns(cm_ns)
def _set_cm_services(self, cm_ns)
def _start_controller(self, name)
def _on_cm_change(self, cm_ns)
def _load_controller(self, name)
def __init__(self, controller_info, icons, parent=None)
def _on_ctrl_info(self, index)
def paint(self, painter, option, index)
def _list_controllers(self)
def _append_ns(in_ns, suffix)
def _on_header_menu(self, pos)
def columnCount(self, parent)
def _on_ctrl_menu(self, pos)
def _update_cm_list(self)
def _update_controllers(self)
def _show_controllers(self)
def __init__(self, context)
def headerData(self, col, orientation, role)
def data(self, index, role)
def save_settings(self, plugin_settings, instance_settings)
def update_combo(combo, new_vals)
def _rosparam_controller_type(ctrls_ns, ctrl_name)
def _stop_controller(self, name)
def restore_settings(self, plugin_settings, instance_settings)