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'),
83 if context.serial_number() > 1:
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'),
106 'initialized': QIcon(path +
'/resource/led_red.png')}
109 table_view = self.
_widget.table_view
110 table_view.setContextMenuPolicy(Qt.CustomContextMenu)
111 table_view.customContextMenuRequested.connect(self.
_on_ctrl_menu)
115 header = table_view.horizontalHeader()
116 header.setSectionResizeMode(QHeaderView.ResizeToContents)
117 header.setContextMenuPolicy(Qt.CustomContextMenu)
137 w.cm_combo.currentIndexChanged[str].connect(self.
_on_cm_change)
145 instance_settings.set_value(
'cm_ns', self.
_cm_ns)
150 cm_ns = instance_settings.value(
'cm_ns')
151 cm_combo = self.
_widget.cm_combo
152 cm_list = [cm_combo.itemText(i)
for i
in range(cm_combo.count())]
154 idx = cm_list.index(cm_ns)
155 cm_combo.setCurrentIndex(idx)
186 load_srv_name =
_append_ns(cm_ns,
'load_controller')
187 self.
_load_srv = rospy.ServiceProxy(load_srv_name,
190 unload_srv_name =
_append_ns(cm_ns,
'unload_controller')
191 self.
_unload_srv = rospy.ServiceProxy(unload_srv_name,
194 switch_srv_name =
_append_ns(cm_ns,
'switch_controller')
195 self.
_switch_srv = rospy.ServiceProxy(switch_srv_name,
214 @return List of controllers associated to a controller manager 215 namespace. Contains both stopped/running controllers, as returned by 216 the C{list_controllers} service, plus uninitialized controllers with 217 configurations loaded in the parameter server. 228 for name
in get_rosparam_controller_names(all_ctrls_ns):
229 add_ctrl =
not any(name == ctrl.name
for ctrl
in controllers)
232 uninit_ctrl = ControllerState(name=name,
234 state=
'uninitialized')
235 controllers.append(uninit_ctrl)
239 table_view = self.
_widget.table_view
245 row = self.
_widget.table_view.rowAt(pos.y())
252 menu = QMenu(self.
_widget.table_view)
253 if ctrl.state ==
'running':
254 action_stop = menu.addAction(self.
_icons[
'stopped'],
'Stop')
255 action_kill = menu.addAction(self.
_icons[
'uninitialized'],
257 elif ctrl.state ==
'stopped':
258 action_start = menu.addAction(self.
_icons[
'running'],
260 action_unload = menu.addAction(self.
_icons[
'uninitialized'],
262 elif ctrl.state ==
'initialized':
263 action_start = menu.addAction(self.
_icons[
'running'],
'Start')
264 action_unload = menu.addAction(self.
_icons[
'uninitialized'],
266 elif ctrl.state ==
'uninitialized':
267 action_load = menu.addAction(self.
_icons[
'stopped'],
'Load')
268 action_spawn = menu.addAction(self.
_icons[
'running'],
271 action = menu.exec_(self.
_widget.table_view.mapToGlobal(pos))
274 if ctrl.state ==
'running':
275 if action
is action_stop:
277 elif action
is action_kill:
280 elif ctrl.state ==
'stopped' or ctrl.state ==
'initialized':
281 if action
is action_start:
283 elif action
is action_unload:
285 elif ctrl.state ==
'uninitialized':
286 if action
is action_load:
288 if action
is action_spawn:
296 popup.ctrl_name.setText(ctrl.name)
297 popup.ctrl_type.setText(ctrl.type)
299 res_model = QStandardItemModel()
300 model_root = QStandardItem(
'Claimed Resources')
301 res_model.appendRow(model_root)
302 for hw_res
in ctrl.claimed_resources:
303 hw_iface_item = QStandardItem(hw_res.hardware_interface)
304 model_root.appendRow(hw_iface_item)
305 for res
in hw_res.resources:
306 res_item = QStandardItem(res)
307 hw_iface_item.appendRow(res_item)
309 popup.resource_tree.setModel(res_model)
310 popup.resource_tree.setItemDelegate(
FontDelegate(popup.resource_tree))
311 popup.resource_tree.expandAll()
312 popup.move(QCursor.pos())
316 header = self.
_widget.table_view.horizontalHeader()
319 menu = QMenu(self.
_widget.table_view)
320 action_toggle_auto_resize = menu.addAction(
'Toggle Auto-Resize')
321 action = menu.exec_(header.mapToGlobal(pos))
324 if action
is action_toggle_auto_resize:
325 if header.resizeMode(0) == QHeaderView.ResizeToContents:
326 header.setSectionResizeMode(QHeaderView.Interactive)
328 header.setSectionResizeMode(QHeaderView.ResizeToContents)
331 self.
_load_srv.call(LoadControllerRequest(name=name))
334 self.
_unload_srv.call(UnloadControllerRequest(name=name))
337 strict = SwitchControllerRequest.STRICT
338 req = SwitchControllerRequest(start_controllers=[name],
344 strict = SwitchControllerRequest.STRICT
345 req = SwitchControllerRequest(start_controllers=[],
346 stop_controllers=[name],
353 Model containing controller information for tabular display. 355 The model allows display of basic read-only information like controller 358 def __init__(self, controller_info, icons, parent=None):
359 QAbstractTableModel.__init__(self, parent)
364 return len(self.
_data)
370 if orientation == Qt.Horizontal
and role == Qt.DisplayRole:
379 if not index.isValid():
382 ctrl = self.
_data[index.row()]
384 if role == Qt.DisplayRole:
385 if index.column() == 0:
387 elif index.column() == 1:
390 if role == Qt.DecorationRole:
391 if index.column() == 0:
392 return self.
_icons[ctrl.state]
394 if role == Qt.FontRole:
395 if index.column() == 0:
400 if role == Qt.TextAlignmentRole:
401 if index.column() == 1:
402 return Qt.AlignCenter
407 Simple delegate for customizing font weight and italization when 408 displaying resources claimed by a controller 410 def paint(self, painter, option, index):
411 if not index.parent().isValid():
413 option.font.setWeight(QFont.Bold)
414 if index.parent().isValid()
and not index.parent().parent().isValid():
416 option.font.setItalic(
True)
417 option.font.setWeight(QFont.Bold)
418 QStyledItemDelegate.paint(self, painter, option, index)
423 Resolve the namespace containing controller configurations from that of 424 the controller manager. 425 Controllers are assumed to live one level above the controller 428 >>> _resolve_controller_ns('/path/to/controller_manager') 431 In the particular case in which the controller manager is not 432 namespaced, the controller is assumed to live in the root namespace 434 >>> _resolve_controller_ns('/') 436 >>> _resolve_controller_ns('') 438 @param cm_ns Controller manager namespace (can be an empty string) 440 @return Controllers namespace 443 ns = cm_ns.rsplit(
'/', 1)[0]
451 Append a sub-namespace (suffix) to the input namespace 452 @param in_ns Input namespace 454 @return Suffix namespace 466 Get a controller's type from its ROS parameter server configuration 467 @param ctrls_ns Namespace where controllers should be located 469 @param ctrl_name Controller name 471 @return Controller type 474 type_param =
_append_ns(ctrls_ns, ctrl_name) +
'/type' 475 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)