00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019 import rospy
00020
00021 from sr_robot_lib.etherCAT_hand_lib import EtherCAT_Hand_Lib
00022 from QtGui import QTreeWidgetItem, QTreeWidgetItemIterator, QColor, QIcon, QMessageBox
00023 from PyQt4.Qt import QTimer
00024 from PyQt4.QtCore import SIGNAL
00025
00026 import yaml
00027 try:
00028 from yaml import CLoader as Loader, CDumper as Dumper
00029 except ImportError:
00030 from yaml import Loader, Dumper
00031 import os
00032
00033 from collections import deque
00034
00035 green = QColor(153, 231, 96)
00036 orange = QColor(247, 206, 134)
00037 red = QColor(236, 178, 178)
00038
00039
00040 class IndividualCalibration(QTreeWidgetItem):
00041
00042 """
00043 Calibrate a single joint by raw and calibrated values
00044 Calibrated joints will appear as green
00045 or orange if calibrations are loaded from a file
00046 """
00047
00048 def __init__(self, joint_name,
00049 raw_value, calibrated_value,
00050 parent_widget, tree_widget,
00051 robot_lib):
00052 self.joint_name = joint_name
00053 self.raw_value = int(raw_value)
00054 self.calibrated_value = calibrated_value
00055 self.tree_widget = tree_widget
00056 self.robot_lib = robot_lib
00057
00058 QTreeWidgetItem.__init__(self, parent_widget, [
00059 "", "", str(self.raw_value), str(self.calibrated_value)])
00060
00061 for col in xrange(self.tree_widget.columnCount()):
00062 self.setBackgroundColor(col, QColor(red))
00063
00064 self.tree_widget.addTopLevelItem(self)
00065
00066 self.is_calibrated = False
00067
00068 def remove(self):
00069 self.tree_widget.remove
00070
00071 def calibrate(self):
00072 """
00073 Performs the joint calibration and sets background to green
00074 calibrate only the calibration lines, not the items for the fingers / joints / hand
00075 """
00076 self.raw_value = self.robot_lib.get_average_raw_value(
00077 self.joint_name, 100)
00078 self.setText(2, str(self.raw_value))
00079
00080 for col in xrange(self.tree_widget.columnCount()):
00081 if self.text(2) != "":
00082 self.setBackgroundColor(col, QColor(green))
00083
00084 self.is_calibrated = True
00085
00086 def set_is_loaded_calibration(self):
00087 """
00088 set the background to orange: those values are loaded
00089 from the file, not recalibrated
00090 """
00091 for col in xrange(self.tree_widget.columnCount()):
00092 if self.text(2) != "":
00093 self.setBackgroundColor(col, QColor(orange))
00094
00095 self.is_calibrated = True
00096
00097 def get_calibration(self):
00098 return [self.raw_value, self.calibrated_value]
00099
00100
00101 class JointCalibration(QTreeWidgetItem):
00102
00103 """
00104 Calibrate a single joint by calibrations list
00105 Also displays the current joint position in the GUI
00106 """
00107
00108 nb_values_to_check = 5
00109
00110 def __init__(self, joint_name,
00111 calibrations,
00112 parent_widget, tree_widget,
00113 robot_lib):
00114 self.joint_name = joint_name
00115 self.tree_widget = tree_widget
00116 self.robot_lib = robot_lib
00117
00118 self.calibrations = []
00119
00120 self.last_raw_values = deque()
00121
00122 QTreeWidgetItem.__init__(
00123 self, parent_widget, ["", joint_name, "", ""])
00124
00125 for calibration in calibrations:
00126 self.calibrations.append(IndividualCalibration(joint_name,
00127 calibration[0], calibration[1],
00128 self, tree_widget, robot_lib))
00129
00130
00131 self.timer = QTimer()
00132 self.timer.start(200)
00133 tree_widget.addTopLevelItem(self)
00134 tree_widget.connect(
00135 self.timer, SIGNAL('timeout()'), self.update_joint_pos)
00136
00137 def load_joint_calibration(self, new_calibrations):
00138 for calibration in self.calibrations:
00139 self.removeChild(calibration)
00140 self.calibrations = []
00141
00142 for calibration in new_calibrations:
00143 new_calib = IndividualCalibration(self.joint_name,
00144 calibration[0], calibration[1],
00145 self, self.tree_widget, self.robot_lib)
00146 new_calib.set_is_loaded_calibration()
00147 self.calibrations.append(new_calib)
00148
00149 def get_joint_calibration(self):
00150 config = []
00151 for calibration in self.calibrations:
00152 if calibration.is_calibrated:
00153 config.append(calibration.get_calibration())
00154
00155 if len(config) <= 1:
00156
00157
00158 config = [[0, 0.0], [1, 0.0]]
00159 return [self.joint_name, config]
00160
00161 def update_joint_pos(self):
00162 """
00163 Update the joint position if there are enough nonequal values
00164 If the values are equal it can be assumed the sensor are not measuring properly
00165 """
00166 raw_value = self.robot_lib.get_raw_value(self.joint_name)
00167 self.setText(2, str(raw_value))
00168
00169
00170
00171 self.last_raw_values.append(raw_value)
00172 if len(self.last_raw_values) > self.nb_values_to_check:
00173 self.last_raw_values.popleft()
00174
00175
00176 all_equal = True
00177 last_data = self.last_raw_values[0]
00178 for data in self.last_raw_values:
00179 if data != last_data:
00180 all_equal = False
00181 break
00182 if all_equal:
00183 self.setIcon(
00184 0, QIcon(os.path.join(os.path.dirname(os.path.realpath(__file__)), '../icons/warn.gif')))
00185 self.setToolTip(0, "No noise on the data for the last " + str(
00186 self.nb_values_to_check) + " values, there could be a problem with the sensor.")
00187 else:
00188 self.setIcon(0, QIcon())
00189 self.setToolTip(0, "")
00190
00191 def on_close(self):
00192 self.timer.stop()
00193
00194
00195 class FingerCalibration(QTreeWidgetItem):
00196
00197 """
00198 calibrate all joints of a finger
00199 """
00200
00201 def __init__(self, finger_name,
00202 finger_joints,
00203 parent_widget, tree_widget,
00204 robot_lib):
00205
00206 QTreeWidgetItem.__init__(
00207 self, parent_widget, [finger_name, "", "", ""])
00208
00209 self.joints = []
00210 for joint in finger_joints:
00211 self.joints.append(JointCalibration(joint_name=joint[0],
00212 calibrations=joint[1],
00213 parent_widget=self,
00214 tree_widget=tree_widget,
00215 robot_lib=robot_lib))
00216
00217 tree_widget.addTopLevelItem(self)
00218
00219
00220 class HandCalibration(QTreeWidgetItem):
00221
00222 """
00223 calibrate all joints of all fingers of a hand
00224 """
00225
00226 joint_map = {"First Finger": [["FFJ1", [[0.0, 0.0],
00227 [0.0, 22.5],
00228 [0.0, 45.0],
00229 [0.0, 67.5],
00230 [0.0, 90.0]]],
00231 ["FFJ2", [[0.0, 0.0],
00232 [0.0, 22.5],
00233 [0.0, 45.0],
00234 [0.0, 67.5],
00235 [0.0, 90.0]]],
00236 ["FFJ3", [[0.0, 0.0],
00237 [0.0, 22.5],
00238 [0.0, 45.0],
00239 [0.0, 67.5],
00240 [0.0, 90.0]]],
00241 ["FFJ4", [[0.0, -20.0],
00242 [0.0, -10.0],
00243 [0.0, 0.0],
00244 [0.0, 10.0],
00245 [0.0, 20.0]]]],
00246
00247 "Middle Finger": [["MFJ1", [[0.0, 0.0],
00248 [0.0, 22.5],
00249 [0.0, 45.0],
00250 [0.0, 67.5],
00251 [0.0, 90.0]]],
00252 ["MFJ2", [[0.0, 0.0],
00253 [0.0, 22.5],
00254 [0.0, 45.0],
00255 [0.0, 67.5],
00256 [0.0, 90.0]]],
00257 ["MFJ3", [[0.0, 0.0],
00258 [0.0, 22.5],
00259 [0.0, 45.0],
00260 [0.0, 67.5],
00261 [0.0, 90.0]]],
00262 ["MFJ4", [[0.0, -20.0],
00263 [0.0, -10.0],
00264 [0.0, 0.0],
00265 [0.0, 10.0],
00266 [0.0, 20.0]]]],
00267
00268 "Ring Finger": [["RFJ1", [[0.0, 0.0],
00269 [0.0, 22.5],
00270 [0.0, 45.0],
00271 [0.0, 67.5],
00272 [0.0, 90.0]]],
00273 ["RFJ2", [[0.0, 0.0],
00274 [0.0, 22.5],
00275 [0.0, 45.0],
00276 [0.0, 67.5],
00277 [0.0, 90.0]]],
00278 ["RFJ3", [[0.0, 0.0],
00279 [0.0, 22.5],
00280 [0.0, 45.0],
00281 [0.0, 67.5],
00282 [0.0, 90.0]]],
00283 ["RFJ4", [[0.0, -20.0],
00284 [0.0, -10.0],
00285 [0.0, 0.0],
00286 [0.0, 10.0],
00287 [0.0, 20.0]]]],
00288
00289 "Little Finger": [["LFJ1", [[0.0, 0.0],
00290 [0.0, 22.5],
00291 [0.0, 45.0],
00292 [0.0, 67.5],
00293 [0.0, 90.0]]],
00294 ["LFJ2", [[0.0, 0.0],
00295 [0.0, 22.5],
00296 [0.0, 45.0],
00297 [0.0, 67.5],
00298 [0.0, 90.0]]],
00299 ["LFJ3", [[0.0, 0.0],
00300 [0.0, 22.5],
00301 [0.0, 45.0],
00302 [0.0, 67.5],
00303 [0.0, 90.0]]],
00304 ["LFJ4", [[0.0, -20.0],
00305 [0.0, -10.0],
00306 [0.0, 0.0],
00307 [0.0, 10.0],
00308 [0.0, 20.0]]],
00309 ["LFJ5", [[0.0, 0.0],
00310 [0.0, 22.5],
00311 [0.0, 45.0],
00312 [0.0, 67.5],
00313 [0.0, 90.0]]]],
00314
00315 "Thumb": [["THJ1", [[0.0, 0.0],
00316 [0.0, 22.5],
00317 [0.0, 45.0],
00318 [0.0, 67.5],
00319 [0.0, 90.0]]],
00320 ["THJ2", [[0.0, -40.0],
00321 [0.0, -20.0],
00322 [0.0, 0.0],
00323 [0.0, 20.0],
00324 [0.0, 40.0]]],
00325 ["THJ3", [[0.0, -15.0],
00326 [0.0, 0.0],
00327 [0.0, 15.0]]],
00328 ["THJ4", [[0.0, 0.0],
00329 [0.0, 22.5],
00330 [0.0, 45.0],
00331 [0.0, 67.5]]],
00332 ["THJ5", [[0.0, -60.0],
00333 [0.0, -30.0],
00334 [0.0, 0.0],
00335 [0.0, 30.0],
00336 [0.0, 60.0]]]],
00337
00338 "Wrist": [["WRJ1", [[0.0, -45.0],
00339 [0.0, -22.5],
00340 [0.0, 0.0],
00341 [0.0, 15.0],
00342 [0.0, 30.0]]],
00343 ["WRJ2", [[0.0, -30.0],
00344 [0.0, 0.0],
00345 [0.0, 10.0]]]]
00346 }
00347
00348 def __init__(self,
00349 tree_widget,
00350 progress_bar,
00351 fingers=["First Finger", "Middle Finger",
00352 "Ring Finger", "Little Finger",
00353 "Thumb", "Wrist"]):
00354 self.fingers = []
00355
00356
00357 self.is_active = True
00358
00359 QTreeWidgetItem.__init__(self, ["Hand", "", "", ""])
00360
00361 self.robot_lib = EtherCAT_Hand_Lib()
00362 if not self.robot_lib.activate():
00363 btn_pressed = QMessageBox.warning(
00364 tree_widget, "Warning", "The EtherCAT Hand node doesn't seem to be running, or the debug topic is not"
00365 " being published. Do you still want to continue? The calibration will be useless.",
00366 buttons=QMessageBox.Ok | QMessageBox.Cancel)
00367
00368 if btn_pressed == QMessageBox.Cancel:
00369 self.is_active = False
00370
00371 for finger in fingers:
00372 if finger in self.joint_map.keys():
00373 self.fingers.append(FingerCalibration(finger,
00374 self.joint_map[finger],
00375 self, tree_widget,
00376 self.robot_lib))
00377
00378 else:
00379 print finger, " not found in the calibration map"
00380
00381 self.joint_0_calibration_index = 0
00382
00383 self.progress_bar = progress_bar
00384
00385 self.tree_widget = tree_widget
00386 self.tree_widget.addTopLevelItem(self)
00387 self.tree_widget.itemActivated.connect(self.calibrate_item)
00388
00389 def unregister(self):
00390 it = QTreeWidgetItemIterator(self)
00391 while it.value():
00392 try:
00393 it.value().on_close()
00394 except:
00395 pass
00396 it += 1
00397
00398 self.robot_lib.on_close()
00399
00400 def calibrate_item(self, item):
00401 try:
00402
00403 item.calibrate()
00404 except:
00405 pass
00406
00407 self.progress()
00408
00409
00410 self.tree_widget.setItemSelected(item, False)
00411 next_item = self.tree_widget.itemBelow(item)
00412 self.tree_widget.setItemSelected(next_item, True)
00413 self.tree_widget.setCurrentItem(next_item)
00414
00415 def calibrate_joint0s(self, btn_joint_0s):
00416 joint0s = ["FFJ1", "FFJ2",
00417 "MFJ1", "MFJ2",
00418 "RFJ1", "RFJ2",
00419 "LFJ1", "LFJ2"]
00420
00421 it = QTreeWidgetItemIterator(self)
00422 while it.value():
00423 if it.value().text(1) in joint0s:
00424 it += self.joint_0_calibration_index + 1
00425 it.value().calibrate()
00426 it += 1
00427
00428 self.joint_0_calibration_index += 1
00429 if self.joint_0_calibration_index == len(self.joint_map["First Finger"][0][1]):
00430 self.joint_0_calibration_index = 0
00431
00432
00433 btn_joint_0s.setText(
00434 "Save all Joint 0s (angle = " +
00435 str(self.joint_map["First Finger"][0][1][self.joint_0_calibration_index][1]) + ")")
00436
00437 self.progress()
00438
00439 def progress(self):
00440 it = QTreeWidgetItemIterator(self)
00441 nb_of_items = 0
00442 nb_of_calibrated_items = 0
00443 while it.value():
00444 it += 1
00445 try:
00446 if it.value().is_calibrated:
00447 nb_of_calibrated_items += 1
00448 nb_of_items += 1
00449 except:
00450 pass
00451
00452 self.progress_bar.setValue(
00453 int(float(nb_of_calibrated_items) / float(nb_of_items) * 100.0))
00454
00455 def load(self, filepath):
00456 f = open(filepath, 'r')
00457 document = ""
00458 for line in f.readlines():
00459 document += line
00460 f.close()
00461 yaml_config = yaml.load(document)
00462
00463 for joint in yaml_config["sr_calibrations"]:
00464 it = QTreeWidgetItemIterator(self)
00465 while it.value():
00466 if it.value().text(1) == joint[0]:
00467 it.value().load_joint_calibration(joint[1])
00468 it += 1
00469
00470 def save(self, filepath):
00471 yaml_config = {}
00472
00473 joint_configs = []
00474 it = QTreeWidgetItemIterator(self)
00475 while it.value():
00476 try:
00477 joint_configs.append(it.value().get_joint_calibration())
00478 except:
00479 pass
00480 it += 1
00481
00482
00483
00484
00485
00486 full_config_to_write = "{\'sr_calibrations\': [\n"
00487 for joint_config in joint_configs:
00488 full_config_to_write += "[\""
00489 full_config_to_write += joint_config[0] + "\", "
00490
00491
00492 for index, calib in enumerate(joint_config[1]):
00493 joint_config[1][index][0] = float(calib[0])
00494 joint_config[1][index][1] = float(calib[1])
00495
00496 full_config_to_write += str(joint_config[1])
00497 full_config_to_write += "], \n"
00498 full_config_to_write += "]}"
00499
00500 f = open(filepath, 'w')
00501 f.write(full_config_to_write)
00502 f.close()
00503
00504 def is_calibration_complete(self):
00505 it = QTreeWidgetItemIterator(self)
00506 while it.value():
00507 try:
00508 if not it.value().is_calibrated:
00509 return False
00510 except:
00511 pass
00512 it += 1
00513
00514 return True