00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016 import os, time
00017 import roslib; roslib.load_manifest('sr_gui_grasp_controller')
00018 import rospy
00019
00020 from rospy import loginfo, logerr, logdebug
00021
00022 from qt_gui.plugin import Plugin
00023 from python_qt_binding import loadUi
00024
00025 import QtCore
00026 from QtCore import Qt, QEvent, QObject
00027 import QtGui
00028 from QtGui import *
00029
00030 from Grasp import Grasp
00031 from grasps_interpoler import GraspInterpoler
00032 from grasps_parser import GraspParser
00033
00034 from shadowhand_ros import ShadowHand_ROS
00035
00036 class JointSelecter(QtGui.QWidget):
00037 """
00038 Select which joints to save in a new grasp
00039 """
00040 def __init__(self, parent, all_joints):
00041 QtGui.QWidget.__init__(self, parent=parent)
00042 self.frame = QtGui.QFrame()
00043 self.layout = QtGui.QGridLayout()
00044 self.checkboxes = []
00045
00046 col = 0
00047
00048 rows = [0, 0, 0, 0, 0, 0]
00049 joint_names = all_joints.keys()
00050 joint_names.sort()
00051 for joint in joint_names:
00052 if "fj1" in joint.lower():
00053 continue
00054 if "fj2" in joint.lower():
00055 continue
00056 if "ff" in joint.lower():
00057 col = 0
00058 elif "mf" in joint.lower():
00059 col = 1
00060 elif "rf" in joint.lower():
00061 col = 2
00062 elif "lf" in joint.lower():
00063 col = 3
00064 elif "th" in joint.lower():
00065 col = 4
00066 else:
00067 col = 5
00068
00069 row = rows[col]
00070 rows[col] = row + 1
00071 cb = QtGui.QCheckBox(str(joint), self.frame)
00072 self.checkboxes.append(cb)
00073 self.layout.addWidget(cb, row, col)
00074
00075 self.frame.setLayout(self.layout)
00076 layout = QtGui.QVBoxLayout()
00077 layout.addWidget(self.frame)
00078 self.frame.show()
00079 self.setLayout(layout)
00080 self.show()
00081
00082 def get_selected(self):
00083 joints = []
00084 for cb in self.checkboxes:
00085 if cb.isChecked():
00086 joints.append(str(cb.text()))
00087
00088 return joints
00089
00090 def select_all(self):
00091 for cb in self.checkboxes:
00092 cb.setChecked(True)
00093
00094 def deselect_all(self):
00095 for cb in self.checkboxes:
00096 cb.setChecked(False)
00097
00098 class GraspSaver(QtGui.QDialog):
00099 """
00100 Save a new grasp from the current joints positions.
00101 """
00102 def __init__(self, parent, all_joints, plugin_parent):
00103 QtGui.QDialog.__init__(self, parent)
00104 self.plugin_parent = plugin_parent
00105 self.all_joints = all_joints
00106 self.setModal(True)
00107 self.setWindowTitle("Save Grasp")
00108
00109 self.grasp_name = ""
00110
00111 self.upper_frame = QtGui.QFrame()
00112 self.upper_layout = QtGui.QHBoxLayout()
00113 label_name = QtGui.QLabel()
00114 label_name.setText("Grasp Name: ")
00115 name_widget = QtGui.QLineEdit()
00116 self.upper_frame.connect(name_widget, QtCore.SIGNAL('textChanged(QString)'), self.name_changed)
00117
00118 self.upper_layout.addWidget(label_name)
00119 self.upper_layout.addWidget(name_widget)
00120 self.upper_frame.setLayout(self.upper_layout)
00121
00122 select_all_frame = QtGui.QFrame()
00123 select_all_layout = QtGui.QHBoxLayout()
00124 btn_select_all = QtGui.QPushButton(select_all_frame)
00125 btn_select_all.setText("Select All")
00126 select_all_layout.addWidget(btn_select_all)
00127 self.connect(btn_select_all, QtCore.SIGNAL("clicked()"), self.select_all)
00128 btn_deselect_all = QtGui.QPushButton(select_all_frame)
00129 btn_deselect_all.setText("Deselect All")
00130 select_all_layout.addWidget(btn_deselect_all)
00131 self.connect(btn_deselect_all, QtCore.SIGNAL("clicked()"), self.deselect_all)
00132 select_all_frame.setLayout(select_all_layout)
00133
00134 self.joint_selecter = JointSelecter(self, self.all_joints)
00135
00136 btn_frame = QtGui.QFrame()
00137 self.btn_ok = QtGui.QPushButton(btn_frame)
00138 self.btn_ok.setText("OK")
00139 self.btn_ok.setDisabled(True)
00140 self.connect(self.btn_ok, QtCore.SIGNAL("clicked()"), self.accept)
00141 btn_cancel = QtGui.QPushButton(btn_frame)
00142 btn_cancel.setText("Cancel")
00143 self.connect(btn_cancel, QtCore.SIGNAL("clicked()"), self.reject)
00144
00145 btn_layout = QtGui.QHBoxLayout()
00146 btn_layout.addWidget(self.btn_ok)
00147 btn_layout.addWidget(btn_cancel)
00148 btn_frame.setLayout(btn_layout)
00149
00150 self.layout = QtGui.QVBoxLayout()
00151 self.layout.addWidget(self.upper_frame)
00152 self.layout.addWidget(select_all_frame)
00153 self.layout.addWidget(self.joint_selecter)
00154 self.layout.addWidget(btn_frame)
00155
00156 self.setLayout(self.layout)
00157 self.show()
00158
00159 def select_all(self):
00160 self.joint_selecter.select_all()
00161
00162 def deselect_all(self):
00163 self.joint_selecter.deselect_all()
00164
00165 def name_changed(self, name):
00166 self.grasp_name = name
00167 if self.grasp_name != "":
00168 self.btn_ok.setEnabled(True)
00169 else:
00170 self.btn_ok.setDisabled(True)
00171
00172 def accept(self):
00173 grasp = Grasp()
00174 grasp.grasp_name = self.grasp_name
00175
00176 joints_to_save = self.joint_selecter.get_selected()
00177 if len(joints_to_save) == 0:
00178 joints_to_save = self.all_joints.keys()
00179 for joint_to_save in joints_to_save:
00180 grasp.joints_and_positions[joint_to_save] = self.all_joints[joint_to_save]
00181
00182 self.plugin_parent.sr_lib.grasp_parser.write_grasp_to_file(grasp)
00183 self.plugin_parent.sr_lib.grasp_parser.refresh()
00184
00185 self.plugin_parent.reloadGraspSig['int'].emit(1)
00186
00187 QtGui.QDialog.accept(self)
00188
00189 class GraspChooser(QtGui.QWidget):
00190 """
00191 Choose a grasp from a list of grasps.
00192 """
00193 def __init__(self, parent, plugin_parent, title):
00194 QtGui.QWidget.__init__(self)
00195 self.plugin_parent = plugin_parent
00196 self.grasp = None
00197 self.title = QtGui.QLabel()
00198 self.title.setText(title)
00199
00200 def draw(self):
00201 self.frame = QtGui.QFrame(self)
00202
00203 self.list = QtGui.QListWidget()
00204 first_item = self.refresh_list()
00205 self.connect(self.list, QtCore.SIGNAL('itemClicked(QListWidgetItem*)'), self.grasp_choosed)
00206
00207 self.connect(self.list, QtCore.SIGNAL('itemDoubleClicked(QListWidgetItem*)'), self.double_click)
00208 self.list.setViewMode(QtGui.QListView.ListMode)
00209 self.list.setResizeMode(QtGui.QListView.Adjust)
00210 self.list.setItemSelected(first_item, True)
00211 self.grasp_choosed(first_item, first_time=True)
00212
00213 self.layout = QtGui.QVBoxLayout()
00214 self.layout.addWidget(self.title)
00215 self.layout.addWidget(self.list)
00216
00217
00218
00219
00220 self.plugin_parent.reloadGraspSig['int'].connect(self.refresh_list)
00221
00222 self.frame.setLayout(self.layout)
00223 layout = QtGui.QVBoxLayout()
00224 layout.addWidget(self.frame)
00225 self.frame.show()
00226 self.setLayout(layout)
00227 self.show()
00228
00229 def double_click(self, item):
00230 self.grasp = self.plugin_parent.sr_lib.grasp_parser.grasps[str(item.text())]
00231 self.plugin_parent.sr_lib.sendupdate_from_dict(self.grasp.joints_and_positions)
00232 self.plugin_parent.set_reference_grasp()
00233
00234 def grasp_choosed(self, item, first_time=False):
00235 self.grasp = self.plugin_parent.sr_lib.grasp_parser.grasps[str(item.text())]
00236 if not first_time:
00237 self.plugin_parent.grasp_changed()
00238 self.plugin_parent.set_reference_grasp()
00239
00240 def refresh_list(self, value = 0):
00241 self.list.clear()
00242 first_item = None
00243 grasps = self.plugin_parent.sr_lib.grasp_parser.grasps.keys()
00244 grasps.sort()
00245 for grasp_name in grasps:
00246 item = QtGui.QListWidgetItem(grasp_name)
00247 if first_item == None:
00248 first_item = item
00249 self.list.addItem(item)
00250 return first_item
00251
00252 class GraspSlider(QtGui.QWidget):
00253 """
00254 Slide from one grasp to another.
00255 """
00256 def __init__(self, parent, plugin_parent):
00257 QtGui.QWidget.__init__(self, parent)
00258 self.plugin_parent = plugin_parent
00259
00260 def draw(self):
00261 self.frame = QtGui.QFrame(self)
00262 label_frame = QtGui.QFrame(self.frame)
00263 from_label = QtGui.QLabel()
00264 from_label.setText("From")
00265 ref_label = QtGui.QLabel()
00266 ref_label.setText("Reference")
00267 to_label = QtGui.QLabel()
00268 to_label.setText("To")
00269 label_layout = QtGui.QHBoxLayout()
00270 label_layout.addWidget(from_label)
00271 label_layout.addWidget(ref_label)
00272 label_layout.addWidget(to_label)
00273
00274 label_frame.setLayout(label_layout)
00275
00276 self.slider = QtGui.QSlider()
00277 self.slider.setOrientation(QtCore.Qt.Horizontal)
00278 self.slider.setFocusPolicy(QtCore.Qt.NoFocus)
00279 self.slider.setTickInterval(100)
00280 self.slider.setTickPosition(QSlider.TicksAbove)
00281 self.slider.setMinimum(-100)
00282 self.slider.setMaximum(100)
00283
00284 self.connect(self.slider, QtCore.SIGNAL('valueChanged(int)'), self.changeValue)
00285
00286 self.layout = QtGui.QVBoxLayout()
00287 self.layout.addWidget(label_frame)
00288 self.layout.addWidget(self.slider)
00289
00290 self.frame.setLayout(self.layout)
00291 layout = QtGui.QVBoxLayout()
00292 layout.addWidget(self.frame)
00293 self.frame.show()
00294 self.setLayout(layout)
00295 self.show()
00296
00297 def changeValue(self, value):
00298 self.plugin_parent.interpolate_grasps(value)
00299
00300 class SrGuiGraspController(Plugin):
00301 """Main GraspController plugin Dock window."""
00302
00303 reloadGraspSig = QtCore.pyqtSignal(int)
00304
00305 def __init__(self, context):
00306 super(SrGuiGraspController, self).__init__(context)
00307
00308 self.setObjectName('SrGuiGraspController')
00309 self_dir = os.path.dirname(os.path.realpath(__file__));
00310 self.ui_dir = os.path.join(self_dir, '../../ui')
00311 self.img_dir = os.path.join(self_dir, '../../images')
00312 self.icon_dir = os.path.join(self_dir, '../../images/icons')
00313 self.sr_lib = ShadowHand_ROS()
00314
00315 ui_file = os.path.join(self.ui_dir, 'SrGuiGraspController.ui')
00316 self._widget = QWidget()
00317 loadUi(ui_file, self._widget)
00318 context.add_widget(self._widget)
00319
00320 self.current_grasp = Grasp()
00321 self.current_grasp.name = 'CURRENT_UNSAVED'
00322 self.grasp_interpoler_1 = None
00323 self.grasp_interpoler_2 = None
00324
00325 self.layout = self._widget.layout
00326
00327 subframe = QtGui.QFrame()
00328 sublayout = QtGui.QVBoxLayout()
00329
00330 self.grasp_slider = GraspSlider(self._widget, self)
00331 sublayout.addWidget(self.grasp_slider)
00332
00333 btn_frame = QtGui.QFrame()
00334 btn_layout = QtGui.QHBoxLayout()
00335 self.btn_save = QtGui.QPushButton()
00336 self.btn_save.setText("Save")
00337 self.btn_save.setFixedWidth(130)
00338 self.btn_save.setIcon(QtGui.QIcon(self.icon_dir + '/save.png'))
00339 btn_frame.connect(self.btn_save, QtCore.SIGNAL('clicked()'), self.save_grasp)
00340 btn_layout.addWidget(self.btn_save)
00341 btn_set_ref = QtGui.QPushButton()
00342 btn_set_ref.setText("Set Reference")
00343 btn_set_ref.setFixedWidth(130)
00344 btn_set_ref.setIcon(QtGui.QIcon(self.icon_dir + '/iconHand.png'))
00345 btn_frame.connect(btn_set_ref, QtCore.SIGNAL('clicked()'), self.set_reference_grasp)
00346 btn_layout.addWidget(btn_set_ref)
00347
00348 btn_frame.setLayout(btn_layout)
00349 sublayout.addWidget(btn_frame)
00350 subframe.setLayout(sublayout)
00351
00352 self.grasp_from_chooser = GraspChooser(self._widget, self, "From: ")
00353 self.layout.addWidget(self.grasp_from_chooser)
00354 self.layout.addWidget(subframe)
00355
00356 self.grasp_to_chooser = GraspChooser(self._widget, self, "To: ")
00357 self.layout.addWidget(self.grasp_to_chooser)
00358
00359 self.grasp_slider.draw()
00360 self.grasp_to_chooser.draw()
00361 self.grasp_from_chooser.draw()
00362
00363 time.sleep(0.2)
00364 self.set_reference_grasp()
00365
00366 def shutdown_plugin(self):
00367 self._widget.close()
00368 self._widget.deleteLater()
00369
00370 def save_settings(self, global_settings, perspective_settings):
00371 pass
00372
00373 def restore_settings(self, global_settings, perspective_settings):
00374 pass
00375
00376 def save_grasp(self):
00377 all_joints = self.sr_lib.read_all_current_positions()
00378 GraspSaver(self._widget, all_joints, self)
00379
00380 def set_reference_grasp(self):
00381 self.current_grasp.joints_and_positions = self.sr_lib.read_all_current_positions()
00382
00383 if self.current_grasp.joints_and_positions is None:
00384
00385 self.sr_lib.activate_etherCAT_hand()
00386
00387 rospy.sleep(0.5)
00388 self.current_grasp.joints_and_positions = self.sr_lib.read_all_current_positions()
00389
00390 if self.current_grasp.joints_and_positions is None:
00391 QMessageBox.warning(self._widget, "Warning", "Could not read current grasp.\nCheck that the hand controllers are running.\nThen click \"Set Reference\"")
00392 return
00393
00394 self.grasp_interpoler_1 = GraspInterpoler(self.grasp_from_chooser.grasp, self.current_grasp)
00395 self.grasp_interpoler_2 = GraspInterpoler(self.current_grasp, self.grasp_to_chooser.grasp)
00396
00397 self.grasp_slider.slider.setValue(0)
00398
00399 def grasp_changed(self):
00400 self.current_grasp.joints_and_positions = self.sr_lib.read_all_current_positions()
00401
00402 if self.current_grasp.joints_and_positions is None:
00403 QMessageBox.warning(self._widget, "Warning", "Could not read current grasp.\nCheck that the hand controllers are running.\nThen click \"Set Reference\"")
00404 return
00405
00406 self.grasp_interpoler_1 = GraspInterpoler(self.grasp_from_chooser.grasp, self.current_grasp)
00407 self.grasp_interpoler_2 = GraspInterpoler(self.current_grasp, self.grasp_to_chooser.grasp)
00408
00409 def interpolate_grasps(self, value):
00410 if self.grasp_interpoler_1 is None \
00411 or self.grasp_interpoler_2 is None:
00412 QMessageBox.warning(self._widget, "Warning", "Could not read current grasp.\nCheck that the hand controllers are running.\nThen click \"Set Reference\"")
00413 return
00414
00415 if value < 0:
00416 targets_to_send = self.grasp_interpoler_1.interpolate(100 + value)
00417 self.sr_lib.sendupdate_from_dict(targets_to_send)
00418 else:
00419 targets_to_send = self.grasp_interpoler_2.interpolate(value)
00420 self.sr_lib.sendupdate_from_dict(targets_to_send)