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