21 from sr_utilities.hand_finder
import HandFinder
22 from sr_robot_lib.etherCAT_hand_lib
import EtherCAT_Hand_Lib
23 from PyQt5.QtGui
import QColor, QIcon
24 from PyQt5.QtWidgets
import QTreeWidget, QTreeWidgetItem, QTreeWidgetItemIterator, QMessageBox, QPushButton
25 from PyQt5.QtCore
import QTimer, pyqtSignal
29 from yaml
import CLoader
as Loader, CDumper
as Dumper
31 from yaml
import Loader, Dumper
34 from collections
import deque
36 green = QColor(153, 231, 96)
37 orange = QColor(247, 206, 134)
38 red = QColor(236, 178, 178)
44 Calibrate a single joint by raw and calibrated values 45 Calibrated joints will appear as green 46 or orange if calibrations are loaded from a file 50 raw_value, calibrated_value,
51 parent_widget, tree_widget,
59 QTreeWidgetItem.__init__(self, parent_widget, [
63 self.setBackground(col, QColor(red))
74 Performs the joint calibration and sets background to green 75 calibrate only the calibration lines, not the items for the fingers / joints / hand 78 self.
joint_name, number_of_samples=100, accept_zeros=
False)
82 if self.text(2) !=
"":
83 self.setBackground(col, QColor(green))
89 set the background to orange: those values are loaded 90 from the file, not recalibrated 93 if self.text(2) !=
"":
94 self.setBackground(col, QColor(orange))
105 Calibrate coupled joints by raw and calibrated values 106 Calibrated joints will appear as green 107 or orange if calibrations are loaded from a file 111 raw_values, calibrated_values,
112 parent_widget, tree_widget,
116 self.
raw_values = [int(raw_value)
for raw_value
in raw_values]
121 QTreeWidgetItem.__init__(self, parent_widget, [
126 self.setBackground(col, QColor(red))
134 Performs the joint calibration and sets background to green 135 calibrate only the calibration lines, not the items for the fingers / joints / hand 138 for idx
in range(0, 2):
141 raw_values_str.append(str(self.
raw_values[idx]))
142 self.setText(2,
", ".join(raw_values_str))
145 if self.text(2) !=
"":
146 self.setBackground(col, QColor(green))
157 Calibrate a single joint by calibrations list 158 Also displays the current joint position in the GUI 161 nb_values_to_check = 5
165 parent_widget, tree_widget,
166 robot_lib, package_path):
179 QTreeWidgetItem.__init__(
180 self, parent_widget, [
"", joint_name,
"",
""])
181 tree_widget.setItemWidget(self, 2, self.
plot_button)
182 for calibration
in calibrations:
184 calibration[0], calibration[1],
185 self, tree_widget, robot_lib))
188 QTreeWidgetItem.__init__(
189 self, parent_widget, [
"", joint_name[0] +
", " + joint_name[1],
"",
""])
190 tree_widget.setItemWidget(self, 2, self.
plot_button)
191 for calibration
in calibrations:
193 calibration[0], calibration[1],
194 self, tree_widget, robot_lib))
201 self.
timer.start(200)
203 tree_widget.addTopLevelItem(self)
207 temporary_file_name =
"{}/resource/tmp_plot.xml".format(self.
package_path)
211 template_filename =
"{}/resource/rqt_multiplot_1_sensor.xml".format(self.
package_path)
214 process = [
"rosrun",
"rqt_multiplot",
"rqt_multiplot",
"--multiplot-config", temporary_file_name,
215 "--multiplot-run-all"]
218 template_filename =
"{}/resource/plotjuggler_2_sensors.xml".format(self.
package_path)
222 replace_list.append([
"sensor_id_{}".format(i), str(sensor_index)])
223 replace_list.append([
"sensor_name_{}".format(i), sensor_names[i]])
224 process = [
"rosrun",
"plotjuggler",
"plotjuggler",
"-n",
"-l", temporary_file_name]
227 template_filename =
"{}/resource/plotjuggler_2_sensors.xml".format(self.
package_path)
229 for i, joint_name
in enumerate(self.
joint_name):
230 replace_list.append([
"sensor_id_{}".format(i), str(self.
raw_value_index[i])])
231 replace_list.append([
"sensor_name_{}".format(i), joint_name])
232 process = [
"rosrun",
"plotjuggler",
"plotjuggler",
"-n",
"-l", temporary_file_name]
234 with open(template_filename,
"r") as f: 237 rospy.logerr(
"Failed to open multiplot template file: {}".format(template_filename))
240 hand_finder = HandFinder()
241 prefix = hand_finder.get_available_prefix()
243 replace_list.append([
'/rh/',
'/lh/'])
244 for replacement
in replace_list:
245 template = template.replace(replacement[0], replacement[1])
247 with open(temporary_file_name,
"w+")
as f:
250 rospy.logerr(
"Failed to write temportary multiplot configuration file: {}".format(temporary_file_name))
256 self.removeChild(calibration)
259 for calibration
in new_calibrations:
262 calibration[0], calibration[1],
266 calibration[0], [calibration[1], calibration[2]],
268 new_calib.set_is_loaded_calibration()
274 if calibration.is_calibrated:
275 config.append(calibration.get_calibration())
281 config = [[0, 0.0], [1, 0.0]]
283 config = [[[0, 0], [0.0, 0.0]], [[1, 1], [0.0, 0.0]]]
288 Update the joint position if there are enough nonequal values 289 If the values are equal it can be assumed the sensor are not measuring properly 298 self.
plot_button.setText(str(raw_value[0]) +
", " + str(raw_value[1]))
310 if type(data)
is not list:
311 last_data_not_equal = data != last_data
313 last_data_not_equal = (data[0] != last_data[0]
or data[1] != last_data[1])
314 if last_data_not_equal:
319 0, QIcon(os.path.join(os.path.dirname(os.path.realpath(__file__)),
'../icons/warn.gif')))
320 self.setToolTip(0,
"No noise on the data for the last " + str(
323 self.setIcon(0, QIcon())
324 self.setToolTip(0,
"")
335 calibrate all joints of a finger 340 parent_widget, tree_widget,
341 robot_lib, package_path):
343 QTreeWidgetItem.__init__(
344 self, parent_widget, [finger_name,
"",
"",
""])
347 for joint
in finger_joints:
349 calibrations=joint[1],
351 tree_widget=tree_widget,
353 package_path=package_path))
355 tree_widget.addTopLevelItem(self)
361 calibrate all joints of all fingers of a hand 367 fingers=["First Finger", "Middle Finger",
368 "Ring Finger", "Little Finger",
374 self.
package_path = rospkg.RosPack().get_path(
'sr_gui_hand_calibration')
377 self.
joint_map = {
"First Finger": [[
"FFJ1", [[0.0, 0.0],
382 [
"FFJ2", [[0.0, 0.0],
387 [
"FFJ3", [[0.0, 0.0],
392 [
"FFJ4", [[0.0, -20.0],
398 "Middle Finger": [[
"MFJ1", [[0.0, 0.0],
403 [
"MFJ2", [[0.0, 0.0],
408 [
"MFJ3", [[0.0, 0.0],
413 [
"MFJ4", [[0.0, -20.0],
419 "Ring Finger": [[
"RFJ1", [[0.0, 0.0],
424 [
"RFJ2", [[0.0, 0.0],
429 [
"RFJ3", [[0.0, 0.0],
434 [
"RFJ4", [[0.0, -20.0],
440 "Little Finger": [[
"LFJ1", [[0.0, 0.0],
445 [
"LFJ2", [[0.0, 0.0],
450 [
"LFJ3", [[0.0, 0.0],
455 [
"LFJ4", [[0.0, -20.0],
460 [
"LFJ5", [[0.0, 0.0],
466 "Wrist": [[
"WRJ1", [[0.0, -45.0],
471 [
"WRJ2", [[0.0, -30.0],
477 self.
joint_map[
"Thumb"] = [[[
"THJ1",
"THJ2"], [[[0.0, 0.0], [0.0, 40]],
478 [[0.0, 0.0], [0.0, 20]],
479 [[0.0, 0.0], [0.0, 0.0]],
480 [[0.0, 0.0], [0.0, -20.0]],
481 [[0.0, 0.0], [0.0, -40.0]],
482 [[0.0, 0.0], [22.5, 40.0]],
483 [[0.0, 0.0], [22.5, 20.0]],
484 [[0.0, 0.0], [22.5, 0.0]],
485 [[0.0, 0.0], [22.5, -20.0]],
486 [[0.0, 0.0], [22.5, -40.0]],
487 [[0.0, 0.0], [45.0, 40.0]],
488 [[0.0, 0.0], [45.0, 20.0]],
489 [[0.0, 0.0], [45.0, 0.0]],
490 [[0.0, 0.0], [45.0, -20.0]],
491 [[0.0, 0.0], [45.0, -40.0]],
492 [[0.0, 0.0], [67.5, 40.0]],
493 [[0.0, 0.0], [67.5, 20.0]],
494 [[0.0, 0.0], [67.5, 0.0]],
495 [[0.0, 0.0], [67.5, -20.0]],
496 [[0.0, 0.0], [67.5, -40.0]],
497 [[0.0, 0.0], [90.0, 40.0]],
498 [[0.0, 0.0], [90.0, 20.0]],
499 [[0.0, 0.0], [90.0, 0.0]],
500 [[0.0, 0.0], [90.0, -20.0]],
501 [[0.0, 0.0], [90.0, -40]]]],
502 [
"THJ3", [[0.0, -15.0],
505 [
"THJ4", [[0.0, 0.0],
509 [
"THJ5", [[0.0, -60.0],
515 self.
joint_map[
"Thumb"] = [[
"THJ1", [[0.0, 0.0],
520 [
"THJ2", [[0.0, -40.0],
525 [
"THJ3", [[0.0, -15.0],
528 [
"THJ4", [[0.0, 0.0],
532 [
"THJ5", [[0.0, -60.0],
543 QTreeWidgetItem.__init__(self, [
"Hand",
"",
"",
""])
547 btn_pressed = QMessageBox.warning(
548 tree_widget,
"Warning",
"The EtherCAT Hand node doesn't seem to be running, or the debug topic is not" 549 " being published. Do you still want to continue? The calibration will be useless.",
550 buttons=QMessageBox.Ok | QMessageBox.Cancel)
552 if btn_pressed == QMessageBox.Cancel:
555 for finger
in fingers:
564 print finger,
" not found in the calibration map" 575 it = QTreeWidgetItemIterator(self)
578 it.value().on_close()
595 item.setSelected(
False)
597 if next_item
is not None:
598 next_item.setSelected(
True)
602 joint0s = [
"FFJ1",
"FFJ2",
607 it = QTreeWidgetItemIterator(self)
609 if it.value().text(1)
in joint0s:
611 it.value().calibrate()
619 btn_joint_0s.setText(
620 "Save all Joint 0s (angle = " +
626 it = QTreeWidgetItemIterator(self)
628 nb_of_calibrated_items = 0
632 if it.value().is_calibrated:
633 nb_of_calibrated_items += 1
639 int(float(nb_of_calibrated_items) / float(nb_of_items) * 100.0))
642 f = open(filepath,
'r') 644 for line
in f.readlines():
647 yaml_config = yaml.load(document)
649 if "sr_calibrations" not in yaml_config.keys():
650 error_string = (
'The selected calibration file does not contain calibration ' +
652 rospy.logwarn(error_string)
653 QMessageBox(QMessageBox.Critical,
'Calibration file error', error_string).exec_()
657 used_yaml_config = yaml_config[
"sr_calibrations"]
659 if "sr_calibrations_coupled" not in yaml_config.keys():
660 error_string = (
'The selected calibration file does not contain coupled thumb calibration ' +
661 'values. Choose one that does, or switch to "Old Version" mode.')
662 rospy.logwarn(error_string)
663 QMessageBox(QMessageBox.Critical,
'Calibration file error', error_string).exec_()
665 used_yaml_config = yaml_config[
"sr_calibrations"] + yaml_config[
"sr_calibrations_coupled"]
666 for joint
in used_yaml_config:
667 it = QTreeWidgetItemIterator(self)
669 if type(joint[0])
is not list:
670 joint_name = joint[0]
672 joint_name =
", ".join(joint[0])
673 if it.value().text(1) == joint_name:
674 it.value().load_joint_calibration(joint[1])
683 it = QTreeWidgetItemIterator(self)
686 joint_configs.append(it.value().get_joint_calibration())
695 full_config_to_write =
"sr_calibrations: [\n" 696 for joint_config
in joint_configs:
697 if type(joint_config[0])
is not list:
698 full_config_to_write +=
"[\"" 699 full_config_to_write += joint_config[0] +
"\", " 702 for index, calib
in enumerate(joint_config[1]):
703 joint_config[1][index][0] = float(calib[0])
704 joint_config[1][index][1] = float(calib[1])
706 full_config_to_write += str(joint_config[1])
707 full_config_to_write +=
"], \n" 708 full_config_to_write +=
"]" 711 full_config_to_write +=
"\n\nsr_calibrations_coupled: [\n" 712 for joint_config
in joint_configs:
713 if type(joint_config[0])
is list:
714 full_config_to_write +=
"[[\"" 715 full_config_to_write += joint_config[0][0] +
"\", \"" + joint_config[0][1] +
"\"], [" 717 for index, calib
in enumerate(joint_config[1]):
718 joint_config[1][index][0][0] = float(calib[0][0])
719 joint_config[1][index][0][1] = float(calib[0][1])
720 joint_config[1][index][1][0] = float(calib[1][0])
721 joint_config[1][index][1][1] = float(calib[1][1])
724 full_config_to_write +=
", \n " 725 full_config_to_write +=
"[" 726 full_config_to_write += str(joint_config[1][index][0]) +
", " 727 full_config_to_write += str(joint_config[1][index][1][0]) +
", " + \
728 str(joint_config[1][index][1][1])
729 full_config_to_write +=
"]" 730 full_config_to_write +=
"]]" 731 full_config_to_write +=
"\n]" 733 f = open(filepath,
'w')
734 f.write(full_config_to_write)
738 it = QTreeWidgetItemIterator(self)
741 if not it.value().is_calibrated:
joint_0_calibration_index
def update_joint_pos(self)
def calibrate_item(self, item)
def __init__(self, joint_names, raw_values, calibrated_values, parent_widget, tree_widget, robot_lib)
def is_calibration_complete(self)
def __init__(self, joint_name, calibrations, parent_widget, tree_widget, robot_lib, package_path)
def get_calibration(self)
def plot_raw_button_clicked(self)
def load_joint_calibration(self, new_calibrations)
def __init__(self, joint_name, raw_value, calibrated_value, parent_widget, tree_widget, robot_lib)
def __init__(self, tree_widget, progress_bar, fingers=["First Finger", Middle, Finger, Ring, Finger, Little, Finger, Thumb, Wrist, old_version=False)
def set_is_loaded_calibration(self)
def calibrate_joint0s(self, btn_joint_0s)
def get_joint_calibration(self)
def __init__(self, finger_name, finger_joints, parent_widget, tree_widget, robot_lib, package_path)
def get_calibration(self)