grasp_controller.py
Go to the documentation of this file.
00001 # Copyright 2011 Shadow Robot Company Ltd.
00002 #
00003 # This program is free software: you can redistribute it and/or modify it
00004 # under the terms of the GNU General Public License as published by the Free
00005 # Software Foundation, either version 2 of the License, or (at your option)
00006 # any later version.
00007 #
00008 # This program is distributed in the hope that it will be useful, but WITHOUT
00009 # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
00010 # FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
00011 # more details.
00012 #
00013 # You should have received a copy of the GNU General Public License along
00014 # with this program.  If not, see <http://www.gnu.org/licenses/>.
00015 
00016 import os, time, rospy, rospkg
00017 
00018 from rospy import loginfo, logerr, logdebug
00019 
00020 from qt_gui.plugin import Plugin
00021 from python_qt_binding import loadUi
00022 
00023 import QtCore
00024 from QtCore import Qt, QEvent, QObject
00025 import QtGui
00026 from QtGui import *
00027 
00028 from sr_hand.Grasp import Grasp
00029 from sr_hand.grasps_interpoler import GraspInterpoler
00030 from sr_hand.grasps_parser import GraspParser
00031 
00032 from sr_hand.shadowhand_ros import ShadowHand_ROS
00033 
00034 class JointSelecter(QtGui.QWidget):
00035     """
00036     Select which joints to save in a new grasp
00037     """
00038     def __init__(self, parent, all_joints):
00039         QtGui.QWidget.__init__(self, parent=parent)
00040         self.frame = QtGui.QFrame()
00041         self.layout = QtGui.QGridLayout()
00042         self.checkboxes = []
00043 
00044         col = 0
00045         #vectors to set the correct row in the layout for each col
00046         rows = [0, 0, 0, 0, 0, 0]
00047         joint_names = all_joints.keys()
00048         joint_names.sort()
00049         for joint in joint_names:
00050             if "fj1" in joint.lower():
00051                 continue
00052             if "fj2" in joint.lower():
00053                 continue
00054             if "ff" in joint.lower():
00055                 col = 0
00056             elif "mf" in joint.lower():
00057                 col = 1
00058             elif "rf" in joint.lower():
00059                 col = 2
00060             elif "lf" in joint.lower():
00061                 col = 3
00062             elif "th" in joint.lower():
00063                 col = 4
00064             else:
00065                 col = 5
00066 
00067             row = rows[col]
00068             rows[col] = row + 1
00069             cb = QtGui.QCheckBox(str(joint), self.frame)
00070             self.checkboxes.append(cb)
00071             self.layout.addWidget(cb, row, col)
00072 
00073         self.frame.setLayout(self.layout)
00074         layout = QtGui.QVBoxLayout()
00075         layout.addWidget(self.frame)
00076         self.frame.show()
00077         self.setLayout(layout)
00078         self.show()
00079 
00080     def get_selected(self):
00081         """
00082         Retrieve selected joints
00083         """
00084         joints = []
00085         for cb in self.checkboxes:
00086             if cb.isChecked():
00087                 joints.append(str(cb.text()))
00088 
00089         return joints
00090 
00091     def select_all(self):
00092         """
00093         Select all joints
00094         """
00095         for cb in self.checkboxes:
00096             cb.setChecked(True)
00097 
00098     def deselect_all(self):
00099         """
00100         Unselect all joints
00101         """
00102         for cb in self.checkboxes:
00103             cb.setChecked(False)
00104 
00105 class GraspSaver(QtGui.QDialog):
00106     """
00107     Save a new grasp from the current joints positions.
00108     """
00109     def __init__(self, parent, all_joints, plugin_parent):
00110         QtGui.QDialog.__init__(self, parent)
00111         self.plugin_parent = plugin_parent
00112         self.all_joints = all_joints
00113         self.setModal(True)
00114         self.setWindowTitle("Save Grasp")
00115 
00116         self.grasp_name = ""
00117 
00118         self.upper_frame = QtGui.QFrame()
00119         self.upper_layout = QtGui.QHBoxLayout()
00120         label_name = QtGui.QLabel()
00121         label_name.setText("Grasp Name: ")
00122         name_widget = QtGui.QLineEdit()
00123         self.upper_frame.connect(name_widget, QtCore.SIGNAL('textChanged(QString)'), self.name_changed)
00124 
00125         self.upper_layout.addWidget(label_name)
00126         self.upper_layout.addWidget(name_widget)
00127         self.upper_frame.setLayout(self.upper_layout)
00128 
00129         select_all_frame = QtGui.QFrame()
00130         select_all_layout = QtGui.QHBoxLayout()
00131         btn_select_all = QtGui.QPushButton(select_all_frame)
00132         btn_select_all.setText("Select All")
00133         select_all_layout.addWidget(btn_select_all)
00134         self.connect(btn_select_all, QtCore.SIGNAL("clicked()"), self.select_all)
00135         btn_deselect_all = QtGui.QPushButton(select_all_frame)
00136         btn_deselect_all.setText("Deselect All")
00137         select_all_layout.addWidget(btn_deselect_all)
00138         self.connect(btn_deselect_all, QtCore.SIGNAL("clicked()"), self.deselect_all)
00139         select_all_frame.setLayout(select_all_layout)
00140 
00141         self.joint_selecter = JointSelecter(self, self.all_joints)
00142 
00143         btn_frame = QtGui.QFrame()
00144         self.btn_ok = QtGui.QPushButton(btn_frame)
00145         self.btn_ok.setText("OK")
00146         self.btn_ok.setDisabled(True)
00147         self.connect(self.btn_ok, QtCore.SIGNAL("clicked()"), self.accept)
00148         btn_cancel = QtGui.QPushButton(btn_frame)
00149         btn_cancel.setText("Cancel")
00150         self.connect(btn_cancel, QtCore.SIGNAL("clicked()"), self.reject)
00151 
00152         btn_layout = QtGui.QHBoxLayout()
00153         btn_layout.addWidget(self.btn_ok)
00154         btn_layout.addWidget(btn_cancel)
00155         btn_frame.setLayout(btn_layout)
00156 
00157         self.layout = QtGui.QVBoxLayout()
00158         self.layout.addWidget(self.upper_frame)
00159         self.layout.addWidget(select_all_frame)
00160         self.layout.addWidget(self.joint_selecter)
00161         self.layout.addWidget(btn_frame)
00162 
00163         self.setLayout(self.layout)
00164         self.show()
00165 
00166     def select_all(self):
00167         """
00168         Select all joints
00169         """
00170         self.joint_selecter.select_all()
00171 
00172     def deselect_all(self):
00173         """
00174         Unselect all joints
00175         """
00176         self.joint_selecter.deselect_all()
00177 
00178     def name_changed(self, name):
00179         self.grasp_name = name
00180         if self.grasp_name != "":
00181             self.btn_ok.setEnabled(True)
00182         else:
00183             self.btn_ok.setDisabled(True)
00184 
00185     def accept(self):
00186         """
00187         Save grasp for the selected joints
00188         """
00189         grasp = Grasp()
00190         grasp.grasp_name = self.grasp_name
00191 
00192         joints_to_save = self.joint_selecter.get_selected()
00193         if len(joints_to_save) == 0:
00194             joints_to_save = self.all_joints.keys()
00195         for joint_to_save in joints_to_save:
00196             grasp.joints_and_positions[joint_to_save] = self.all_joints[joint_to_save]
00197 
00198         self.plugin_parent.sr_lib.grasp_parser.write_grasp_to_file(grasp)
00199         self.plugin_parent.sr_lib.grasp_parser.refresh()
00200 
00201         self.plugin_parent.reloadGraspSig['int'].emit(1)
00202 
00203         QtGui.QDialog.accept(self)
00204 
00205 class GraspChooser(QtGui.QWidget):
00206     """
00207     Choose a grasp from a list of grasps.
00208     """
00209     def __init__(self, parent, plugin_parent, title):
00210         QtGui.QWidget.__init__(self)
00211         self.plugin_parent = plugin_parent
00212         self.grasp = None
00213         self.title = QtGui.QLabel()
00214         self.title.setText(title)
00215 
00216     def draw(self):
00217         """
00218         Draw the gui and connect signals
00219         """
00220         self.frame = QtGui.QFrame(self)
00221 
00222         self.list = QtGui.QListWidget()
00223         first_item = self.refresh_list()
00224         self.connect(self.list, QtCore.SIGNAL('itemClicked(QListWidgetItem*)'), self.grasp_selected)
00225 
00226         self.connect(self.list, QtCore.SIGNAL('itemDoubleClicked(QListWidgetItem*)'), self.double_click)
00227         self.list.setViewMode(QtGui.QListView.ListMode)
00228         self.list.setResizeMode(QtGui.QListView.Adjust)
00229         self.list.setItemSelected(first_item, True)
00230         self.grasp_selected(first_item, first_time=True)
00231 
00232         self.layout = QtGui.QVBoxLayout()
00233         self.layout.addWidget(self.title)
00234         self.layout.addWidget(self.list)
00235 
00236         ###
00237         # SIGNALS
00238         ##
00239         self.plugin_parent.reloadGraspSig['int'].connect(self.refresh_list)
00240 
00241         self.frame.setLayout(self.layout)
00242         layout = QtGui.QVBoxLayout()
00243         layout.addWidget(self.frame)
00244         self.frame.show()
00245         self.setLayout(layout)
00246         self.show()
00247 
00248     def double_click(self, item):
00249         """ 
00250         Sends new targets to the hand from a dictionary mapping the name of the joint to the value of its target
00251         """
00252         self.grasp = self.plugin_parent.sr_lib.grasp_parser.grasps[str(item.text())]
00253         self.plugin_parent.sr_lib.sendupdate_from_dict(self.grasp.joints_and_positions)
00254         self.plugin_parent.set_reference_grasp()
00255 
00256     def grasp_selected(self, item, first_time=False):
00257         """
00258         grasp has been selected with a single click
00259         """
00260         self.grasp = self.plugin_parent.sr_lib.grasp_parser.grasps[str(item.text())]
00261         if not first_time:
00262             self.plugin_parent.grasp_changed()
00263             self.plugin_parent.set_reference_grasp()
00264 
00265     def refresh_list(self, value = 0):
00266         """
00267         refreash list of grasps
00268         """
00269         self.list.clear()
00270         first_item = None
00271         grasps = self.plugin_parent.sr_lib.grasp_parser.grasps.keys()
00272         grasps.sort()
00273         for grasp_name in grasps:
00274             item = QtGui.QListWidgetItem(grasp_name)
00275             if first_item == None:
00276                 first_item = item
00277             self.list.addItem(item)
00278         return first_item
00279 
00280 class GraspSlider(QtGui.QWidget):
00281     """
00282     Slide from one grasp to another.
00283     """
00284     def __init__(self, parent, plugin_parent):
00285         QtGui.QWidget.__init__(self, parent)
00286         self.plugin_parent = plugin_parent
00287 
00288     def draw(self):
00289         """
00290         Draw the gui and connect signals
00291         """
00292         self.frame = QtGui.QFrame(self)
00293         label_frame = QtGui.QFrame(self.frame)
00294         from_label = QtGui.QLabel()
00295         from_label.setText("From")
00296         ref_label = QtGui.QLabel()
00297         ref_label.setText("Reference")
00298         to_label = QtGui.QLabel()
00299         to_label.setText("To")
00300         label_layout = QtGui.QHBoxLayout()
00301         label_layout.addWidget(from_label)
00302         label_layout.addWidget(ref_label)
00303         label_layout.addWidget(to_label)
00304 
00305         label_frame.setLayout(label_layout)
00306 
00307         self.slider = QtGui.QSlider()
00308         self.slider.setOrientation(QtCore.Qt.Horizontal)
00309         self.slider.setFocusPolicy(QtCore.Qt.NoFocus)
00310         self.slider.setTickInterval(100)
00311         self.slider.setTickPosition(QSlider.TicksAbove)
00312         self.slider.setMinimum(-100)
00313         self.slider.setMaximum(100)
00314 
00315         self.connect(self.slider, QtCore.SIGNAL('valueChanged(int)'), self.changeValue)
00316 
00317         self.layout = QtGui.QVBoxLayout()
00318         self.layout.addWidget(label_frame)
00319         self.layout.addWidget(self.slider)
00320 
00321         self.frame.setLayout(self.layout)
00322         layout = QtGui.QVBoxLayout()
00323         layout.addWidget(self.frame)
00324         self.frame.show()
00325         self.setLayout(layout)
00326         self.show()
00327 
00328     def changeValue(self, value):
00329         """
00330         interpolate from the current grasp to new value
00331         """
00332         self.plugin_parent.interpolate_grasps(value)
00333 
00334 class SrGuiGraspController(Plugin):
00335     """
00336     Main GraspController plugin Dock window.
00337     """
00338 
00339     reloadGraspSig = QtCore.pyqtSignal(int)
00340 
00341     def __init__(self, context):
00342         super(SrGuiGraspController, self).__init__(context)
00343 
00344         self.setObjectName('SrGuiGraspController')
00345         
00346         self.icon_dir = os.path.join(rospkg.RosPack().get_path('sr_visualization_icons'), '/icons')
00347         
00348         self.sr_lib   = ShadowHand_ROS()
00349         
00350         ui_file = os.path.join(rospkg.RosPack().get_path('sr_gui_grasp_controller'), 'uis', 'SrGuiGraspController.ui')
00351         self._widget     = QWidget()
00352         loadUi(ui_file, self._widget)
00353         context.add_widget(self._widget)
00354 
00355         self.current_grasp = Grasp()
00356         self.current_grasp.name = 'CURRENT_UNSAVED'
00357         self.grasp_interpoler_1 = None
00358         self.grasp_interpoler_2 = None
00359 
00360         self.layout = self._widget.layout
00361 
00362         subframe = QtGui.QFrame()
00363         sublayout = QtGui.QVBoxLayout()
00364 
00365         self.grasp_slider = GraspSlider(self._widget, self)
00366         sublayout.addWidget(self.grasp_slider)
00367 
00368         btn_frame = QtGui.QFrame()
00369         btn_layout = QtGui.QHBoxLayout()
00370         self.btn_save = QtGui.QPushButton()
00371         self.btn_save.setText("Save")
00372         self.btn_save.setFixedWidth(130)
00373         self.btn_save.setIcon(QtGui.QIcon(self.icon_dir + '/save.png'))
00374         btn_frame.connect(self.btn_save, QtCore.SIGNAL('clicked()'), self.save_grasp)
00375         btn_layout.addWidget(self.btn_save)
00376         btn_set_ref = QtGui.QPushButton()
00377         btn_set_ref.setText("Set Reference")
00378         btn_set_ref.setFixedWidth(130)
00379         btn_set_ref.setIcon(QtGui.QIcon(self.icon_dir + '/iconHand.png'))
00380         btn_frame.connect(btn_set_ref, QtCore.SIGNAL('clicked()'), self.set_reference_grasp)
00381         btn_layout.addWidget(btn_set_ref)
00382 
00383         btn_frame.setLayout(btn_layout)
00384         sublayout.addWidget(btn_frame)
00385         subframe.setLayout(sublayout)
00386 
00387         self.grasp_from_chooser = GraspChooser(self._widget, self, "From: ")
00388         self.layout.addWidget(self.grasp_from_chooser)
00389         self.layout.addWidget(subframe)
00390 
00391         self.grasp_to_chooser = GraspChooser(self._widget, self, "To: ")
00392         self.layout.addWidget(self.grasp_to_chooser)
00393 
00394         self.grasp_slider.draw()
00395         self.grasp_to_chooser.draw()
00396         self.grasp_from_chooser.draw()
00397 
00398         time.sleep(0.2)
00399         self.set_reference_grasp()
00400 
00401     def shutdown_plugin(self):
00402         self._widget.close()
00403         self._widget.deleteLater()
00404 
00405     def save_settings(self, global_settings, perspective_settings):
00406         pass
00407 
00408     def restore_settings(self, global_settings, perspective_settings):
00409         pass
00410 
00411     def save_grasp(self):
00412         all_joints = self.sr_lib.read_all_current_positions()
00413         GraspSaver(self._widget, all_joints, self)
00414 
00415     def set_reference_grasp(self):
00416         """
00417         Set the current grasp as a reference for interpolation
00418         """
00419         self.current_grasp.joints_and_positions = self.sr_lib.read_all_current_positions()
00420         
00421         if self.current_grasp.joints_and_positions is None:
00422             #We try to activate ethercat hand again (detect if any controllers are running, and listen to them to extract the current position)
00423             self.sr_lib.activate_etherCAT_hand()
00424             #Some time to start receiving data
00425             rospy.sleep(0.5)
00426             self.current_grasp.joints_and_positions = self.sr_lib.read_all_current_positions()
00427         
00428             if self.current_grasp.joints_and_positions is None:
00429                 QMessageBox.warning(self._widget, "Warning", "Could not read current grasp.\nCheck that the hand controllers are running.\nThen click \"Set Reference\"")
00430                 return
00431 
00432         self.grasp_interpoler_1 = GraspInterpoler(self.grasp_from_chooser.grasp, self.current_grasp)
00433         self.grasp_interpoler_2 = GraspInterpoler(self.current_grasp, self.grasp_to_chooser.grasp)
00434 
00435         self.grasp_slider.slider.setValue(0)
00436 
00437     def grasp_changed(self):
00438         """
00439         interpolate grasps from chosen to current one and from current to chosen
00440         hand controllers must be running and reference must be set
00441         """
00442         self.current_grasp.joints_and_positions = self.sr_lib.read_all_current_positions()
00443         
00444         if self.current_grasp.joints_and_positions is None:
00445             QMessageBox.warning(self._widget, "Warning", "Could not read current grasp.\nCheck that the hand controllers are running.\nThen click \"Set Reference\"")
00446             return
00447         
00448         self.grasp_interpoler_1 = GraspInterpoler(self.grasp_from_chooser.grasp, self.current_grasp)
00449         self.grasp_interpoler_2 = GraspInterpoler(self.current_grasp, self.grasp_to_chooser.grasp)
00450 
00451     def interpolate_grasps(self, value):
00452         """
00453         interpolate grasp from the current one to the one indicated by value
00454         or in the opposite direction if value < 0
00455         hand controllers must be running and reference must be set
00456         """
00457         if self.grasp_interpoler_1 is None \
00458             or self.grasp_interpoler_2 is None:
00459             QMessageBox.warning(self._widget, "Warning", "Could not read current grasp.\nCheck that the hand controllers are running.\nThen click \"Set Reference\"")
00460             return
00461         #from -> current
00462         if value < 0:
00463             targets_to_send = self.grasp_interpoler_1.interpolate(100 + value)
00464             self.sr_lib.sendupdate_from_dict(targets_to_send)
00465         else:   #current -> to
00466             targets_to_send = self.grasp_interpoler_2.interpolate(value)
00467             self.sr_lib.sendupdate_from_dict(targets_to_send)


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