motor_resetter.py
Go to the documentation of this file.
1 #!/usr/bin/env python
2 
3 # Disabling E1002 check since it complains about super for no reason -
4 # inheriting from QObject
5 #
6 
7 # Copyright 2011 Shadow Robot Company Ltd.
8 #
9 # This program is free software: you can redistribute it and/or modify it
10 # under the terms of the GNU General Public License as published by the Free
11 # Software Foundation version 2 of the License.
12 #
13 # This program is distributed in the hope that it will be useful, but WITHOUT
14 # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
15 # FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
16 # more details.
17 #
18 # You should have received a copy of the GNU General Public License along
19 # with this program. If not, see <http://www.gnu.org/licenses/>.
20 
21 import os
22 import rospkg
23 import rospy
24 
25 from qt_gui.plugin import Plugin
26 from python_qt_binding import loadUi
27 
28 import QtCore
29 from QtCore import Qt, QThread, QPoint
30 from QtWidgets import QWidget, QMessageBox, QFrame, \
31  QHBoxLayout, QCheckBox, QLabel
32 from QtGui import QColor
33 
34 from std_srvs.srv import Empty
35 from diagnostic_msgs.msg import DiagnosticArray
36 from sr_utilities.hand_finder import HandFinder
37 
38 
39 class MotorFlasher(QThread):
40 
41  motor_finished = QtCore.pyqtSignal('QPoint')
42  failed = QtCore.pyqtSignal('QString')
43 
44  def __init__(self, parent, nb_motors_to_program, prefix):
45  QThread.__init__(self, None)
46  self.parent = parent
47  self.nb_motors_to_program = nb_motors_to_program
48  self.prefix = prefix
49 
50  def run(self):
51  programmed_motors = 0
52  for motor in self.parent.motors:
53  if motor.checkbox.checkState() == Qt.Checked:
54  try:
55  print(
56  "resetting: sr_hand_robot/" + self.prefix +
57  "reset_motor_" + motor.motor_name)
58  self.flasher_service = rospy.ServiceProxy(
59  'sr_hand_robot/' + self.prefix + 'reset_motor_' +
60  motor.motor_name, Empty)
61  self.flasher_service()
62  except rospy.ServiceException, e:
63  self.failed['QString'].emit("Service did not process request: %s" % str(e))
64  return
65 
66  programmed_motors += 1
67  self.motor_finished['QPoint'].emit(QPoint(programmed_motors, 0.0))
68 
69 
70 class Motor(QFrame):
71 
72  def __init__(self, parent, motor_name, motor_index):
73  QFrame.__init__(self, parent)
74 
75  self.motor_name = motor_name
76  self.motor_index = motor_index
77 
78  self.layout = QHBoxLayout()
79 
80  self.checkbox = QCheckBox(motor_name + " [" + str(motor_index) + "]",
81  self)
82  self.layout.addWidget(self.checkbox)
83 
84  self.revision_label = QLabel("")
85  self.revision_label.setToolTip("Svn Revision")
86  self.layout.addWidget(self.revision_label)
87 
88  self.setLayout(self.layout)
89 
90 
92 
93  """
94  A gui plugin for resetting motors on the shadow hand.
95  """
96 
97  def __init__(self, context):
98  super(SrGuiMotorResetter, self).__init__(context)
99  self.setObjectName('SrGuiMotorResetter')
100 
101  self._publisher = None
102  self._widget = QWidget()
103 
104  ui_file = os.path.join(
105  rospkg.RosPack().get_path('sr_gui_motor_resetter'), 'uis',
106  'SrGuiMotorResetter.ui')
107  loadUi(ui_file, self._widget)
108  self._widget.setObjectName('SrMotorResetterUi')
109  context.add_widget(self._widget)
110 
111  # setting the prefixes
112  self.diag_sub = rospy.Subscriber("diagnostics", DiagnosticArray,
114 
115  self._hand_finder = HandFinder()
116  hand_parameters = self._hand_finder.get_hand_parameters()
117  self._prefix = ""
118  for hand in hand_parameters.mapping:
119  self._widget.select_prefix.addItem(hand_parameters.mapping[hand])
120  if not hand_parameters.mapping:
121  rospy.logerr("No hand detected")
122  QMessageBox.warning(
123  self._widget, "warning", "No hand is detected")
124  else:
125  self._widget.select_prefix.setCurrentIndex(0)
126  self._prefix = hand_parameters.mapping.values()[0] + "/"
127 
128  self._widget.select_prefix.currentIndexChanged['QString'].connect(
129  self.prefix_selected)
130  # motors_frame is defined in the ui file with a grid layout
131  self.motors = []
132  self.motors_frame = self._widget.motors_frame
133  self.populate_motors()
134  self.progress_bar = self._widget.motors_progress_bar
135  self.progress_bar.hide()
136 
138 
139  # Bind button clicks
140  self._widget.btn_select_all.pressed.connect(self.on_select_all_pressed)
141  self._widget.btn_select_none.pressed.connect(
143  self._widget.btn_reset_motors.pressed.connect(
145 
146  def populate_motors(self):
147 
148  for i in reversed(range(self.motors_frame.layout().count())):
149  self.motors_frame.layout().itemAt(i).widget().setParent(None)
150  self.motors = []
151 
152  if rospy.has_param(self._prefix + "joint_to_motor_mapping"):
153  joint_to_motor_mapping = rospy.get_param(
154  self._prefix + "joint_to_motor_mapping")
155  else:
156  QMessageBox.warning(
157  self.motors_frame, "Warning", "Couldn't find the " +
158  self._prefix + "joint_to_motor_mapping parameter."
159  " Make sure the etherCAT Hand node is running")
160  return
161 
162  joint_names = [
163  ["FFJ0", "FFJ1", "FFJ2", "FFJ3", "FFJ4"],
164  ["MFJ0", "MFJ1", "MFJ2", "MFJ3", "MFJ4"],
165  ["RFJ0", "RFJ1", "RFJ2", "RFJ3", "RFJ4"],
166  ["LFJ0", "LFJ1", "LFJ2", "LFJ3", "LFJ4", "LFJ5"],
167  ["THJ1", "THJ2", "THJ3", "THJ4", "THJ5"],
168  ["WRJ1", "WRJ2"]
169  ]
170 
171  row = 0
172  col = 0
173  index_jtm_mapping = 0
174  for finger in joint_names:
175  col = 0
176  for joint_name in finger:
177  motor_index = joint_to_motor_mapping[index_jtm_mapping]
178  if motor_index != -1:
179  motor = Motor(self.motors_frame, joint_name, motor_index)
180  self.motors_frame.layout().addWidget(motor, row, col)
181  self.motors.append(motor)
182  col += 1
183  index_jtm_mapping += 1
184  row += 1
185 
186  def diagnostics_callback(self, msg):
187  for status in msg.status:
188  for motor in self.motors:
189  if motor.motor_name in status.name and self._prefix.replace(
190  "/", "") in status.name:
191  for key_values in status.values:
192  if "Firmware svn revision" in key_values.key:
193  server_current_modified = key_values.value.split(
194  " / ")
195 
196  if server_current_modified[0] \
197  > self.server_revision:
198  self.server_revision = int(
199  server_current_modified[0].strip())
200 
201  palette = motor.revision_label.palette()
202  palette.setColor(
203  motor.revision_label.foregroundRole(),
204  Qt.green)
205  if server_current_modified[0].strip() != \
206  server_current_modified[1].strip():
207  palette.setColor(
208  motor.revision_label.foregroundRole(),
209  QColor(255, 170, 23))
210  motor.revision_label.setPalette(palette)
211 
212  if "True" in server_current_modified[2]:
213  palette.setColor(
214  motor.revision_label.foregroundRole(),
215  Qt.red)
216  motor.revision_label.setText(
217  "svn: " + server_current_modified[
218  1] + " [M]")
219  motor.revision_label.setPalette(palette)
220  else:
221  motor.revision_label.setText(
222  " svn: " + server_current_modified[1])
223  motor.revision_label.setPalette(palette)
224 
226  for motor in self.motors:
227  motor.checkbox.setCheckState(Qt.Checked)
228 
230  for motor in self.motors:
231  motor.checkbox.setCheckState(Qt.Unchecked)
232 
234  print("Reset motors pressed")
235  self.progress_bar.reset()
236  nb_motors_to_program = 0
237  for motor in self.motors:
238  if motor.checkbox.checkState() == Qt.Checked:
239  nb_motors_to_program += 1
240  if nb_motors_to_program == 0:
241  QMessageBox.warning(self._widget, "Warning",
242  "No motors selected for resetting.")
243  return
244  self.progress_bar.setMaximum(nb_motors_to_program)
245 
246  self.motor_flasher = MotorFlasher(self, nb_motors_to_program,
247  self._prefix)
248 
249  self.motor_flasher.finished.connect(self.finished_programming_motors)
250  self.motor_flasher.motor_finished['QPoint'].connect(self.one_motor_finished)
251  self.motor_flasher.failed['QString'].connect(self.failed_programming_motors)
252 
253  self._widget.setCursor(Qt.WaitCursor)
254  self.motors_frame.setEnabled(False)
255  self._widget.btn_select_all.setEnabled(False)
256  self._widget.btn_select_none.setEnabled(False)
257  self.progress_bar.show()
258  self._widget.btn_reset_motors.hide()
259 
260  self.motor_flasher.start()
261 
262  def one_motor_finished(self, point):
263  self.progress_bar.setValue(int(point.x()))
264 
266  self.motors_frame.setEnabled(True)
267  self._widget.btn_select_all.setEnabled(True)
268  self._widget.btn_select_none.setEnabled(True)
269  self._widget.setCursor(Qt.ArrowCursor)
270  self.progress_bar.hide()
271  self._widget.btn_reset_motors.show()
272 
273  def failed_programming_motors(self, message):
274  QMessageBox.warning(self.motors_frame, "Warning", message)
275 
277  if self._publisher is not None:
278  self._publisher.unregister()
279  self._publisher = None
280 
281  def shutdown_plugin(self):
282  self._unregisterPublisher()
283 
284  def save_settings(self, global_settings, perspective_settings):
285  pass
286 
287  def restore_settings(self, global_settings, perspective_settings):
288  pass
289 
290  def prefix_selected(self, prefix):
291  self._prefix = str(prefix) + "/"
292  self.populate_motors()
def save_settings(self, global_settings, perspective_settings)
def restore_settings(self, global_settings, perspective_settings)
def __init__(self, parent, nb_motors_to_program, prefix)
def __init__(self, parent, motor_name, motor_index)


sr_gui_motor_resetter
Author(s): Mark Pitchless
autogenerated on Wed Oct 14 2020 03:22:51