bootloader.py
Go to the documentation of this file.
1 # Copyright 2011 Shadow Robot Company Ltd.
2 #
3 # This program is free software: you can redistribute it and/or modify it
4 # under the terms of the GNU General Public License as published by the Free
5 # Software Foundation version 2 of the License.
6 #
7 # This program is distributed in the hope that it will be useful, but WITHOUT
8 # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
9 # FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
10 # more details.
11 #
12 # You should have received a copy of the GNU General Public License along
13 # with this program. If not, see <http://www.gnu.org/licenses/>.
14 
15 import os
16 import rospy
17 import rospkg
18 
19 from qt_gui.plugin import Plugin
20 from python_qt_binding import loadUi
21 from QtCore import QEvent, QObject, Qt, QTimer, Slot, QThread, QPoint
22 from QtGui import QCursor, QColor
23 from QtWidgets import QWidget, QShortcut, QMessageBox, QFrame, QHBoxLayout, QCheckBox, QLabel, QFileDialog
24 
25 from std_srvs.srv import Empty
26 from diagnostic_msgs.msg import DiagnosticArray
27 
28 from sr_robot_msgs.srv import SimpleMotorFlasher, SimpleMotorFlasherResponse
29 
30 
31 class MotorBootloader(QThread):
32 
33  def __init__(self, parent, nb_motors_to_program):
34  QThread.__init__(self, None)
35  self.parent = parent
36  self.nb_motors_to_program = nb_motors_to_program
37 
38  def run(self):
39  bootloaded_motors = 0
40  firmware_path = self.parent._widget.txt_path.text()
41  for motor in self.parent.motors:
42  if motor.checkbox.checkState() == Qt.Checked:
43  try:
44  self.bootloader_service = rospy.ServiceProxy(
45  'SimpleMotorFlasher', SimpleMotorFlasher)
46  resp = self.bootloader_service(
47  firmware_path.encode('ascii', 'ignore'), motor.motor_index)
48  except rospy.ServiceException, e:
49  self.failed['QString'].emit("Service did not process request: %s" % str(e))
50  return
51 
52  if resp == SimpleMotorFlasherResponse.FAIL:
53  self.failed['QString'].emit("Bootloading motor " + +"failed")
54  bootloaded_motors += 1
55  self.motor_finished['QPoint'].emit(QPoint(bootloaded_motors, 0.0))
56 
57 
58 class Motor(QFrame):
59 
60  def __init__(self, parent, motor_name, motor_index):
61  QFrame.__init__(self, parent)
62 
63  self.motor_name = motor_name
64  self.motor_index = motor_index
65 
66  self.layout = QHBoxLayout()
67 
68  self.checkbox = QCheckBox(
69  motor_name + " [" + str(motor_index) + "]", self)
70  self.layout.addWidget(self.checkbox)
71 
72  self.revision_label = QLabel("")
73  self.revision_label.setToolTip("Svn Revision")
74  self.layout.addWidget(self.revision_label)
75 
76  self.setLayout(self.layout)
77 
78 
80 
81  """
82  A GUI plugin for bootloading the muscle drivers on the etherCAT muscle shadow hand
83  """
84 
85  def __init__(self, context):
86  super(SrGuiBootloader, self).__init__(context)
87  self.setObjectName('SrGuiBootloader')
88 
89  self._publisher = None
90  self._widget = QWidget()
91 
92  ui_file = os.path.join(rospkg.RosPack().get_path(
93  'sr_gui_bootloader'), 'uis', 'SrBootloader.ui')
94  loadUi(ui_file, self._widget)
95  self._widget.setObjectName('SrMotorResetterUi')
96  context.add_widget(self._widget)
97 
98  # motors_frame is defined in the ui file with a grid layout
99  self.motors = []
100  self.motors_frame = self._widget.motors_frame
101  self.populate_motors()
102  self.progress_bar = self._widget.motors_progress_bar
103  self.progress_bar.hide()
104 
106  self.diag_sub = rospy.Subscriber(
107  "diagnostics", DiagnosticArray, self.diagnostics_callback)
108 
109  # Bind button clicks
110  self._widget.btn_select_bootloader.pressed.connect(
112  self._widget.btn_select_all.pressed.connect(self.on_select_all_pressed)
113  self._widget.btn_select_none.pressed.connect(
115  self._widget.btn_bootload.pressed.connect(self.on_bootload_pressed)
116 
118  """
119  Select a hex file to bootload. Hex files must exist in the released_firmaware folder
120  """
121  path_to_bootloader = "~"
122  try:
123  path_to_bootloader = os.path.join(rospkg.RosPack().get_path(
124  'sr_external_dependencies'), 'compiled_firmware', 'released_firmware')
125  except:
126  rospy.logwarn(
127  "couldn't find the sr_edc_controller_configuration package")
128 
129  filter_files = "*.hex"
130  filename, _ = QFileDialog.getOpenFileName(
131  self._widget.motors_frame, self._widget.tr(
132  'Select hex file to bootload'),
133  self._widget.tr(
134  path_to_bootloader),
135  self._widget.tr(filter_files))
136  if filename == "":
137  return
138 
139  self._widget.txt_path.setText(filename)
140  self._widget.btn_bootload.setEnabled(True)
141 
142  def populate_motors(self):
143  """
144  Find motors according to joint_to_motor_mapping mapping that must exist on the parameter server
145  and add to the list of Motor objects etherCAT hand node must be running
146  """
147  row = 0
148  col = 0
149  for motor_index in range(0, 4):
150  if motor_index == 0:
151  row = 0
152  col = 0
153  elif motor_index == 1:
154  row = 0
155  col = 1
156  elif motor_index == 2:
157  row = 1
158  col = 0
159  elif motor_index == 3:
160  row = 1
161  col = 1
162 
163  muscle_driver_name = "Muscle driver " + str(motor_index)
164  motor = Motor(self.motors_frame, muscle_driver_name, motor_index)
165  self.motors_frame.layout().addWidget(motor, row, col)
166  self.motors.append(motor)
167 
168  def diagnostics_callback(self, msg):
169  for status in msg.status:
170  for motor in self.motors:
171  if motor.motor_name in status.name:
172  for key_values in status.values:
173  if "Firmware svn revision" in key_values.key:
174  server_current_modified = key_values.value.split(" / ")
175 
176  if server_current_modified[0] > self.server_revision:
177  self.server_revision = int(
178  server_current_modified[0].strip())
179 
180  palette = motor.revision_label.palette()
181  palette.setColor(
182  motor.revision_label.foregroundRole(), Qt.green)
183  if server_current_modified[0].strip() != server_current_modified[1].strip():
184  palette.setColor(
185  motor.revision_label.foregroundRole(), QColor(255, 170, 23))
186  motor.revision_label.setPalette(palette)
187 
188  if "True" in server_current_modified[2]:
189  palette.setColor(
190  motor.revision_label.foregroundRole(), Qt.red)
191  motor.revision_label.setText(
192  "svn: " + server_current_modified[1] + " [M]")
193  motor.revision_label.setPalette(palette)
194  else:
195  motor.revision_label.setText(
196  " svn: " + server_current_modified[1])
197  motor.revision_label.setPalette(palette)
198 
200  """
201  Select all motors
202  """
203  for motor in self.motors:
204  motor.checkbox.setCheckState(Qt.Checked)
205 
207  """
208  Unselect all motors
209  """
210  for motor in self.motors:
211  motor.checkbox.setCheckState(Qt.Unchecked)
212 
214  """
215  Start programming motors
216  """
217  self.progress_bar.reset()
218  nb_motors_to_program = 0
219  for motor in self.motors:
220  if motor.checkbox.checkState() == Qt.Checked:
221  nb_motors_to_program += 1
222  if nb_motors_to_program == 0:
223  QMessageBox.warning(
224  self._widget, "Warning", "No motors selected for resetting.")
225  return
226  self.progress_bar.setMaximum(nb_motors_to_program)
227 
228  self.motor_bootloader = MotorBootloader(self, nb_motors_to_program)
229 
230  self._widget.motor_bootloader.finished.connect(self.finished_programming_motors)
231  self._widget.motor_bootloader.motor_finished['QPoint'].connect(self.one_motor_finished)
232  self._widget.motor_bootloader.failed['QString'].connect(self.failed_programming_motors)
233 
234  self._widget.setCursor(Qt.WaitCursor)
235  self.motors_frame.setEnabled(False)
236  self._widget.btn_select_all.setEnabled(False)
237  self._widget.btn_select_none.setEnabled(False)
238  self.progress_bar.show()
239  self._widget.btn_bootload.hide()
240 
241  self.motor_bootloader.start()
242 
243  def one_motor_finished(self, point):
244  self.progress_bar.setValue(int(point.x()))
245 
247  """
248  Programming of motors completed
249  """
250  self.motors_frame.setEnabled(True)
251  self._widget.btn_select_all.setEnabled(True)
252  self._widget.btn_select_none.setEnabled(True)
253  self._widget.setCursor(Qt.ArrowCursor)
254  self.progress_bar.hide()
255  self._widget.btn_bootload.show()
256 
257  def failed_programming_motors(self, message):
258  QMessageBox.warning(self._widget.motors_frame, "Warning", message)
259 
261  if self._publisher is not None:
262  self._publisher.unregister()
263  self._publisher = None
264 
265  def shutdown_plugin(self):
266  self._unregisterPublisher()
267 
268  def save_settings(self, global_settings, perspective_settings):
269  pass
270 
271  def restore_settings(self, global_settings, perspective_settings):
272  pass
def __init__(self, parent, nb_motors_to_program)
Definition: bootloader.py:33
def save_settings(self, global_settings, perspective_settings)
Definition: bootloader.py:268
def restore_settings(self, global_settings, perspective_settings)
Definition: bootloader.py:271
def __init__(self, parent, motor_name, motor_index)
Definition: bootloader.py:60


sr_gui_muscle_driver_bootloader
Author(s): Ugo Cupcic
autogenerated on Wed Oct 14 2020 03:22:52