00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022 import os
00023 import rospkg
00024 import rospy
00025
00026 from qt_gui.plugin import Plugin
00027 from python_qt_binding import loadUi
00028
00029 from QtCore import Qt, QThread, SIGNAL, QPoint
00030 from QtGui import QWidget, QMessageBox, QFrame, \
00031 QHBoxLayout, QCheckBox, QLabel, QColor
00032
00033 from std_srvs.srv import Empty
00034 from diagnostic_msgs.msg import DiagnosticArray
00035 from sr_utilities.hand_finder import HandFinder
00036
00037
00038 class MotorFlasher(QThread):
00039
00040 def __init__(self, parent, nb_motors_to_program, prefix):
00041 QThread.__init__(self, None)
00042 self.parent = parent
00043 self.nb_motors_to_program = nb_motors_to_program
00044 self.prefix = prefix
00045
00046 def run(self):
00047 programmed_motors = 0
00048 for motor in self.parent.motors:
00049 if motor.checkbox.checkState() == Qt.Checked:
00050 try:
00051 print(
00052 "resetting: realtime_loop/" + self.prefix +
00053 "reset_motor_" + motor.motor_name)
00054 self.flasher_service = rospy.ServiceProxy(
00055 'realtime_loop/' + self.prefix + 'reset_motor_' +
00056 motor.motor_name, Empty)
00057 self.flasher_service()
00058 except rospy.ServiceException, e:
00059 self.emit(SIGNAL("failed(QString)"),
00060 "Service did not process request: %s" % str(e))
00061 return
00062
00063 programmed_motors += 1
00064 self.emit(SIGNAL("motor_finished(QPoint)"),
00065 QPoint(programmed_motors, 0.0))
00066
00067
00068 class Motor(QFrame):
00069
00070 def __init__(self, parent, motor_name, motor_index):
00071 QFrame.__init__(self, parent)
00072
00073 self.motor_name = motor_name
00074 self.motor_index = motor_index
00075
00076 self.layout = QHBoxLayout()
00077
00078 self.checkbox = QCheckBox(motor_name + " [" + str(motor_index) + "]",
00079 self)
00080 self.layout.addWidget(self.checkbox)
00081
00082 self.revision_label = QLabel("")
00083 self.revision_label.setToolTip("Svn Revision")
00084 self.layout.addWidget(self.revision_label)
00085
00086 self.setLayout(self.layout)
00087
00088
00089 class SrGuiMotorResetter(Plugin):
00090
00091 """
00092 A gui plugin for resetting motors on the shadow hand.
00093 """
00094
00095 def __init__(self, context):
00096 super(SrGuiMotorResetter, self).__init__(context)
00097 self.setObjectName('SrGuiMotorResetter')
00098
00099 self._publisher = None
00100 self._widget = QWidget()
00101
00102 ui_file = os.path.join(
00103 rospkg.RosPack().get_path('sr_gui_motor_resetter'), 'uis',
00104 'SrGuiMotorResetter.ui')
00105 loadUi(ui_file, self._widget)
00106 self._widget.setObjectName('SrMotorResetterUi')
00107 context.add_widget(self._widget)
00108
00109
00110 self.diag_sub = rospy.Subscriber("diagnostics", DiagnosticArray,
00111 self.diagnostics_callback)
00112
00113 self._hand_finder = HandFinder()
00114 hand_parameters = self._hand_finder.get_hand_parameters()
00115 self._prefix = ""
00116 for hand in hand_parameters.mapping:
00117 self._widget.select_prefix.addItem(hand_parameters.mapping[hand])
00118 if not hand_parameters.mapping:
00119 rospy.logerr("No hand detected")
00120 QMessageBox.warning(
00121 self._widget, "warning", "No hand is detected")
00122 else:
00123 self._widget.select_prefix.setCurrentIndex(0)
00124 self._prefix = hand_parameters.mapping.values()[0] + "/"
00125
00126 self._widget.select_prefix.currentIndexChanged['QString'].connect(
00127 self.prefix_selected)
00128
00129 self.motors = []
00130 self.motors_frame = self._widget.motors_frame
00131 self.populate_motors()
00132 self.progress_bar = self._widget.motors_progress_bar
00133 self.progress_bar.hide()
00134
00135 self.server_revision = 0
00136
00137
00138 self._widget.btn_select_all.pressed.connect(self.on_select_all_pressed)
00139 self._widget.btn_select_none.pressed.connect(
00140 self.on_select_none_pressed)
00141 self._widget.btn_reset_motors.pressed.connect(
00142 self.on_reset_motors_pressed)
00143
00144 def populate_motors(self):
00145
00146 for i in reversed(range(self.motors_frame.layout().count())):
00147 self.motors_frame.layout().itemAt(i).widget().setParent(None)
00148 self.motors = []
00149
00150 if rospy.has_param(self._prefix + "joint_to_motor_mapping"):
00151 joint_to_motor_mapping = rospy.get_param(
00152 self._prefix + "joint_to_motor_mapping")
00153 else:
00154 QMessageBox.warning(
00155 self.motors_frame, "Warning", "Couldn't find the " +
00156 self._prefix + "joint_to_motor_mapping parameter."
00157 " Make sure the etherCAT Hand node is running")
00158 return
00159
00160 joint_names = [
00161 ["FFJ0", "FFJ1", "FFJ2", "FFJ3", "FFJ4"],
00162 ["MFJ0", "MFJ1", "MFJ2", "MFJ3", "MFJ4"],
00163 ["RFJ0", "RFJ1", "RFJ2", "RFJ3", "RFJ4"],
00164 ["LFJ0", "LFJ1", "LFJ2", "LFJ3", "LFJ4", "LFJ5"],
00165 ["THJ1", "THJ2", "THJ3", "THJ4", "THJ5"],
00166 ["WRJ1", "WRJ2"]
00167 ]
00168
00169 row = 0
00170 col = 0
00171 index_jtm_mapping = 0
00172 for finger in joint_names:
00173 col = 0
00174 for joint_name in finger:
00175 motor_index = joint_to_motor_mapping[index_jtm_mapping]
00176 if motor_index != -1:
00177 motor = Motor(self.motors_frame, joint_name, motor_index)
00178 self.motors_frame.layout().addWidget(motor, row, col)
00179 self.motors.append(motor)
00180 col += 1
00181 index_jtm_mapping += 1
00182 row += 1
00183
00184 def diagnostics_callback(self, msg):
00185 for status in msg.status:
00186 for motor in self.motors:
00187 if motor.motor_name in status.name and self._prefix.replace(
00188 "/", "") in status.name:
00189 for key_values in status.values:
00190 if "Firmware svn revision" in key_values.key:
00191 server_current_modified = key_values.value.split(
00192 " / ")
00193
00194 if server_current_modified[0] \
00195 > self.server_revision:
00196 self.server_revision = int(
00197 server_current_modified[0].strip())
00198
00199 palette = motor.revision_label.palette()
00200 palette.setColor(
00201 motor.revision_label.foregroundRole(),
00202 Qt.green)
00203 if server_current_modified[0].strip() != \
00204 server_current_modified[1].strip():
00205 palette.setColor(
00206 motor.revision_label.foregroundRole(),
00207 QColor(255, 170, 23))
00208 motor.revision_label.setPalette(palette)
00209
00210 if "True" in server_current_modified[2]:
00211 palette.setColor(
00212 motor.revision_label.foregroundRole(),
00213 Qt.red)
00214 motor.revision_label.setText(
00215 "svn: " + server_current_modified[
00216 1] + " [M]")
00217 motor.revision_label.setPalette(palette)
00218 else:
00219 motor.revision_label.setText(
00220 " svn: " + server_current_modified[1])
00221 motor.revision_label.setPalette(palette)
00222
00223 def on_select_all_pressed(self):
00224 for motor in self.motors:
00225 motor.checkbox.setCheckState(Qt.Checked)
00226
00227 def on_select_none_pressed(self):
00228 for motor in self.motors:
00229 motor.checkbox.setCheckState(Qt.Unchecked)
00230
00231 def on_reset_motors_pressed(self):
00232 print("Reset motors pressed")
00233 self.progress_bar.reset()
00234 nb_motors_to_program = 0
00235 for motor in self.motors:
00236 if motor.checkbox.checkState() == Qt.Checked:
00237 nb_motors_to_program += 1
00238 if nb_motors_to_program == 0:
00239 QMessageBox.warning(self._widget, "Warning",
00240 "No motors selected for resetting.")
00241 return
00242 self.progress_bar.setMaximum(nb_motors_to_program)
00243
00244 self.motor_flasher = MotorFlasher(self, nb_motors_to_program,
00245 self._prefix)
00246 self._widget.connect(self.motor_flasher, SIGNAL("finished()"),
00247 self.finished_programming_motors)
00248 self._widget.connect(self.motor_flasher,
00249 SIGNAL("motor_finished(QPoint)"),
00250 self.one_motor_finished)
00251 self._widget.connect(self.motor_flasher, SIGNAL("failed(QString)"),
00252 self.failed_programming_motors)
00253
00254 self._widget.setCursor(Qt.WaitCursor)
00255 self.motors_frame.setEnabled(False)
00256 self._widget.btn_select_all.setEnabled(False)
00257 self._widget.btn_select_none.setEnabled(False)
00258 self.progress_bar.show()
00259 self._widget.btn_reset_motors.hide()
00260
00261 self.motor_flasher.start()
00262
00263 def one_motor_finished(self, point):
00264 self.progress_bar.setValue(int(point.x()))
00265
00266 def finished_programming_motors(self):
00267 self.motors_frame.setEnabled(True)
00268 self._widget.btn_select_all.setEnabled(True)
00269 self._widget.btn_select_none.setEnabled(True)
00270 self._widget.setCursor(Qt.ArrowCursor)
00271 self.progress_bar.hide()
00272 self._widget.btn_reset_motors.show()
00273
00274 def failed_programming_motors(self, message):
00275 QMessageBox.warning(self.motors_frame, "Warning", message)
00276
00277 def _unregisterPublisher(self):
00278 if self._publisher is not None:
00279 self._publisher.unregister()
00280 self._publisher = None
00281
00282 def shutdown_plugin(self):
00283 self._unregisterPublisher()
00284
00285 def save_settings(self, global_settings, perspective_settings):
00286 pass
00287
00288 def restore_settings(self, global_settings, perspective_settings):
00289 pass
00290
00291 def prefix_selected(self, prefix):
00292 self._prefix = str(prefix) + "/"
00293 self.populate_motors()