motor_resetter.py
Go to the documentation of this file.
00001 # Copyright 2011 Shadow Robot Company Ltd.
00002 #
00003 # This program is free software: you can redistribute it and/or modify it
00004 # under the terms of the GNU General Public License as published by the Free
00005 # Software Foundation, either version 2 of the License, or (at your option)
00006 # any later version.
00007 #
00008 # This program is distributed in the hope that it will be useful, but WITHOUT
00009 # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
00010 # FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
00011 # more details.
00012 #
00013 # You should have received a copy of the GNU General Public License along
00014 # with this program.  If not, see <http://www.gnu.org/licenses/>.
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         # motors_frame is defined in the ui file with a grid layout
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         # Bind button clicks
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


sr_gui_motor_resetter
Author(s): Mark Pitchless
autogenerated on Fri Aug 28 2015 13:16:41