00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019 import os
00020
00021 import roslib
00022 roslib.load_manifest('sr_gui_joint_slider')
00023 import rospy
00024
00025 from qt_gui.plugin import Plugin
00026 from python_qt_binding import loadUi
00027
00028
00029 from xml.etree import ElementTree as ET
00030
00031 from PyQt4 import QtCore, QtGui, Qt
00032 from QtGui import QShortcut, QMessageBox, QFrame
00033 from pr2_mechanism_msgs.srv import ListControllers, SwitchController, LoadController
00034 from sr_robot_msgs.msg import sendupdate, joint
00035 from std_msgs.msg import Float64
00036 from math import radians, degrees
00037
00038 class JointController():
00039 """
00040 Contains the min and the max and the command and state topics for the joint controller.
00041 """
00042 def __init__(self, name, command_topic, msg_type, min=0, max=90):
00043 self.name = name
00044 self.command_topic = command_topic
00045 self.msg_type = msg_type
00046 self.min = min
00047 self.max = max
00048
00049 class Joint():
00050 """
00051 Contains the name, and a controllers list for the joint.
00052 """
00053 def __init__(self, name="", joint_controller_list=None):
00054 self.name = name
00055 self.controller_list = joint_controller_list
00056
00057 class ExtendedSlider(QFrame):
00058 """
00059 This slider displays the current position and the target as well.
00060 """
00061 def __init__(self, joint, uiFile, robot_lib, plugin_parent, parent=None):
00062 QFrame.__init__(self, parent)
00063 ui_file = os.path.join(os.path.dirname(os.path.realpath(__file__)), uiFile)
00064 loadUi(ui_file, self)
00065
00066 self.robot_lib = robot_lib
00067
00068 self.plugin_parent = plugin_parent
00069 self.joint = joint
00070 self.current_controller_index = -1
00071 self.label.setText(joint.name)
00072 self.current_value = 0
00073
00074 self.slider.setFocusPolicy(QtCore.Qt.NoFocus)
00075 self.slider.setTracking(True)
00076 self.pos_slider_tracking_behaviour = True
00077 self.is_selected = False
00078 self.first_update_done = False
00079
00080 if len(self.joint.controller_list) > 1:
00081 self.slider.setMinimum(0)
00082 self.slider.setMaximum(10)
00083 self.min_label.setText("Unknown")
00084 self.max_label.setText("Unknown")
00085 elif len(self.joint.controller_list) == 1:
00086 self.current_controller_index = 0
00087 self.slider.setMinimum(joint.controller_list[self.current_controller_index].min)
00088 self.slider.setMaximum(joint.controller_list[self.current_controller_index].max)
00089 self.min_label.setText(str(joint.controller_list[self.current_controller_index].min))
00090 self.max_label.setText(str(joint.controller_list[self.current_controller_index].max))
00091 else:
00092 rospy.logwarn("No controllers defined for this joint")
00093
00094 self.connect(self.selected, QtCore.SIGNAL('stateChanged(int)'), self.checkbox_click)
00095 self.connect(self.slider, QtCore.SIGNAL('valueChanged(int)'), self.changeValue)
00096
00097 self.timer = Qt.QTimer(self)
00098 self.connect(self.timer, QtCore.SIGNAL('timeout()'), self.update)
00099 self.timer.start(200)
00100
00101 def changeValue(self, value):
00102 self.target.setText("Tgt: " + str(value))
00103 self.sendupdate(value)
00104
00105 def sendupdate(self, value):
00106 raise NotImplementedError, "Virtual method, please implement."
00107
00108 def update(self):
00109 raise NotImplementedError, "Virtual method, please implement."
00110
00111 def refresh(self):
00112 raise NotImplementedError, "Virtual method, please implement."
00113
00114 def checkbox_click(self, value):
00115 self.is_selected = value
00116
00117 def set_slider_behaviour(self):
00118 raise NotImplementedError, "Virtual method, please implement."
00119
00120 def set_new_slider_behaviour(self, tracking):
00121 if tracking:
00122 self.pos_slider_tracking_behaviour = True
00123 else:
00124 self.pos_slider_tracking_behaviour = False
00125 self.set_slider_behaviour()
00126
00127
00128 class EtherCATHandSlider(ExtendedSlider):
00129 """
00130 Slider for the EtherCAT Hand.
00131 """
00132 def __init__(self, joint, uiFile, robot_lib, plugin_parent, parent=None):
00133 ExtendedSlider.__init__(self, joint, uiFile, robot_lib, plugin_parent, parent)
00134
00135 self.initialize_controller()
00136
00137 def initialize_controller(self):
00138 self.current_controller_index = self.get_current_joint_controller(self.get_current_controllers())
00139
00140 if (self.current_controller_index == -1):
00141 raise Exception("No controller found for joint: " + self.joint.name)
00142 else:
00143 self.slider.setMinimum(self.joint.controller_list[self.current_controller_index].min)
00144 self.slider.setMaximum(self.joint.controller_list[self.current_controller_index].max)
00145 self.min_label.setText(str(self.joint.controller_list[self.current_controller_index].min))
00146 self.max_label.setText(str(self.joint.controller_list[self.current_controller_index].max))
00147
00148 self.pub = rospy.Publisher(self.joint.controller_list[self.current_controller_index].command_topic, Float64, latch=True)
00149 self.set_slider_behaviour()
00150
00151 def get_current_joint_controller(self, current_controllers):
00152 for index, joint_controller in enumerate(self.joint.controller_list):
00153 for controller in current_controllers:
00154 if (controller.find(self.joint.name.lower() + '_' + joint_controller.name) != -1):
00155 return index
00156 return -1
00157
00158 def get_current_controllers(self):
00159 success = True
00160 list_controllers = rospy.ServiceProxy('pr2_controller_manager/list_controllers', ListControllers)
00161 try:
00162 resp1 = list_controllers()
00163 except rospy.ServiceException:
00164 success = False
00165
00166 current_controllers = []
00167
00168 if success:
00169 all_loaded_controllers = resp1.controllers
00170 for state,tmp_contrl in zip(resp1.state,resp1.controllers):
00171 if state == "running":
00172 current_controllers.append(tmp_contrl)
00173 else:
00174 rospy.loginfo("Couldn't get list of controllers from pr2_controller_manager/list_controllers service")
00175
00176 return current_controllers
00177
00178 def sendupdate(self, value):
00179 if (self.current_controller_index == -1):
00180 self.initialize_controller()
00181
00182 if (self.current_controller_index != -1):
00183 if (self.joint.controller_list[self.current_controller_index].name == "mixed_position_velocity") or (self.joint.controller_list[self.current_controller_index].name == "position"):
00184 self.pub.publish(radians(float(value)))
00185 elif self.joint.controller_list[self.current_controller_index].name == "velocity":
00186 self.pub.publish(float(value) / 100.0)
00187 else:
00188 self.pub.publish(float(value))
00189
00190 def update(self):
00191 try:
00192 if (self.joint.controller_list[self.current_controller_index].name == "mixed_position_velocity") or (self.joint.controller_list[self.current_controller_index].name == "position"):
00193 self.current_value = round(degrees(self.robot_lib.get_position(self.joint.name)),1)
00194 elif (self.joint.controller_list[self.current_controller_index].name == "velocity"):
00195 self.current_value = round(self.robot_lib.get_velocity(self.joint.name),1)
00196 elif (self.joint.controller_list[self.current_controller_index].name == "effort"):
00197 self.current_value = round(self.robot_lib.get_effort(self.joint.name),1)
00198 self.value.setText("Val: " + str(self.current_value))
00199 if self.first_update_done == False:
00200 if (self.joint.controller_list[self.current_controller_index].name == "mixed_position_velocity") or (self.joint.controller_list[self.current_controller_index].name == "position"):
00201 self.slider.setSliderPosition(self.current_value)
00202 self.slider.setValue(self.current_value)
00203 self.target.setText("Tgt: " + str(self.current_value))
00204 else:
00205 self.target.setText("Tgt: 0.0")
00206 self.first_update_done = True
00207 except:
00208 pass
00209
00210 def refresh(self):
00211 """
00212 Refresh the current position of the slider
00213 """
00214 if (self.current_controller_index != -1):
00215 if (self.joint.controller_list[self.current_controller_index].name == "mixed_position_velocity") or (self.joint.controller_list[self.current_controller_index].name == "position"):
00216 self.slider.setSliderPosition(self.current_value)
00217 self.slider.setValue(self.current_value)
00218 self.target.setText("Tgt: " + str(self.current_value))
00219
00220 def set_slider_behaviour(self):
00221 """
00222 Depending on the type of controllers we may want a different behaviour
00223 """
00224 if (self.joint.controller_list[self.current_controller_index].name == "mixed_position_velocity") or (self.joint.controller_list[self.current_controller_index].name == "position"):
00225 if self.pos_slider_tracking_behaviour:
00226 self.slider.setTracking(True)
00227 else:
00228 self.slider.setTracking(False)
00229 elif (self.joint.controller_list[self.current_controller_index].name == "velocity"):
00230 self.slider.setTracking(True)
00231 self.connect(self.slider, QtCore.SIGNAL('sliderReleased()'), self.on_slider_released)
00232 elif (self.joint.controller_list[self.current_controller_index].name == "effort"):
00233 self.slider.setTracking(True)
00234 self.connect(self.slider, QtCore.SIGNAL('sliderReleased()'), self.on_slider_released)
00235
00236 def on_slider_released(self):
00237 if (self.joint.controller_list[self.current_controller_index].name == "effort") or (self.joint.controller_list[self.current_controller_index].name == "velocity"):
00238 self.slider.setSliderPosition(0)
00239 self.changeValue(0)
00240
00241
00242 class CANHandSlider(ExtendedSlider):
00243 """
00244 Slider for the CAN Hand.
00245 """
00246 def __init__(self, joint, uiFile, robot_lib, plugin_parent, parent=None):
00247 ExtendedSlider.__init__(self, joint, uiFile, robot_lib, plugin_parent, parent)
00248 self.set_slider_behaviour()
00249 self.pub = rospy.Publisher(self.joint.controller_list[self.current_controller_index].command_topic, sendupdate, latch=True)
00250
00251 def sendupdate(self, value):
00252 message=[]
00253 message.append(joint(joint_name=self.joint.name, joint_target=value))
00254 self.pub.publish(sendupdate(len(message), message))
00255
00256 def update(self):
00257 try:
00258 self.current_value = round(self.robot_lib.valueof(self.joint.name),1)
00259 self.value.setText("Val: " + str(self.current_value))
00260 if self.first_update_done == False:
00261 self.slider.setSliderPosition(self.current_value)
00262 self.slider.setValue(self.current_value)
00263 self.target.setText("Tgt: " + str(self.current_value))
00264 self.first_update_done = True
00265 except:
00266 pass
00267
00268 def refresh(self):
00269 """
00270 Refresh the current position of the slider
00271 """
00272 self.slider.setSliderPosition(self.current_value)
00273 self.slider.setValue(self.current_value)
00274 self.target.setText("Tgt: " + str(self.current_value))
00275
00276 def set_slider_behaviour(self):
00277 if self.pos_slider_tracking_behaviour:
00278 self.slider.setTracking(True)
00279 else:
00280 self.slider.setTracking(False)
00281
00282
00283 class ArmSlider(ExtendedSlider):
00284 """
00285 Slider for the CAN Arm.
00286 """
00287 def __init__(self, joint, uiFile, robot_lib, plugin_parent, parent=None):
00288 ExtendedSlider.__init__(self, joint, uiFile, robot_lib, plugin_parent, parent)
00289 self.set_slider_behaviour()
00290 self.pub = rospy.Publisher(self.joint.controller_list[self.current_controller_index].command_topic, sendupdate, latch=True)
00291
00292 def sendupdate(self, value):
00293 message=[]
00294 message.append(joint(joint_name=self.joint.name, joint_target=value))
00295 self.pub.publish(sendupdate(len(message), message))
00296
00297 def update(self):
00298 try:
00299 self.current_value = round(self.robot_lib.valueof(self.joint.name),1)
00300 self.value.setText("Val: " + str(self.current_value))
00301 if self.first_update_done == False:
00302 self.slider.setSliderPosition(self.current_value)
00303 self.slider.setValue(self.current_value)
00304 self.target.setText("Tgt: " + str(self.current_value))
00305 self.first_update_done = True
00306 except:
00307 pass
00308
00309 def refresh(self):
00310 """
00311 Refresh the current position of the slider
00312 """
00313 self.slider.setSliderPosition(self.current_value)
00314 self.slider.setValue(self.current_value)
00315 self.target.setText("Tgt: " + str(self.current_value))
00316
00317 def set_slider_behaviour(self):
00318 if self.pos_slider_tracking_behaviour:
00319 self.slider.setTracking(True)
00320 else:
00321 self.slider.setTracking(False)
00322
00323 class SelectionSlider(QFrame):
00324 """
00325 This slider allows the user to move the selected sliders.
00326 """
00327 def __init__(self, name, min, max, uiFile, plugin_parent, parent=None):
00328 QFrame.__init__(self, parent)
00329 ui_file = os.path.join(os.path.dirname(os.path.realpath(__file__)), uiFile)
00330 loadUi(ui_file, self)
00331
00332 self.plugin_parent = plugin_parent
00333 self.label.setText(name)
00334
00335 self.slider.setFocusPolicy(QtCore.Qt.NoFocus)
00336 self.slider.setTracking(False)
00337 self.is_selected = False
00338
00339 self.slider.setMinimum(min)
00340 self.slider.setMaximum(max)
00341 self.min_label.setText(str(min))
00342 self.max_label.setText(str(max))
00343
00344 self.connect(self.slider, QtCore.SIGNAL('valueChanged(int)'), self.changeValue)
00345
00346 self.connect(self.selected, QtCore.SIGNAL('stateChanged(int)'), self.checkbox_click)
00347
00348 def changeValue(self, value):
00349 raise NotImplementedError, "Virtual method, please implement."
00350
00351 def checkbox_click(self, value):
00352 self.is_selected = value
00353 for slider in self.plugin_parent.sliders:
00354 if slider.is_selected != value:
00355 slider.is_selected = value
00356 slider.selected.setChecked(value)
00357
00358 class EtherCATSelectionSlider(SelectionSlider):
00359 """
00360 This slider allows the user to move the selected sliders for an etherCAT hand.
00361 """
00362 def __init__(self, name, min, max, uiFile, plugin_parent, parent=None):
00363 SelectionSlider.__init__(self, name, min, max, uiFile, plugin_parent, parent)
00364 self.set_slider_behaviour()
00365
00366 def set_slider_behaviour(self):
00367 """
00368 Depending on the type of controllers we may want a different behaviour
00369 """
00370
00371 self.slider.setTracking(True)
00372
00373
00374 for slider in self.plugin_parent.sliders:
00375 if (slider.joint.controller_list[slider.current_controller_index].name == "effort") or (slider.joint.controller_list[slider.current_controller_index].name == "velocity"):
00376 self.connect(self.slider, QtCore.SIGNAL('sliderReleased()'), self.on_slider_released)
00377 self.slider.setSliderPosition(50)
00378 self.current_value = 50
00379 self.target.setText("Tgt: " + str(50) + "%")
00380 break
00381
00382 def changeValue(self, value):
00383
00384 for slider in self.plugin_parent.sliders:
00385 if slider.is_selected:
00386 temp_value = ((slider.slider.maximum() - slider.slider.minimum()) * float(value) / 100.0) + slider.slider.minimum()
00387 slider.slider.setSliderPosition(temp_value)
00388 slider.changeValue(temp_value)
00389
00390 self.current_value = value
00391 self.target.setText("Tgt: " + str(value) + "%")
00392
00393 def on_slider_released(self):
00394 for slider in self.plugin_parent.sliders:
00395 if slider.is_selected:
00396 if (slider.joint.controller_list[slider.current_controller_index].name == "effort") or (slider.joint.controller_list[slider.current_controller_index].name == "velocity"):
00397 slider.slider.setSliderPosition(0)
00398 slider.changeValue(0)
00399 self.slider.setSliderPosition(50)
00400 self.current_value = 50
00401 self.target.setText("Tgt: " + str(50) + "%")
00402
00403 class CANHandSelectionSlider(SelectionSlider):
00404 """
00405 This slider allows the user to move the selected sliders for a ShadowArm.
00406 """
00407 def __init__(self, name, min, max, uiFile, robot_lib, plugin_parent, parent=None):
00408 SelectionSlider.__init__(self, name, min, max, uiFile, plugin_parent, parent)
00409 self.robot_lib = robot_lib
00410 self.slider.setTracking(True)
00411
00412 def changeValue(self, value):
00413
00414 joint_dict = {}
00415 for slider in self.plugin_parent.sliders:
00416 if slider.is_selected:
00417 temp_value = ((slider.slider.maximum() - slider.slider.minimum()) * float(value) / 100.0) + slider.slider.minimum()
00418 slider.slider.setSliderPosition(temp_value)
00419 slider.target.setText("Tgt: " + str(temp_value))
00420 joint_dict[slider.joint.name] = temp_value
00421
00422 self.robot_lib.sendupdate_from_dict(joint_dict)
00423 self.current_value = value
00424 self.target.setText("Tgt: " + str(value) + "%")
00425
00426 class ArmSelectionSlider(SelectionSlider):
00427 """
00428 This slider allows the user to move the selected sliders for a ShadowArm.
00429 """
00430 def __init__(self, name, min, max, uiFile, robot_lib, plugin_parent, parent=None):
00431 SelectionSlider.__init__(self, name, min, max, uiFile, plugin_parent, parent)
00432 self.robot_lib = robot_lib
00433 self.slider.setTracking(True)
00434
00435 def changeValue(self, value):
00436
00437 joint_dict = {}
00438 for slider in self.plugin_parent.sliders:
00439 if slider.is_selected:
00440 temp_value = ((slider.slider.maximum() - slider.slider.minimum()) * float(value) / 100.0) + slider.slider.minimum()
00441 slider.slider.setSliderPosition(temp_value)
00442 slider.target.setText("Tgt: " + str(temp_value))
00443 joint_dict[slider.joint.name] = temp_value
00444
00445 self.robot_lib.sendupdate_arm_from_dict(joint_dict)
00446 self.current_value = value
00447 self.target.setText("Tgt: " + str(value) + "%")
00448
00449
00450
00451
00452