sliders.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 import rospy
00021 
00022 from python_qt_binding import loadUi
00023 
00024 from PyQt4 import QtCore, Qt
00025 from QtGui import QFrame
00026 from controller_manager_msgs.srv import ListControllers
00027 from sr_robot_msgs.msg import sendupdate, joint
00028 from std_msgs.msg import Float64
00029 from math import radians, degrees
00030 from trajectory_msgs.msg import JointTrajectory, JointTrajectoryPoint
00031 
00032 
00033 class JointController():
00034 
00035     """
00036     Contains the min and the max and the command and state topics for the joint controller.
00037     """
00038 
00039     def __init__(self, name, controller_type, controller_state_type,
00040                  controller_category, subscribe_status_cb_list=None,
00041                  cmd_publisher=None, traj_target=None):
00042         self.name = name
00043         self.controller_type = controller_type
00044         self.controller_state_type = controller_state_type
00045         self.controller_category = controller_category
00046         self.subscribe_status_cb_list = subscribe_status_cb_list
00047         self.cmd_publisher = cmd_publisher
00048         self.traj_target = traj_target
00049 
00050 
00051 class Joint():
00052 
00053     """
00054     Contains the name, and a controllers list for the joint.
00055     """
00056 
00057     def __init__(self, name, min, max, vel, joint_controller):
00058         self.name = name
00059         self.controller = joint_controller
00060         # Here we manipulate the limits to be in degrees (if they have to do with angles)
00061         # And also use vel to set min and max if the controller for this joint
00062         # is a velocity controller
00063         self.min = round(degrees(min), 1)
00064         self.max = round(degrees(max), 1)
00065         self.vel = round(degrees(vel), 1)
00066         if self.controller.controller_category == "velocity":
00067             self.min = -self.vel
00068             self.max = self.vel
00069         elif self.controller.controller_category == "effort":
00070             # Happily hardcoded value. It is difficult to establish a relation
00071             # between these units and Newtons. 900 is enough
00072             self.min = -900
00073             self.max = 900
00074 
00075 
00076 class ExtendedSlider(QFrame):
00077 
00078     """
00079     This slider displays the current position and the target as well.
00080     """
00081 
00082     def __init__(self, joint, uiFile, plugin_parent, parent=None):
00083         QFrame.__init__(self, parent)
00084         ui_file = os.path.join(
00085             os.path.dirname(os.path.realpath(__file__)), uiFile)
00086         loadUi(ui_file, self)
00087 
00088         self.state = None
00089 
00090         self.plugin_parent = plugin_parent
00091         self.joint = joint
00092         self.current_controller_index = -1
00093         self.label.setText(joint.name)
00094         self.current_value = 0
00095 
00096         self.slider.setFocusPolicy(QtCore.Qt.NoFocus)
00097         self.slider.setTracking(True)
00098         self.pos_slider_tracking_behaviour = True
00099         self.is_selected = False
00100         self.first_update_done = False
00101 
00102         self.current_controller_index = 0
00103         self.slider.setMinimum(joint.min)
00104         self.slider.setMaximum(joint.max)
00105         self.min_label.setText(str(joint.min))
00106         self.max_label.setText(str(joint.max))
00107 
00108         self.connect(self.selected, QtCore.SIGNAL(
00109             'stateChanged(int)'), self.checkbox_click)
00110         self.connect(self.slider, QtCore.SIGNAL(
00111             'valueChanged(int)'), self.changeValue)
00112 
00113         self.timer = Qt.QTimer(self)
00114         self.connect(self.timer, QtCore.SIGNAL('timeout()'), self.update)
00115         self.timer.start(200)
00116 
00117     def changeValue(self, value):
00118         self.target.setText("Tgt: " + str(value))
00119         self.sendupdate(value)
00120 
00121     def sendupdate(self, value):
00122         raise NotImplementedError("Virtual method, please implement.")
00123 
00124     def update(self):
00125         raise NotImplementedError("Virtual method, please implement.")
00126 
00127     def refresh(self):
00128         raise NotImplementedError("Virtual method, please implement.")
00129 
00130     def checkbox_click(self, value):
00131         self.is_selected = value
00132 
00133     def set_slider_behaviour(self):
00134         raise NotImplementedError("Virtual method, please implement.")
00135 
00136     def set_new_slider_behaviour(self, tracking):
00137         if tracking:
00138             self.pos_slider_tracking_behaviour = True
00139         else:
00140             self.pos_slider_tracking_behaviour = False
00141         self.set_slider_behaviour()
00142 
00143 
00144 class EtherCATHandSlider(ExtendedSlider):
00145 
00146     """
00147     Slider for the EtherCAT Hand.
00148     """
00149 
00150     def __init__(self, joint, uiFile, plugin_parent, parent=None):
00151         ExtendedSlider.__init__(self, joint, uiFile, plugin_parent, parent)
00152 
00153         self.initialize_controller()
00154 
00155     def initialize_controller(self):
00156         self.slider.setMinimum(self.joint.min)
00157         self.slider.setMaximum(self.joint.max)
00158         self.min_label.setText(str(self.joint.min))
00159         self.max_label.setText(str(self.joint.max))
00160 
00161         self.pub = rospy.Publisher(
00162             self.joint.controller.name + "/command",
00163             Float64,
00164             queue_size=1,
00165             latch=True
00166         )
00167         self.set_slider_behaviour()
00168         self.state_sub = rospy.Subscriber(
00169             self.joint.controller.name + "/state", self.joint.controller.controller_state_type, self._state_cb)
00170 
00171     def _state_cb(self, msg):
00172         self.state = msg
00173 
00174     def sendupdate(self, value):
00175         if (self.joint.controller.controller_category == "position")\
00176                 or (self.joint.controller.controller_category == "velocity"):
00177             self.pub.publish(radians(float(value)))
00178         else:
00179             self.pub.publish(float(value))
00180 
00181     def update(self):
00182         try:
00183             if (self.joint.controller.controller_category == "position")\
00184                     or (self.joint.controller.controller_category == "velocity"):
00185                 self.current_value = round(
00186                     degrees(self.state.process_value), 1)
00187             elif (self.joint.controller.controller_category == "effort"):
00188                 self.current_value = round(self.state.process_value, 1)
00189             self.value.setText("Val: " + str(self.current_value))
00190 
00191             if not self.first_update_done:
00192                 if (self.joint.controller.controller_category == "position"):
00193                     self.slider.setSliderPosition(self.current_value)
00194                     self.slider.setValue(self.current_value)
00195                     self.target.setText("Tgt: " + str(self.current_value))
00196                 else:
00197                     self.target.setText("Tgt: 0.0")
00198                 self.first_update_done = True
00199         except:
00200             pass
00201 
00202     def refresh(self):
00203         """
00204         Refresh the current position of the slider with index = self.current_controller_index
00205         """
00206         if (self.joint.controller.controller_category == "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 
00211     def set_slider_behaviour(self):
00212         """
00213         Set the behaviour of the slider according to controller type
00214         """
00215         if (self.joint.controller.controller_category == "position"):
00216             if self.pos_slider_tracking_behaviour:
00217                 self.slider.setTracking(True)
00218             else:
00219                 self.slider.setTracking(False)
00220         elif (self.joint.controller.controller_category == "velocity"):
00221             self.slider.setTracking(True)
00222             self.connect(self.slider, QtCore.SIGNAL(
00223                 'sliderReleased()'), self.on_slider_released)
00224         elif (self.joint.controller.controller_category == "effort"):
00225             self.slider.setTracking(True)
00226             self.connect(self.slider, QtCore.SIGNAL(
00227                 'sliderReleased()'), self.on_slider_released)
00228 
00229     def on_slider_released(self):
00230         if (self.joint.controller.controller_category == "effort")\
00231                 or (self.joint.controller.controller_category == "velocity"):
00232             self.slider.setSliderPosition(0)
00233             self.changeValue(0)
00234 
00235 
00236 class EtherCATHandTrajectorySlider(ExtendedSlider):
00237 
00238     """
00239     Slider for one EtherCAT Hand joint, that uses the trajectory controller interface.
00240     """
00241 
00242     def __init__(self, joint, uiFile, plugin_parent, parent=None):
00243         ExtendedSlider.__init__(self, joint, uiFile, plugin_parent, parent)
00244 
00245         self.initialize_controller()
00246 
00247     def initialize_controller(self):
00248         self.slider.setMinimum(self.joint.min)
00249         self.slider.setMaximum(self.joint.max)
00250         self.min_label.setText(str(self.joint.min))
00251         self.max_label.setText(str(self.joint.max))
00252 
00253         self.pub = self.joint.controller.cmd_publisher
00254         self.set_slider_behaviour()
00255 
00256         self.joint.controller.subscribe_status_cb_list.append(self._state_cb)
00257 
00258     def _state_cb(self, msg):
00259         self.state = msg.actual.positions[
00260             msg.joint_names.index(self.joint.name)]
00261 
00262     def sendupdate(self, value):
00263         if self.joint.controller.traj_target.joint_names \
00264                 and self.joint.controller.traj_target.points:
00265             self.joint.controller.traj_target.points[0].positions[
00266                 self.joint.controller.traj_target.joint_names.index(self.joint.name)] = radians(float(value))
00267             self.pub.publish(self.joint.controller.traj_target)
00268 
00269     def update(self):
00270         try:
00271             self.current_value = round(degrees(self.state), 1)
00272             self.value.setText("Val: " + str(self.current_value))
00273 
00274             if not self.first_update_done:
00275                 self.slider.setSliderPosition(self.current_value)
00276                 self.slider.setValue(self.current_value)
00277                 self.target.setText("Tgt: " + str(self.current_value))
00278 
00279                 self.first_update_done = True
00280         except:
00281             pass
00282 
00283     def refresh(self):
00284         """
00285         Refresh the current position of the slider with index = self.current_controller_index
00286         """
00287         self.slider.setSliderPosition(self.current_value)
00288         self.slider.setValue(self.current_value)
00289         self.target.setText("Tgt: " + str(self.current_value))
00290 
00291     def set_slider_behaviour(self):
00292         """
00293         Set the behaviour of the slider according to controller type
00294         """
00295         if (self.joint.controller.controller_category == "position_trajectory"):
00296             if self.pos_slider_tracking_behaviour:
00297                 self.slider.setTracking(True)
00298             else:
00299                 self.slider.setTracking(False)
00300 
00301     def on_slider_released(self):
00302         pass
00303 
00304 
00305 class SelectionSlider(QFrame):
00306 
00307     """
00308     This slider allows the user to move the selected sliders.
00309     """
00310 
00311     def __init__(self, name, min, max, uiFile, plugin_parent, parent=None):
00312         QFrame.__init__(self, parent)
00313         ui_file = os.path.join(
00314             os.path.dirname(os.path.realpath(__file__)), uiFile)
00315         loadUi(ui_file, self)
00316 
00317         self.plugin_parent = plugin_parent
00318         self.label.setText(name)
00319 
00320         self.slider.setFocusPolicy(QtCore.Qt.NoFocus)
00321         self.slider.setTracking(False)
00322         self.is_selected = False
00323 
00324         self.slider.setMinimum(min)
00325         self.slider.setMaximum(max)
00326         self.min_label.setText(str(min))
00327         self.max_label.setText(str(max))
00328 
00329         self.connect(self.slider, QtCore.SIGNAL(
00330             'valueChanged(int)'), self.changeValue)
00331 
00332         self.connect(self.selected, QtCore.SIGNAL(
00333             'stateChanged(int)'), self.checkbox_click)
00334 
00335     def changeValue(self, value):
00336         raise NotImplementedError("Virtual method, please implement.")
00337 
00338     def checkbox_click(self, value):
00339         self.is_selected = value
00340         for slider in self.plugin_parent.sliders:
00341             if slider.is_selected != value:
00342                 slider.is_selected = value
00343                 slider.selected.setChecked(value)
00344 
00345 
00346 class EtherCATSelectionSlider(SelectionSlider):
00347 
00348     """
00349     This slider allows the user to move the selected sliders for an etherCAT hand.
00350     """
00351 
00352     def __init__(self, name, min, max, uiFile, plugin_parent, parent=None):
00353         SelectionSlider.__init__(
00354             self, name, min, max, uiFile, plugin_parent, parent)
00355         self.set_slider_behaviour()
00356 
00357     def set_slider_behaviour(self):
00358         """
00359         Set the behaviour of the slider according to controller type
00360         Currently we set the tracking to true for all the slide types
00361         If any of the controllers is an effort or velocity controller
00362         we will activate the slider released signal detection
00363         And set the slider halfway (50) as that is the position of the 0
00364         for effort and velocity controllers
00365         """
00366         self.slider.setTracking(True)
00367         for slider in self.plugin_parent.sliders:
00368             if (slider.joint.controller.controller_category == "effort")\
00369                     or (slider.joint.controller.controller_category == "velocity"):
00370                 self.connect(self.slider, QtCore.SIGNAL(
00371                     'sliderReleased()'), self.on_slider_released)
00372                 self.slider.setSliderPosition(50)
00373                 self.current_value = 50
00374                 self.target.setText("Tgt: " + str(50) + "%")
00375                 break
00376 
00377     def changeValue(self, value):
00378         """
00379         modify the values from the selected sliders.
00380         """
00381         for slider in self.plugin_parent.sliders:
00382             if slider.is_selected:
00383                 temp_value = ((slider.slider.maximum() - slider.slider.minimum()) * float(
00384                     value) / 100.0) + slider.slider.minimum()
00385                 slider.slider.setSliderPosition(temp_value)
00386                 slider.changeValue(temp_value)
00387 
00388         self.current_value = value
00389         self.target.setText("Tgt: " + str(value) + "%")
00390 
00391     def on_slider_released(self):
00392         for slider in self.plugin_parent.sliders:
00393             if slider.is_selected:
00394                 if (slider.joint.controller.controller_category == "effort")\
00395                         or (slider.joint.controller.controller_category == "velocity"):
00396                     slider.slider.setSliderPosition(0)
00397                     slider.changeValue(0)
00398         self.slider.setSliderPosition(50)
00399         self.current_value = 50
00400         self.target.setText("Tgt: " + str(50) + "%")


sr_gui_joint_slider
Author(s): Ugo Cupcic
autogenerated on Thu Jun 6 2019 21:13:55