jointSlider.py
Go to the documentation of this file.
00001 #!/usr/bin/env python
00002 #
00003 # Copyright 2012 Shadow Robot Company Ltd.
00004 #
00005 # This program is free software: you can redistribute it and/or modify it
00006 # under the terms of the GNU General Public License as published by the Free
00007 # Software Foundation, either version 2 of the License, or (at your option)
00008 # any later version.
00009 #
00010 # This program is distributed in the hope that it will be useful, but WITHOUT
00011 # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
00012 # FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
00013 # more details.
00014 #
00015 # You should have received a copy of the GNU General Public License along
00016 # with this program.  If not, see <http://www.gnu.org/licenses/>.
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 #import xml.dom.minidom
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         """
00153         @return: index of the current controller or -1 on failure
00154         """
00155         for index, joint_controller in enumerate(self.joint.controller_list):
00156             for controller in current_controllers:
00157                 if (controller.find(self.joint.name.lower() + '_' + joint_controller.name) != -1):
00158                     return index
00159         return -1
00160 
00161     def get_current_controllers(self):
00162         """
00163         @return: list of current controllers
00164         """
00165         success = True
00166         list_controllers = rospy.ServiceProxy('pr2_controller_manager/list_controllers', ListControllers)
00167         try:
00168             resp1 = list_controllers()
00169         except rospy.ServiceException:
00170             success = False
00171 
00172         current_controllers = []
00173 
00174         if success:
00175             all_loaded_controllers = resp1.controllers
00176             for state,tmp_contrl in zip(resp1.state,resp1.controllers):
00177                 if state == "running":
00178                     current_controllers.append(tmp_contrl)
00179         else:
00180             rospy.loginfo("Couldn't get list of controllers from pr2_controller_manager/list_controllers service")
00181 
00182         return current_controllers
00183 
00184     def sendupdate(self, value):
00185         if (self.current_controller_index == -1):
00186             self.initialize_controller()
00187 
00188         if (self.current_controller_index != -1):
00189             if (self.joint.controller_list[self.current_controller_index].name == "mixed_position_velocity") or (self.joint.controller_list[self.current_controller_index].name == "position") or (self.joint.controller_list[self.current_controller_index].name == "muscle_position"):
00190                 self.pub.publish(radians(float(value)))
00191             elif self.joint.controller_list[self.current_controller_index].name == "velocity":
00192                 self.pub.publish(float(value) / 100.0)
00193             else:
00194                 self.pub.publish(float(value))
00195 
00196     def update(self):
00197         try:
00198             if (self.joint.controller_list[self.current_controller_index].name == "mixed_position_velocity") or (self.joint.controller_list[self.current_controller_index].name == "position")  or (self.joint.controller_list[self.current_controller_index].name == "muscle_position"):
00199                 self.current_value = round(degrees(self.robot_lib.get_position(self.joint.name)),1)
00200             elif (self.joint.controller_list[self.current_controller_index].name == "velocity"):
00201                 self.current_value = round(self.robot_lib.get_velocity(self.joint.name),1)
00202             elif (self.joint.controller_list[self.current_controller_index].name == "effort"):
00203                 self.current_value = round(self.robot_lib.get_effort(self.joint.name),1)
00204             self.value.setText("Val: " + str(self.current_value))
00205             if self.first_update_done == False:
00206                 if (self.joint.controller_list[self.current_controller_index].name == "mixed_position_velocity") or (self.joint.controller_list[self.current_controller_index].name == "position")  or (self.joint.controller_list[self.current_controller_index].name == "muscle_position"):
00207                     self.slider.setSliderPosition(self.current_value)
00208                     self.slider.setValue(self.current_value)
00209                     self.target.setText("Tgt: " + str(self.current_value))
00210                 else:
00211                     self.target.setText("Tgt: 0.0")
00212                 self.first_update_done = True
00213         except:
00214             pass
00215         
00216     def refresh(self):
00217         """
00218         Refresh the current position of the slider with index = self.current_controller_index 
00219         """
00220         if (self.current_controller_index != -1):
00221             if (self.joint.controller_list[self.current_controller_index].name == "mixed_position_velocity") or (self.joint.controller_list[self.current_controller_index].name == "position") or (self.joint.controller_list[self.current_controller_index].name == "muscle_position"):
00222                 self.slider.setSliderPosition(self.current_value)
00223                 self.slider.setValue(self.current_value)
00224                 self.target.setText("Tgt: " + str(self.current_value))
00225 
00226     def set_slider_behaviour(self):
00227         """
00228         Set the behaviour of the slider according to controller type
00229         """
00230         if (self.joint.controller_list[self.current_controller_index].name == "mixed_position_velocity") or (self.joint.controller_list[self.current_controller_index].name == "position") or (self.joint.controller_list[self.current_controller_index].name == "muscle_position"):
00231             if self.pos_slider_tracking_behaviour:
00232                 self.slider.setTracking(True)
00233             else:
00234                 self.slider.setTracking(False)
00235         elif (self.joint.controller_list[self.current_controller_index].name == "velocity"):
00236             self.slider.setTracking(True)
00237             self.connect(self.slider, QtCore.SIGNAL('sliderReleased()'), self.on_slider_released)
00238         elif (self.joint.controller_list[self.current_controller_index].name == "effort"):
00239             self.slider.setTracking(True)
00240             self.connect(self.slider, QtCore.SIGNAL('sliderReleased()'), self.on_slider_released)
00241 
00242     def on_slider_released(self):
00243         if (self.joint.controller_list[self.current_controller_index].name == "effort") or (self.joint.controller_list[self.current_controller_index].name == "velocity"):
00244             self.slider.setSliderPosition(0)
00245             self.changeValue(0)
00246         
00247 
00248 class CANHandSlider(ExtendedSlider):
00249     """
00250     Slider for the CAN Hand.
00251     """
00252     def __init__(self, joint, uiFile, robot_lib, plugin_parent, parent=None):
00253         ExtendedSlider.__init__(self, joint, uiFile, robot_lib, plugin_parent, parent)
00254         self.set_slider_behaviour()
00255         self.pub = rospy.Publisher(self.joint.controller_list[self.current_controller_index].command_topic, sendupdate, latch=True)
00256 
00257     def sendupdate(self, value):
00258         message=[]
00259         message.append(joint(joint_name=self.joint.name, joint_target=value))
00260         self.pub.publish(sendupdate(len(message), message))
00261 
00262     def update(self):
00263         try:
00264             self.current_value = round(self.robot_lib.valueof(self.joint.name),1)
00265             self.value.setText("Val: " + str(self.current_value))
00266             if self.first_update_done == False:
00267                 self.slider.setSliderPosition(self.current_value)
00268                 self.slider.setValue(self.current_value)
00269                 self.target.setText("Tgt: " + str(self.current_value))
00270                 self.first_update_done = True
00271         except:
00272             pass
00273     
00274     def refresh(self):
00275         """
00276         Refresh the current position of the slider
00277         """
00278         self.slider.setSliderPosition(self.current_value)
00279         self.slider.setValue(self.current_value)
00280         self.target.setText("Tgt: " + str(self.current_value))
00281 
00282     def set_slider_behaviour(self):
00283         if self.pos_slider_tracking_behaviour:
00284             self.slider.setTracking(True)
00285         else:
00286             self.slider.setTracking(False)
00287 
00288 
00289 class ArmSlider(ExtendedSlider):
00290     """
00291     Slider for the CAN Arm.
00292     """
00293     def __init__(self, joint, uiFile, robot_lib, plugin_parent, parent=None):
00294         ExtendedSlider.__init__(self, joint, uiFile, robot_lib, plugin_parent, parent)
00295         self.set_slider_behaviour()
00296         self.pub = rospy.Publisher(self.joint.controller_list[self.current_controller_index].command_topic, sendupdate, latch=True)
00297 
00298     def sendupdate(self, value):
00299         message=[]
00300         message.append(joint(joint_name=self.joint.name, joint_target=value))
00301         self.pub.publish(sendupdate(len(message), message))
00302 
00303     def update(self):
00304         try:
00305             self.current_value = round(self.robot_lib.valueof(self.joint.name),1)
00306             self.value.setText("Val: " + str(self.current_value))
00307             if self.first_update_done == False:
00308                 self.slider.setSliderPosition(self.current_value)
00309                 self.slider.setValue(self.current_value)
00310                 self.target.setText("Tgt: " + str(self.current_value))
00311                 self.first_update_done = True
00312         except:
00313             pass
00314     
00315     def refresh(self):
00316         """
00317         Refresh the current position of the slider
00318         """
00319         self.slider.setSliderPosition(self.current_value)
00320         self.slider.setValue(self.current_value)
00321         self.target.setText("Tgt: " + str(self.current_value))
00322     
00323     def set_slider_behaviour(self):
00324         if self.pos_slider_tracking_behaviour:
00325             self.slider.setTracking(True)
00326         else:
00327             self.slider.setTracking(False)
00328 
00329 class SelectionSlider(QFrame):
00330     """
00331     This slider allows the user to move the selected sliders.
00332     """
00333     def __init__(self, name, min, max, uiFile, plugin_parent, parent=None):
00334         QFrame.__init__(self, parent)
00335         ui_file = os.path.join(os.path.dirname(os.path.realpath(__file__)), uiFile)
00336         loadUi(ui_file, self)
00337 
00338         self.plugin_parent = plugin_parent
00339         self.label.setText(name)
00340 
00341         self.slider.setFocusPolicy(QtCore.Qt.NoFocus)
00342         self.slider.setTracking(False)
00343         self.is_selected = False
00344 
00345         self.slider.setMinimum(min)
00346         self.slider.setMaximum(max)
00347         self.min_label.setText(str(min))
00348         self.max_label.setText(str(max))
00349 
00350         self.connect(self.slider, QtCore.SIGNAL('valueChanged(int)'), self.changeValue)
00351 
00352         self.connect(self.selected, QtCore.SIGNAL('stateChanged(int)'), self.checkbox_click)
00353 
00354     def changeValue(self, value):
00355         raise NotImplementedError, "Virtual method, please implement."
00356 
00357     def checkbox_click(self, value):
00358         self.is_selected = value
00359         for slider in self.plugin_parent.sliders:
00360             if slider.is_selected != value:
00361                 slider.is_selected = value
00362                 slider.selected.setChecked(value)
00363 
00364 class EtherCATSelectionSlider(SelectionSlider):
00365     """
00366     This slider allows the user to move the selected sliders for an etherCAT hand.
00367     """
00368     def __init__(self, name, min, max, uiFile, plugin_parent, parent=None):
00369         SelectionSlider.__init__(self, name, min, max, uiFile, plugin_parent, parent)
00370         self.set_slider_behaviour()
00371 
00372     def set_slider_behaviour(self):
00373         """
00374         Set the behaviour of the slider according to controller type
00375         Currently we set the tracking to true for all the slide types
00376         If any of the controllers is an effort or velocity controller we will activate the slider released signal detection
00377         And set the slider halfway (50) as that is the position of the 0 for effort and velocity controllers
00378         """
00379         self.slider.setTracking(True)
00380         for slider in self.plugin_parent.sliders:
00381             if (slider.joint.controller_list[slider.current_controller_index].name == "effort")  or (slider.joint.controller_list[slider.current_controller_index].name == "velocity"):
00382                 self.connect(self.slider, QtCore.SIGNAL('sliderReleased()'), self.on_slider_released)
00383                 self.slider.setSliderPosition(50)
00384                 self.current_value = 50
00385                 self.target.setText("Tgt: " + str(50) + "%")
00386                 break
00387 
00388     def changeValue(self, value):
00389         """
00390         modify the values from the selected sliders.
00391         """
00392         for slider in self.plugin_parent.sliders:
00393             if slider.is_selected:
00394                 temp_value = ((slider.slider.maximum() - slider.slider.minimum()) * float(value) / 100.0) + slider.slider.minimum()
00395                 slider.slider.setSliderPosition(temp_value)
00396                 slider.changeValue(temp_value)
00397 
00398         self.current_value = value
00399         self.target.setText("Tgt: " + str(value) + "%")
00400 
00401     def on_slider_released(self):
00402         for slider in self.plugin_parent.sliders:
00403             if slider.is_selected:
00404                 if (slider.joint.controller_list[slider.current_controller_index].name == "effort") or (slider.joint.controller_list[slider.current_controller_index].name == "velocity"):
00405                     slider.slider.setSliderPosition(0)
00406                     slider.changeValue(0)
00407         self.slider.setSliderPosition(50)
00408         self.current_value = 50
00409         self.target.setText("Tgt: " + str(50) + "%")
00410 
00411 class CANHandSelectionSlider(SelectionSlider):
00412     """
00413     This slider allows the user to move the selected sliders for a ShadowArm.
00414     """
00415     def __init__(self, name, min, max, uiFile, robot_lib, plugin_parent, parent=None):
00416         SelectionSlider.__init__(self, name, min, max, uiFile, plugin_parent, parent)
00417         self.robot_lib = robot_lib
00418         self.slider.setTracking(True)
00419 
00420     def changeValue(self, value):
00421         """
00422         modify the values from the selected sliders.
00423         """
00424         joint_dict = {}
00425         for slider in self.plugin_parent.sliders:
00426             if slider.is_selected:
00427                 temp_value = ((slider.slider.maximum() - slider.slider.minimum()) * float(value) / 100.0) + slider.slider.minimum()
00428                 slider.slider.setSliderPosition(temp_value)
00429                 slider.target.setText("Tgt: " + str(temp_value))
00430                 joint_dict[slider.joint.name] = temp_value
00431 
00432         self.robot_lib.sendupdate_from_dict(joint_dict)
00433         self.current_value = value
00434         self.target.setText("Tgt: " + str(value) + "%")
00435 
00436 class ArmSelectionSlider(SelectionSlider):
00437     """
00438     This slider allows the user to move the selected sliders for a ShadowArm.
00439     """
00440     def __init__(self, name, min, max, uiFile, robot_lib, plugin_parent, parent=None):
00441         SelectionSlider.__init__(self, name, min, max, uiFile, plugin_parent, parent)
00442         self.robot_lib = robot_lib
00443         self.slider.setTracking(True)
00444 
00445     def changeValue(self, value):
00446         """
00447         modify the values from the selected sliders.
00448         """
00449         joint_dict = {}
00450         for slider in self.plugin_parent.sliders:
00451             if slider.is_selected:
00452                 temp_value = ((slider.slider.maximum() - slider.slider.minimum()) * float(value) / 100.0) + slider.slider.minimum()
00453                 slider.slider.setSliderPosition(temp_value)
00454                 slider.target.setText("Tgt: " + str(temp_value))
00455                 joint_dict[slider.joint.name] = temp_value
00456 
00457         self.robot_lib.sendupdate_arm_from_dict(joint_dict)
00458         self.current_value = value
00459         self.target.setText("Tgt: " + str(value) + "%")


sr_gui_joint_slider
Author(s): Ugo Cupcic
autogenerated on Fri Aug 28 2015 13:17:13