diagnostic_gui.py
Go to the documentation of this file.
1 #!/usr/bin/env python
2 
3 # Software License Agreement (BSD License)
4 #
5 # Copyright (c) 2014-2017, Dataspeed Inc.
6 # All rights reserved.
7 #
8 # Redistribution and use in source and binary forms, with or without modification,
9 # are permitted provided that the following conditions are met:
10 #
11 # * Redistributions of source code must retain the above copyright notice,
12 # this list of conditions and the following disclaimer.
13 # * Redistributions in binary form must reproduce the above copyright notice,
14 # this list of conditions and the following disclaimer in the documentation
15 # and/or other materials provided with the distribution.
16 # * Neither the name of Dataspeed Inc. nor the names of its
17 # contributors may be used to endorse or promote products derived from this
18 # software without specific prior written permission.
19 #
20 # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
21 # ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
22 # WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
23 # DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
24 # FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25 # DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
26 # SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
27 # CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
28 # OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
29 # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30 
31 import os
32 import rospy
33 import rospkg
34 import time
35 
36 from qt_gui.plugin import Plugin
37 from python_qt_binding import loadUi
38 from python_qt_binding.QtWidgets import QWidget, QGraphicsScene, QLabel, QGraphicsEllipseItem, QGraphicsLineItem, QGraphicsTextItem
39 from python_qt_binding.QtCore import Qt, Signal, QTimer, QDateTime, QDate, QTime, QPoint
40 from python_qt_binding.QtGui import QPixmap, QFont, QPen, QColor, QBrush, QImage
41 
42 from cmath import *
43 from math import *
44 
45 from mobility_base_core_msgs.msg import Mode, JoystickRaw
46 from rospy.rostime import Time
47 from geometry_msgs.msg import Twist
48 
49 from mobility_base_core_msgs.msg import BumperState
50 from mobility_base_core_msgs.msg import BatteryState
51 from sensor_msgs.msg import Imu
52 import std_msgs.msg
53 import std_srvs.srv
54 from mobility_base_core_msgs.srv import GetMaxSpeed, SetMaxSpeed
55 from numpy import isfinite
56 from mobility_base_core_msgs.srv import SetMaxSpeedRequest
57 
58 
60  def __init__(self):
61  pass
62 
63  BUMPER_1F = 0
64  BUMPER_1L = 1
65  BUMPER_1R = 2
66  BUMPER_1B = 3
67 
68  BUMPER_2F = 4
69  BUMPER_2L = 5
70  BUMPER_2R = 6
71  BUMPER_2B = 7
72 
73  BUMPER_3F = 8
74  BUMPER_3L = 9
75  BUMPER_3R = 10
76  BUMPER_3B = 11
77 
78  BUMPER_4F = 12
79  BUMPER_4L = 13
80  BUMPER_4R = 14
81  BUMPER_4B = 15
82 
83 
85  def __init__(self):
86  pass
87 
88  CHAN_ENABLE = 0
89  CHAN_ROTATE = 1
90  CHAN_FORWARD = 2
91  CHAN_LATERAL = 3
92  CHAN_MODE = 4
93  CHAN_EXTRA = 5
94 
95 
97  last_suppress_time = Time()
98  last_twist_time = Time()
99  gui_update_timer = QTimer()
100 
101  # Raw joystick data
102  joystick_data = []
103  joystick_table_vals = []
104  joystick_channel_text = ['CHAN_ENABLE: ', 'CHAN_ROTATE: ', 'CHAN_FORWARD: ', 'CHAN_LATERAL: ', 'CHAN_MODE: ', 'CHAN_EXTRA: ']
105  joystick_bind_status = False
106  joystick_bind_dot_counter = 0
107 
108  # Mode
109  current_mode = -1
110 
111  # Topic pub timeouts
112  JOYSTICK_SUPPRESS_PERIOD = 0.2 # 5 Hz
113  CMD_VEL_TIMEOUT_PERIOD = 0.2 # 5 Hz
114  joystick_suppressed = False
115  command_received = False
116  current_cmd = Twist()
117  battery_percent = 0
118  battery_voltage = 0
119 
120  # Checklist icons
121  bad_icon = QPixmap()
122  good_icon = QPixmap()
123  none_icon = QPixmap()
124 
125  # Checklist status
126  GOOD = 0
127  BAD = 1
128  NONE = 2
129 
130  # Checklist variables
131  checklist_status = []
132 
133  BATT_MAN = 0
134  ESTOP_MAN = 1
135  DISABLE_MAN = 2
136  JOYSTICK_MAN = 3
137  SUPPRESS_MAN = 4
138  BATT_COMP = 5
139  ESTOP_COMP = 6
140  DISABLE_COMP = 7
141  JOYSTICK_COMP = 8
142  SUPPRESS_COMP = 9
143  CMD_COMP = 10
144 
145  # Bumpers
146  bumper_front_left = 0
147  bumper_front_right = 0
148  bumper_rear_left = 0
149  bumper_rear_right = 0
150 
151  # Gyro cal
152  gyro_cal_status = False
153  gyro_x = 0.0
154  gyro_y = 0.0
155  gyro_z = 0.0
156  cal_enabled = True
157  cal_time = rospy.Time(0)
158 
159  # Max speed config
160  max_speed_known = False
161  max_speed_dirty = True
162  max_linear_actual = 0.0
163  max_angular_actual = 0.0
164  max_linear_setting = 0.0
165  max_angular_setting = 0.0
166 
167  # Wake time
168  current_wake_time = rospy.Time(0)
169  rel_wake_days = 0
170  rel_wake_hours = 0
171  rel_wake_minutes = 0
172  rel_wake_secs = 0
173 
174  # Switching between tabs and full GUI
175  is_currently_tab = False
176  widget_count = 0
177  current_tab_idx = -1
178  raw_data_tab_idx = 5
179 
180  # Check connection to base
181  base_connected = False
182  last_joystick_time = rospy.Time(0)
183 
184  # Constants
185  stick_ind_lox = 80
186  stick_ind_loy = 136
187  stick_ind_rox = 286
188  stick_ind_roy = 135
189  stick_ind_range_pix = 88.0
190  stick_ind_range_max = JoystickRaw.MAX
191  stick_ind_range_min = JoystickRaw.MIN
192  stick_ind_range_mid = JoystickRaw.CENTER
193  stick_ind_range_factor = stick_ind_range_pix / (stick_ind_range_max - stick_ind_range_min)
194  stick_ind_radius = 7
195  mode_ind_x1 = 52
196  mode_ind_y1 = 37
197  mode_ind_x2 = 44
198  mode_ind_y2 = 13
199  power_ind_x1 = 160
200  power_ind_x2 = 206
201  power_ind_y = 213
202  bumper_fl_x = 70
203  bumper_fl_y = 60
204  bumper_fr_x = 293
205  bumper_fr_y = 60
206  bumper_rl_x = 70
207  bumper_rl_y = 282
208  bumper_rr_x = 293
209  bumper_rr_y = 282
210  bumper_dx = 62
211  bumper_dy = 54
212  joystick_table_left_edge = 440
213  joystick_table_top_edge = 525
214  twist_table_left_edge = 700
215  twist_table_top_edge = 580
216  battery_table_left_edge = 700
217  battery_table_top_edge = 730
218 
219  _deferred_fit_in_view = Signal()
220 
221  def __init__(self, context):
222  super(DiagnosticGui, self).__init__(context)
223 
224  # Qt setup
225  self.context_ = context
226  self.init_gui('full')
227 
228  # ROS setup
229  self.topic_timeout_timer = rospy.Timer(rospy.Duration(0.02), self.topic_timeout_cb)
230  self.subscribe_topics()
231  self.advertise_topics()
232 
233  def init_gui(self, gui_type):
234  if gui_type == 'full':
235  self.spawn_full_gui()
237  else:
238  self.spawn_tab_gui()
239  self.init_tables(self._widget.gui_tabs.widget(self.raw_data_tab_idx), 20, 20)
240  self._widget.gui_tabs.setCurrentIndex(self.current_tab_idx)
241 
242  self.reset_gui_timer()
244  self.init_bumper_graphics()
245  self.init_checklists()
246  self.bind_callbacks()
247  self.refresh_max_speed()
248 
249  # Initialize absolute wake time setter to current time
250  datetime_now = QDateTime(QDate.currentDate(), QTime.currentTime())
251  self._widget.absolute_wake_time_obj.setDateTime(datetime_now)
252  temp_time = self._widget.absolute_wake_time_obj.time()
253  temp_time = QTime(temp_time.hour(), temp_time.minute())
254  self._widget.absolute_wake_time_obj.setTime(temp_time)
255 
256  # Set connection label text
257  if self.base_connected:
258  self._widget.disconnected_lbl.setVisible(False)
259  else:
260  self._widget.disconnected_lbl.setVisible(True)
261  self._widget.disconnected_lbl.setText('<font color=#FF0000>NOT CONNECTED</font>')
262 
263  def topic_timeout_cb(self, event):
264  # Joystick suppression
265  if (event.current_real - self.last_suppress_time).to_sec() < self.JOYSTICK_SUPPRESS_PERIOD and self.suppress_dt.to_sec() <= 1.0/9.0:
267  else:
268  self.joystick_suppressed = False
269 
270  # Command message
271  if (event.current_real - self.last_twist_time).to_sec() < self.CMD_VEL_TIMEOUT_PERIOD and self.twist_dt.to_sec() <= 1.0/6.0:
272  self.command_received = True
273  else:
274  self.command_received = False
275 
276  def init_checklists(self):
277  self.bad_icon.load(os.path.join(rospkg.RosPack().get_path('mobility_base_tools'), 'images', 'bad.png'))
278  self.good_icon.load(os.path.join(rospkg.RosPack().get_path('mobility_base_tools'), 'images', 'good.png'))
279  self.none_icon.load(os.path.join(rospkg.RosPack().get_path('mobility_base_tools'), 'images', 'none.png'))
280  self.checklist_status=[0 for i in range(self.CMD_COMP + 1)]
281  self.checklist_status[self.BATT_MAN] = self.NONE
282  self.checklist_status[self.ESTOP_MAN] = self.NONE
283  self.checklist_status[self.DISABLE_MAN] = self.NONE
284  self.checklist_status[self.JOYSTICK_MAN] = self.NONE
285  self.checklist_status[self.SUPPRESS_MAN] = self.NONE
286  self.checklist_status[self.BATT_COMP] = self.NONE
287  self.checklist_status[self.ESTOP_COMP] = self.NONE
288  self.checklist_status[self.DISABLE_COMP] = self.NONE
289  self.checklist_status[self.JOYSTICK_COMP] = self.NONE
290  self.checklist_status[self.SUPPRESS_COMP] = self.NONE
291  self.checklist_status[self.CMD_COMP] = self.NONE
292 
293  def init_tab_tables(self):
294  self.joystick_table_vals = [QLabel(self._widget.gui_tabs.widget(self.raw_data_tab_idx)) for i in range(ChannelIndex.CHAN_EXTRA+1)]
295  self.joystick_table_labels = [QLabel(self._widget.gui_tabs.widget(self.raw_data_tab_idx)) for i in range(ChannelIndex.CHAN_EXTRA+1)]
296  self.joystick_table_heading = QLabel(self._widget.gui_tabs.widget(self.raw_data_tab_idx))
297 
298  def init_tables(self, widget, left, top):
299  # Joystick data table
300  self.joystick_data = [0 for i in range(ChannelIndex.CHAN_EXTRA+1)]
301  self.joystick_table_vals = [QLabel(widget) for i in range(ChannelIndex.CHAN_EXTRA+1)]
302  self.joystick_table_labels = [QLabel(widget) for i in range(ChannelIndex.CHAN_EXTRA+1)]
303  self.joystick_table_heading = QLabel(widget)
304 
305  self.joystick_table_heading.setText('Raw Joystick Data')
306  self.joystick_table_heading.setFont(QFont('Ubuntu', 11, QFont.Bold))
307  self.joystick_table_heading.move(left, top)
308  for i in range(len(self.joystick_table_vals)):
309  self.joystick_table_vals[i].move(left + 150, top + 30 * (i+1))
310  self.joystick_table_vals[i].setText('0000')
311  self.joystick_table_vals[i].setFixedWidth(200)
312 
313  self.joystick_table_labels[i].move(left, top + 30 * (i+1))
314  self.joystick_table_labels[i].setText(self.joystick_channel_text[i])
315 
316  # Twist data table
317  self.twist_table_heading = QLabel(widget)
318  self.twist_table_heading.setText('Current Twist Command')
319  self.twist_table_heading.setFont(QFont('Ubuntu', 11, QFont.Bold))
320  self.twist_table_heading.move(left + 260, top)
321  self.twist_table_labels = [QLabel(widget) for i in range(0, 3)]
322  self.twist_table_vals = [QLabel(widget) for i in range(0, 3)]
323  for i in range(len(self.twist_table_vals)):
324  self.twist_table_vals[i].move(left + 260 + 150, top + 30 * (i+1))
325  self.twist_table_vals[i].setText('Not Published')
326  self.twist_table_vals[i].setFixedWidth(200)
327  self.twist_table_labels[i].move(left + 260, top + 30 * (i+1))
328 
329  self.twist_table_labels[0].setText('Forward (m/s):')
330  self.twist_table_labels[1].setText('Lateral (m/s):')
331  self.twist_table_labels[2].setText('Rotation (rad/s):')
332 
333  # Battery percentage
334  self.battery_heading = QLabel(widget)
335  self.battery_heading.setText('Current Battery State')
336  self.battery_heading.setFont(QFont('Ubuntu', 11, QFont.Bold))
337  self.battery_heading.move(left + 260, top + 150)
338  self.battery_label = QLabel(widget)
339  self.battery_label.move(left + 260, top + 150 +30)
340  self.battery_label.setText('000 %')
341  self.battery_voltage_label = QLabel(widget)
342  self.battery_voltage_label.move(left + 260, top + 150 +60)
343  self.battery_voltage_label.setText('00.00 V')
344  self.battery_voltage_label.setFixedWidth(200)
345 
346  # Mode
347  self.mode_heading = QLabel(widget)
348  self.mode_heading.setFont(QFont('Ubuntu', 11, QFont.Bold))
349  self.mode_heading.move(left, top + 225)
350  self.mode_heading.setText('Current Mode')
351  self.mode_label = QLabel(widget)
352  self.mode_label.move(left + 120, top + 225)
353  self.mode_label.setText('XXXXXXXXXXXXXXXXXXXXXX')
354 
355  def bind_callbacks(self):
356  self._widget.start_bind_btn.clicked.connect(self.start_bind)
357  self._widget.stop_bind_btn.clicked.connect(self.stop_bind)
358 
359  self._widget.gyro_cal_btn.clicked.connect(self.cal_gyro)
360  self._widget.clear_cal_btn.clicked.connect(self.clear_cal)
361 
362  self._widget.max_linear_txt.editingFinished.connect(self.max_linear_changed)
363  self._widget.max_angular_txt.editingFinished.connect(self.max_angular_changed)
364  self._widget.set_speed_btn.clicked.connect(self.set_max_speed)
365  self._widget.clear_speed_btn.clicked.connect(self.clear_max_speed)
366 
367  self._widget.wake_time_days_txt.editingFinished.connect(self.wake_days_changed)
368  self._widget.wake_time_hours_txt.editingFinished.connect(self.wake_hours_changed)
369  self._widget.wake_time_minutes_txt.editingFinished.connect(self.wake_minutes_changed)
370  self._widget.wake_time_secs_txt.editingFinished.connect(self.wake_secs_changed)
371  self._widget.set_relative_wake_time_btn.clicked.connect(self.set_relative_wake_time)
372  self._widget.set_absolute_wake_time_btn.clicked.connect(self.set_absolute_wake_time)
373  self._widget.clear_wake_time_btn.clicked.connect(self.clear_wake_time)
374 
375  if self.is_currently_tab:
376  self._widget.gui_tabs.currentChanged.connect(self.set_current_tab)
377 
378  def set_current_tab(self, idx):
379  self.current_tab_idx = self._widget.gui_tabs.currentIndex()
380 
381  def start_bind(self):
382  self.pub_start_bind.publish(std_msgs.msg.Empty())
383 
384  def stop_bind(self):
385  self.pub_stop_bind.publish(std_msgs.msg.Empty())
386 
387  def cal_gyro(self):
388  gyro_cal_srv = rospy.ServiceProxy('/mobility_base/imu/calibrate', std_srvs.srv.Empty)
389  try:
390  gyro_cal_srv()
391  self.cal_enabled = False
392  self.cal_time = rospy.Time.now()
393  except:
394  pass
395 
396  def clear_cal(self):
397  clear_cal_srv = rospy.ServiceProxy('/mobility_base/imu/clear_cal', std_srvs.srv.Empty)
398  try:
399  clear_cal_srv()
400  except:
401  pass
402 
404  try:
405  float_val = float(self._widget.max_linear_txt.text())
406  self.max_linear_setting = float_val;
407  except ValueError:
408  if self.max_linear_actual <= 0 or not isfinite(self.max_linear_actual):
409  self.max_linear_setting = 0.0
410  else:
412  self.max_speed_dirty = True
413 
415  try:
416  float_val = float(self._widget.max_angular_txt.text())
417  self.max_angular_setting = float_val;
418  except ValueError:
419  if self.max_angular_actual <= 0 or not isfinite(self.max_angular_actual):
420  self.max_angular_setting = 0.0
421  else:
423  self.max_speed_dirty = True
424 
425  def set_max_speed(self):
426  set_max_speed_srv = rospy.ServiceProxy('/mobility_base/set_max_speed', SetMaxSpeed)
427  req = SetMaxSpeedRequest()
428  req.linear = self.max_linear_setting
429  req.angular = self.max_angular_setting
430  try:
431  set_max_speed_srv(req)
432  self.max_speed_known = False
433  except:
434  pass
435 
436  def clear_max_speed(self):
437  set_max_speed_srv = rospy.ServiceProxy('/mobility_base/set_max_speed', SetMaxSpeed)
438  req = SetMaxSpeedRequest()
439  req.linear = float('nan')
440  req.angular = float('nan')
441  try:
442  set_max_speed_srv(req)
443  self.max_speed_known = False
444  except:
445  pass
446 
447  def wake_days_changed(self):
448  try:
449  self.rel_wake_days = float(self._widget.wake_time_days_txt.text())
450  except:
451  self._widget.wake_time_days_txt.setText(str(self.rel_wake_days))
452 
454  try:
455  self.rel_wake_hours = float(self._widget.wake_time_hours_txt.text())
456  except:
457  self._widget.wake_time_hours_txt.setText(str(self.rel_wake_hours))
458 
460  try:
461  self.rel_wake_minutes = float(self._widget.wake_time_minutes_txt.text())
462  except:
463  self._widget.wake_time_minutes_txt.setText(str(self.rel_wake_minutes))
464 
465  def wake_secs_changed(self):
466  try:
467  self.rel_wake_secs = float(self._widget.wake_time_secs_txt.text())
468  except:
469  self._widget.wake_time_secs_txt.setText(str(self.rel_wake_secs))
470 
472  new_wake_time = std_msgs.msg.Time()
473  rel_wake_time = 86400 * self.rel_wake_days + 3600 * self.rel_wake_hours + 60 * self.rel_wake_minutes + self.rel_wake_secs
474  new_wake_time.data = rospy.Time.now() + rospy.Duration(rel_wake_time)
475  self.pub_set_wake_time.publish(new_wake_time)
476 
478  self.pub_set_wake_time.publish(rospy.Time(self._widget.absolute_wake_time_obj.dateTime().toTime_t()))
479 
480  def clear_wake_time(self):
481  self.pub_set_wake_time.publish(rospy.Time(0))
482 
483  def refresh_max_speed(self):
484  self.max_speed_dirty = True
485  self.max_speed_known = False
486 
487  def update_gui_cb(self):
488 
489  # Switch between tabs and full GUI
490  if self.is_currently_tab:
491  if self._widget.height() > 830 and self._widget.width() > 1205:
492  self.is_currently_tab = False
493  self.context_.remove_widget(self._widget)
494  self.init_gui('full')
495  else:
496  if self._widget.height() < 810 or self._widget.width() < 1185:
497  self.is_currently_tab = True
498  self.context_.remove_widget(self._widget)
499  self.init_gui('tab')
500 
501  # Check connection to base
502  if self.base_connected and (rospy.Time.now() - self.last_joystick_time).to_sec() > 1.0:
503  self.base_connected = False
504  self._widget.disconnected_lbl.setText('<font color=#FF0000>NOT CONNECTED</font>')
505  self._widget.disconnected_lbl.setVisible(True)
506 
507  if not self.base_connected and (rospy.Time.now() - self.last_joystick_time).to_sec() < 1.0:
508  self.base_connected = True
509 # self._widget.disconnected_lbl.setText('')
510  self._widget.disconnected_lbl.setVisible(False)
511 
512  # Update checklists
513  self.update_checklist();
514 
515  # Manage 5 second disable of gyro calibration button
516  if not self.cal_enabled:
517  if (rospy.Time.now() - self.cal_time).to_sec() > 5.0:
518  self._widget.gyro_cal_btn.setEnabled(True)
519  self._widget.gyro_cal_btn.setText('Calibrate')
520  self.cal_enabled = True
521  else:
522  self._widget.gyro_cal_btn.setEnabled(False)
523  self._widget.gyro_cal_btn.setText(str(5 - 0.1*floor(10*(rospy.Time.now() - self.cal_time).to_sec())))
524 
525  # Update joystick graphics
526  if not self.check_joystick_valid():
527  self.update_check_status(self._widget.joystick_bind_chk, self.NONE)
528 
529  if not self.joystick_bind_status:
530  self._widget.joystick_bind_lbl.setText('')
531 
532 
533  for l in self.joystick_power_ind:
534  l.setVisible(True)
537  else:
538  self.update_check_status(self._widget.joystick_bind_chk, self.GOOD)
539  self._widget.joystick_bind_lbl.setText('Joystick bound')
540 
541  for l in self.joystick_power_ind:
542  l.setVisible(False)
543  self.update_right_stick_indicator(self.joystick_data[ChannelIndex.CHAN_LATERAL], self.joystick_data[ChannelIndex.CHAN_FORWARD])
544  self.update_left_stick_indicator(self.joystick_data[ChannelIndex.CHAN_ROTATE], self.joystick_data[ChannelIndex.CHAN_ENABLE])
545  if self.joystick_data[ChannelIndex.CHAN_MODE] < self.stick_ind_range_mid:
546  self.mode_ind.setPen(self.cyan_pen)
547  self._widget.modeLabel.setText("0 (Computer)")
548  else:
549  self.mode_ind.setPen(self.magenta_pen)
550  self._widget.modeLabel.setText("1 (Manual)")
551 
552  # Update joystick data table
553  for i in range(len(self.joystick_table_vals)):
554  self.joystick_table_vals[i].setText(str(self.joystick_data[i]))
555 
556  # Update twist data table
557  if self.command_received:
558  self.twist_table_vals[0].setText(str(0.01 * floor(100 * self.current_cmd.linear.x)))
559  self.twist_table_vals[1].setText(str(0.01 * floor(100 * self.current_cmd.linear.y)))
560  self.twist_table_vals[2].setText(str(0.01 * floor(100 * self.current_cmd.angular.z)))
561  else:
562  self.twist_table_vals[0].setText('Not Published')
563  self.twist_table_vals[1].setText('Not Published')
564  self.twist_table_vals[2].setText('Not Published')
565 
566  # Update battery percentage
567  self.battery_label.setText(str(self.battery_percent) + ' %')
568  self.battery_voltage_label.setText(str(0.01 * floor(100 * self.battery_voltage)) + ' V')
569 
570  # Update mode
571  self.mode_label.setText(self.get_mode_string(self.current_mode))
572 
573  # Update bumper graphics
574  self.bumper_visible_switch(BumperIndex.BUMPER_1F, self.bumper_front_left)
575  self.bumper_visible_switch(BumperIndex.BUMPER_2F, self.bumper_front_right)
576  self.bumper_visible_switch(BumperIndex.BUMPER_3F, self.bumper_rear_left)
577  self.bumper_visible_switch(BumperIndex.BUMPER_4F, self.bumper_rear_right)
578  self.bumper_state_labels[0].setPlainText(str(self.bumper_front_left))
579  self.bumper_state_labels[1].setPlainText(str(self.bumper_front_right))
580  self.bumper_state_labels[2].setPlainText(str(self.bumper_rear_left))
581  self.bumper_state_labels[3].setPlainText(str(self.bumper_rear_right))
582 
583  # Update gyro cal graphics
584  if self.gyro_cal_status:
585  self.update_check_status(self._widget.gyro_cal_chk, self.GOOD)
586  self._widget.gyro_cal_lbl.setText('Gyro calibrated')
587  else:
588  self.update_check_status(self._widget.gyro_cal_chk, self.BAD)
589  self._widget.gyro_cal_lbl.setText('Gyro NOT calibrated')
590 
591  self._widget.gyro_x_lbl.setText('x: ' + str(1e-5*floor(1e5*self.gyro_x)))
592  self._widget.gyro_y_lbl.setText('y: ' + str(1e-5*floor(1e5*self.gyro_y)))
593  self._widget.gyro_z_lbl.setText('z: ' + str(1e-5*floor(1e5*self.gyro_z)))
594 
595  # Update max speed configuration
596  if not self.max_speed_known:
597  service_name = '/mobility_base/get_max_speed'
598  get_max_speed_srv = rospy.ServiceProxy(service_name, GetMaxSpeed)
599 
600  try:
601  resp = get_max_speed_srv()
602  self.max_speed_known = True
603  self.max_linear_actual = resp.linear
604  self.max_angular_actual = resp.angular
605 
606  if self.max_linear_actual <= 0 or not isfinite(self.max_linear_actual):
607  self._widget.max_linear_lbl.setText('Unlimited')
608  else:
609  self._widget.max_linear_lbl.setText(str(1e-2*round(1e2*self.max_linear_actual)))
610 
611  if self.max_angular_actual <= 0 or not isfinite(self.max_angular_actual):
612  self._widget.max_angular_lbl.setText('Unlimited')
613  else:
614  self._widget.max_angular_lbl.setText(str(1e-2*round(1e2*self.max_angular_actual)))
615 
616  except:
617  pass
618 # print service_name + " doesn't exist"
619 
620  if self.max_speed_dirty:
621  self._widget.max_linear_txt.setText(str(self.max_linear_setting))
622  self._widget.max_angular_txt.setText(str(self.max_angular_setting))
623  self.max_speed_dirty = False
624 
625  # Wake time
626  if self.current_wake_time == rospy.Time(0):
627  self._widget.wake_time_lbl.setText('Not Set')
628  else:
629  self._widget.wake_time_lbl.setText(time.strftime('%m/%d/%Y, %H:%M:%S', time.localtime(self.current_wake_time.to_sec())))
630 
632  return self.joystick_data[ChannelIndex.CHAN_FORWARD] > 0 or self.joystick_data[ChannelIndex.CHAN_LATERAL] > 0 or self.joystick_data[ChannelIndex.CHAN_ROTATE] > 0 or self.joystick_data[ChannelIndex.CHAN_MODE] > 0
633 
634  def get_mode_string(self, mode_num):
635  if mode_num == Mode.MODE_ESTOP:
636  return 'MODE_ESTOP'
637  elif mode_num == Mode.MODE_DISABLED:
638  return 'MODE_DISABLED'
639  elif mode_num == Mode.MODE_BATTERY_LIMP_HOME:
640  return 'MODE_BATTERY_LIMP_HOME'
641  elif mode_num == Mode.MODE_BATTERY_CRITICAL:
642  return 'MODE_BATTERY_CRITICAL'
643  elif mode_num == Mode.MODE_WIRELESS:
644  return 'MODE_WIRELESS'
645  elif mode_num == Mode.MODE_TIMEOUT:
646  return 'MODE_TIMEOUT'
647  elif mode_num == Mode.MODE_VELOCITY:
648  return 'MODE_VELOCITY'
649  elif mode_num == Mode.MODE_VELOCITY_RAW:
650  return 'MODE_VELOCITY_RAW'
651  else:
652  return ''
653 
654  def update_checklist(self):
655  if self.current_mode >= Mode.MODE_TIMEOUT:
656  self.checklist_status[self.BATT_MAN] = self.GOOD
657  self.checklist_status[self.ESTOP_MAN] = self.GOOD
658  self.checklist_status[self.DISABLE_MAN] = self.GOOD
659  self.checklist_status[self.JOYSTICK_MAN] = self.BAD
660  self.checklist_status[self.BATT_COMP] = self.GOOD
661  self.checklist_status[self.ESTOP_COMP] = self.GOOD
662  self.checklist_status[self.DISABLE_COMP] = self.GOOD
663  self.checklist_status[self.JOYSTICK_COMP] = self.GOOD
664  elif self.current_mode == Mode.MODE_WIRELESS:
665  self.checklist_status[self.BATT_MAN] = self.GOOD
666  self.checklist_status[self.ESTOP_MAN] = self.GOOD
667  self.checklist_status[self.DISABLE_MAN] = self.GOOD
668  self.checklist_status[self.JOYSTICK_MAN] = self.GOOD
669  self.checklist_status[self.BATT_COMP] = self.GOOD
670  self.checklist_status[self.ESTOP_COMP] = self.GOOD
671  self.checklist_status[self.DISABLE_COMP] = self.GOOD
672  self.checklist_status[self.JOYSTICK_COMP] = self.BAD
673  elif self.current_mode == Mode.MODE_DISABLED:
674  self.checklist_status[self.BATT_MAN] = self.NONE
675  self.checklist_status[self.ESTOP_MAN] = self.GOOD
676  self.checklist_status[self.DISABLE_MAN] = self.BAD
677  self.checklist_status[self.JOYSTICK_MAN] = self.NONE
678  self.checklist_status[self.BATT_COMP] = self.NONE
679  self.checklist_status[self.ESTOP_COMP] = self.GOOD
680  self.checklist_status[self.DISABLE_COMP] = self.BAD
681  self.checklist_status[self.JOYSTICK_COMP] = self.NONE
682  elif self.current_mode == Mode.MODE_ESTOP:
683  self.checklist_status[self.BATT_MAN] = self.NONE
684  self.checklist_status[self.ESTOP_MAN] = self.BAD
685  self.checklist_status[self.DISABLE_MAN] = self.NONE
686  self.checklist_status[self.JOYSTICK_MAN] = self.NONE
687  self.checklist_status[self.BATT_COMP] = self.NONE
688  self.checklist_status[self.ESTOP_COMP] = self.BAD
689  self.checklist_status[self.DISABLE_COMP] = self.NONE
690  self.checklist_status[self.JOYSTICK_COMP] = self.NONE
691  elif self.current_mode == Mode.MODE_BATTERY_CRITICAL:
692  self.checklist_status[self.BATT_MAN] = self.BAD
693  self.checklist_status[self.ESTOP_MAN] = self.GOOD
694  self.checklist_status[self.DISABLE_MAN] = self.GOOD
695  self.checklist_status[self.JOYSTICK_MAN] = self.NONE
696  self.checklist_status[self.BATT_COMP] = self.BAD
697  self.checklist_status[self.ESTOP_COMP] = self.GOOD
698  self.checklist_status[self.DISABLE_COMP] = self.GOOD
699  self.checklist_status[self.JOYSTICK_COMP] = self.NONE
700  elif self.current_mode == Mode.MODE_BATTERY_LIMP_HOME:
701  self.checklist_status[self.BATT_MAN] = self.GOOD
702  self.checklist_status[self.ESTOP_MAN] = self.GOOD
703  self.checklist_status[self.DISABLE_MAN] = self.GOOD
704  self.checklist_status[self.JOYSTICK_MAN] = self.NONE
705  self.checklist_status[self.BATT_COMP] = self.BAD
706  self.checklist_status[self.ESTOP_COMP] = self.GOOD
707  self.checklist_status[self.DISABLE_COMP] = self.GOOD
708  self.checklist_status[self.JOYSTICK_COMP] = self.NONE
709 
710  # Check if joystick is suppressed by topic
711  if self.joystick_suppressed:
712  self.checklist_status[self.SUPPRESS_COMP] = self.GOOD
713  self.checklist_status[self.DISABLE_COMP] = self.NONE
714  self.checklist_status[self.JOYSTICK_COMP] = self.NONE
715  else:
716  self.checklist_status[self.SUPPRESS_COMP] = self.NONE
717  if (rospy.Time.now() - self.last_suppress_time).to_sec() > self.JOYSTICK_SUPPRESS_PERIOD:
718  self.checklist_status[self.SUPPRESS_MAN] = self.GOOD
719  else:
720  self.checklist_status[self.SUPPRESS_MAN] = self.BAD
721 
722  # Command message received
723  if self.command_received:
724  self.checklist_status[self.CMD_COMP] = self.GOOD
725  else:
726  self.checklist_status[self.CMD_COMP] = self.BAD
727 
728  # Override twist checkbox if mode is in TIMEOUT
729  if self.current_mode == Mode.MODE_TIMEOUT:
730  self.checklist_status[self.CMD_COMP] = self.BAD
731 
732  # Update checklist graphics
733  self.update_check_status(self._widget.batt_man_chk, self.checklist_status[self.BATT_MAN])
734  self.update_check_status(self._widget.estop_man_chk, self.checklist_status[self.ESTOP_MAN])
735  self.update_check_status(self._widget.disable_man_chk, self.checklist_status[self.DISABLE_MAN])
736  self.update_check_status(self._widget.joystick_man_chk, self.checklist_status[self.JOYSTICK_MAN])
737  self.update_check_status(self._widget.suppress_man_chk, self.checklist_status[self.SUPPRESS_MAN])
738  self.update_check_status(self._widget.batt_comp_chk, self.checklist_status[self.BATT_COMP])
739  self.update_check_status(self._widget.estop_comp_chk, self.checklist_status[self.ESTOP_COMP])
740  self.update_check_status(self._widget.disable_comp_chk, self.checklist_status[self.DISABLE_COMP])
741  self.update_check_status(self._widget.joystick_comp_chk, self.checklist_status[self.JOYSTICK_COMP])
742  self.update_check_status(self._widget.suppress_comp_chk, self.checklist_status[self.SUPPRESS_COMP])
743  self.update_check_status(self._widget.cmd_comp_chk, self.checklist_status[self.CMD_COMP])
744  self.update_check_status(self._widget.joystick_bind_chk, self.NONE)
745 
746  def update_check_status(self, obj, icon_type):
747  if icon_type == self.GOOD:
748  obj.setPixmap(self.good_icon)
749  elif icon_type == self.BAD:
750  obj.setPixmap(self.bad_icon)
751  else:
752  obj.setPixmap(self.none_icon)
753 
754  def update_table(self):
755  for i in range(0, len(self.joystick_table_vals)):
756  self.joystick_table_vals[i].setText(55)
757 
758  def recv_mode(self, mode_msg):
759  self.current_mode = mode_msg.mode
760 
761  def recv_suppress(self, suppress_msg):
762  self.suppress_dt = rospy.Time.now() - self.last_suppress_time
763  self.last_suppress_time = rospy.Time.now()
764 
765  def recv_twist(self, twist_msg):
766  self.twist_dt = rospy.Time.now() - self.last_twist_time
767  self.last_twist_time = rospy.Time.now()
768  self.current_cmd = twist_msg
769 
770  def recv_joystick(self, joystick_msg):
771  self.joystick_data = joystick_msg.channels;
772  self.last_joystick_time = rospy.Time.now()
773 
774  def recv_bumpers(self, bumper_msg):
775  self.bumper_front_left = bumper_msg.front_left
776  self.bumper_front_right = bumper_msg.front_right
777  self.bumper_rear_left = bumper_msg.rear_left
778  self.bumper_rear_right = bumper_msg.rear_right
779 
780  def recv_battery(self, battery_msg):
781  self.battery_percent = battery_msg.percent
782  self.battery_voltage = battery_msg.voltage
783 
784  def recv_bind_status(self, bind_msg):
785  self.joystick_bind_status = bind_msg.data
786 
787  if bind_msg.data:
789  self._widget.joystick_bind_lbl.setText('Binding.')
790  elif self.joystick_bind_dot_counter == 1:
791  self._widget.joystick_bind_lbl.setText('Binding..')
792  elif self.joystick_bind_dot_counter == 2:
793  self._widget.joystick_bind_lbl.setText('Binding...')
794 
796 
797  def recv_gyro_calibrated(self, cal_msg):
798  self.gyro_cal_status = cal_msg.data
799 
800  def recv_imu(self, imu_msg):
801  self.gyro_x = imu_msg.angular_velocity.x
802  self.gyro_y = imu_msg.angular_velocity.y
803  self.gyro_z = imu_msg.angular_velocity.z
804 
805  def recv_wake_time(self, time_msg):
806  self.current_wake_time = time_msg.data
807 
808  def subscribe_topics(self):
809  sub_joystick = rospy.Subscriber('/mobility_base/joystick_raw', JoystickRaw, self.recv_joystick)
810  sub_suppress = rospy.Subscriber('/mobility_base/suppress_wireless', std_msgs.msg.Empty, self.recv_suppress)
811  sub_twist = rospy.Subscriber('/mobility_base/cmd_vel', Twist, self.recv_twist)
812  sub_mode = rospy.Subscriber('/mobility_base/mode', Mode, self.recv_mode)
813  sub_bumpers = rospy.Subscriber('/mobility_base/bumper_states', BumperState, self.recv_bumpers)
814  sub_battery = rospy.Subscriber('/mobility_base/battery', BatteryState, self.recv_battery)
815  sub_bind = rospy.Subscriber('/mobility_base/bind_status', std_msgs.msg.Bool, self.recv_bind_status)
816  sub_gyro_calibrated = rospy.Subscriber('/mobility_base/imu/is_calibrated', std_msgs.msg.Bool, self.recv_gyro_calibrated)
817  sub_imu = rospy.Subscriber('/mobility_base/imu/data_raw', Imu, self.recv_imu)
818  sub_wake_time = rospy.Subscriber('/mobility_base/wake_time', std_msgs.msg.Time, self.recv_wake_time)
819 
820  def advertise_topics(self):
821  self.pub_start_bind = rospy.Publisher('/mobility_base/bind_start', std_msgs.msg.Empty, queue_size=1)
822  self.pub_stop_bind = rospy.Publisher('/mobility_base/bind_stop', std_msgs.msg.Empty, queue_size=1)
823  self.pub_set_wake_time = rospy.Publisher('/mobility_base/set_wake_time', std_msgs.msg.Time, queue_size=1)
824 
826  # Pens
827  self.cyan_pen = QPen(QColor(0, 255, 255))
828  self.magenta_pen = QPen(QColor(255, 0, 255))
829  self.red_pen = QPen(QColor(255, 0, 0))
830  self.cyan_pen.setWidth(3)
831  self.magenta_pen.setWidth(3)
832  self.red_pen.setWidth(3)
833  self.stick_ind_l = QGraphicsEllipseItem()
834  self.stick_ind_r = QGraphicsEllipseItem()
835  self.stick_line_l = QGraphicsLineItem()
836  self.stick_line_r = QGraphicsLineItem()
837  self.mode_ind = QGraphicsLineItem()
838 
839  # Left joystick indicator circle
840  px_l = self.stick_ind_lox - self.stick_ind_radius
841  py_l = self.stick_ind_loy - self.stick_ind_radius
842  self.stick_ind_l.setRect(px_l, py_l, 2 * self.stick_ind_radius, 2 * self.stick_ind_radius)
843  self.stick_ind_l.setBrush(QBrush(QColor(255, 0, 0)))
844  self.stick_ind_l.setPen(QPen(QColor(0, 0, 0)))
845 
846  # Right joystick indicator circle
847  px_r = self.stick_ind_rox - self.stick_ind_radius
848  py_r = self.stick_ind_roy - self.stick_ind_radius
849  self.stick_ind_r.setRect(px_r, py_r, 2 * self.stick_ind_radius, 2 * self.stick_ind_radius)
850  self.stick_ind_r.setBrush(QBrush(QColor(255, 0, 0)))
851  self.stick_ind_r.setPen(QPen(QColor(0, 0, 0)))
852 
853  # Left joystick indicator line
854  line_pen = QPen(QColor(255,0,0))
855  line_pen.setWidth(4)
856  self.stick_line_l.setLine(self.stick_ind_lox, self.stick_ind_loy, self.stick_ind_lox, self.stick_ind_loy)
857  self.stick_line_l.setPen(line_pen)
858 
859  # Right joystick indicator line
860  self.stick_line_r.setLine(self.stick_ind_rox, self.stick_ind_roy, self.stick_ind_rox, self.stick_ind_roy)
861  self.stick_line_r.setPen(line_pen)
862 
863  # Mode indicator line
864  self.mode_ind.setLine(self.mode_ind_x1, self.mode_ind_y1, self.mode_ind_x2, self.mode_ind_y2)
865  self.mode_ind.setPen(self.cyan_pen)
866 
867  # Joystick power indicator
869  self.joystick_power_ind.append(QGraphicsLineItem(self.power_ind_x1, self.power_ind_y + 20, self.power_ind_x1, self.power_ind_y - 20))
870  self.joystick_power_ind.append(QGraphicsLineItem(self.power_ind_x1, self.power_ind_y - 20, self.power_ind_x1 + 50, self.power_ind_y - 20))
871  self.joystick_power_ind.append(QGraphicsLineItem(self.power_ind_x1+50, self.power_ind_y - 20, self.power_ind_x1+50, self.power_ind_y + 20))
872  self.joystick_power_ind.append(QGraphicsLineItem(self.power_ind_x1+50, self.power_ind_y + 20, self.power_ind_x1, self.power_ind_y + 20))
873 
874  # Populate scene
875  graphics_scene = QGraphicsScene()
876  graphics_scene.addItem(self.stick_ind_l)
877  graphics_scene.addItem(self.stick_ind_r)
878  graphics_scene.addItem(self.stick_line_l)
879  graphics_scene.addItem(self.stick_line_r)
880  graphics_scene.addItem(self.mode_ind)
881  for l in self.joystick_power_ind:
882  l.setPen(self.red_pen)
883  graphics_scene.addItem(l)
884  graphics_scene.setSceneRect(0, 0, self._widget.joystickGraphicsView.width() - 4, self._widget.joystickGraphicsView.height() - 4)
885  self._widget.joystickGraphicsView.setScene(graphics_scene)
886  self._widget.joystickGraphicsView.setBackgroundBrush(QBrush(QImage(os.path.join(rospkg.RosPack().get_path('mobility_base_tools'), 'images', 'dx6ilabels.jpg'))))
887  self._widget.joystickGraphicsView.show()
888 
890 
891  # Pens
892  self.blue_pen = QPen(QColor(0,0,255))
893  self.blue_pen.setWidth(10)
894 
895  self.bumper_lines = []
896 
897  # Text state labels
898  self.bumper_state_labels = [QGraphicsTextItem() for i in range(0,4)]
899  for i in range(len(self.bumper_state_labels)):
900  self.bumper_state_labels[i].setFont(QFont('Ubuntu', 14, QFont.Bold))
901  self.bumper_state_labels[i].setPlainText('00')
902  self.bumper_state_labels[0].setPos(self.bumper_fl_x-10, self.bumper_fl_y + 55)
903  self.bumper_state_labels[1].setPos(self.bumper_fr_x-10, self.bumper_fr_y + 55)
904  self.bumper_state_labels[2].setPos(self.bumper_rl_x-10, self.bumper_rl_y - 80)
905  self.bumper_state_labels[3].setPos(self.bumper_rr_x-10, self.bumper_rr_y - 80)
906 
907  # Bumper indicator lines
908  self.bumper_line(self.bumper_fl_x - 20, self.bumper_fl_y - self.bumper_dy, True)
909  self.bumper_line(self.bumper_fl_x - self.bumper_dx, self.bumper_fl_y - 20, False)
910  self.bumper_line(self.bumper_fl_x + self.bumper_dx, self.bumper_fl_y - 20, False)
911  self.bumper_line(self.bumper_fl_x - 20, self.bumper_fl_y + self.bumper_dy, True)
912  self.bumper_line(self.bumper_fr_x - 20, self.bumper_fr_y - self.bumper_dy, True)
913  self.bumper_line(self.bumper_fr_x - self.bumper_dx, self.bumper_fr_y - 20, False)
914  self.bumper_line(self.bumper_fr_x + self.bumper_dx, self.bumper_fr_y - 20, False)
915  self.bumper_line(self.bumper_fr_x - 20, self.bumper_fr_y + self.bumper_dy, True)
916  self.bumper_line(self.bumper_rl_x - 20, self.bumper_rl_y - self.bumper_dy, True)
917  self.bumper_line(self.bumper_rl_x - self.bumper_dx, self.bumper_rl_y - 20, False)
918  self.bumper_line(self.bumper_rl_x + self.bumper_dx, self.bumper_rl_y - 20, False)
919  self.bumper_line(self.bumper_rl_x - 20, self.bumper_rl_y + self.bumper_dy, True)
920  self.bumper_line(self.bumper_rr_x - 20, self.bumper_rr_y - self.bumper_dy, True)
921  self.bumper_line(self.bumper_rr_x - self.bumper_dx, self.bumper_rr_y - 20, False)
922  self.bumper_line(self.bumper_rr_x + self.bumper_dx, self.bumper_rr_y - 20, False)
923  self.bumper_line(self.bumper_rr_x - 20, self.bumper_rr_y + self.bumper_dy, True)
924 
925  # Populate scene
926  graphics_scene = QGraphicsScene()
927  for bumper in self.bumper_lines:
928  graphics_scene.addItem(bumper)
929  for label in self.bumper_state_labels:
930  graphics_scene.addItem(label)
931  graphics_scene.setSceneRect(0, 0, self._widget.bumperGraphicsView.width() - 4, self._widget.bumperGraphicsView.height() - 4)
932  self._widget.bumperGraphicsView.setScene(graphics_scene)
933  self._widget.bumperGraphicsView.setBackgroundBrush(QBrush(QImage(os.path.join(rospkg.RosPack().get_path('mobility_base_tools'), 'images', 'mb_top.png'))))
934  self._widget.bumperGraphicsView.show()
935 
936  def bumper_line(self, x, y, front):
937  new_line = QGraphicsLineItem()
938  if front:
939  new_line.setLine(x, y, x+40, y)
940  else:
941  new_line.setLine(x, y, x, y+40)
942  new_line.setPen(self.blue_pen)
943  new_line.setVisible(False)
944  self.bumper_lines.append(new_line)
945 
946  def bumper_visible_switch(self, idx, bumper_state):
947  if bumper_state & BumperState.BUMPER_FRONT:
948  self.bumper_lines[idx].setVisible(True)
949  else:
950  self.bumper_lines[idx].setVisible(False)
951  if bumper_state & BumperState.BUMPER_LEFT:
952  self.bumper_lines[idx+1].setVisible(True)
953  else:
954  self.bumper_lines[idx+1].setVisible(False)
955  if bumper_state & BumperState.BUMPER_RIGHT:
956  self.bumper_lines[idx+2].setVisible(True)
957  else:
958  self.bumper_lines[idx+2].setVisible(False)
959  if bumper_state & BumperState.BUMPER_REAR:
960  self.bumper_lines[idx+3].setVisible(True)
961  else:
962  self.bumper_lines[idx+3].setVisible(False)
963 
964  def reset_gui_timer(self):
965  self.gui_update_timer = QTimer(self._widget)
966  self.gui_update_timer.setInterval(100)
967  self.gui_update_timer.setSingleShot(False)
968  self.gui_update_timer.timeout.connect(lambda: self.update_gui_cb())
969  self.gui_update_timer.start()
970 
971  def spawn_full_gui(self):
972  super(DiagnosticGui, self).__init__(self.context_)
973  # Give QObjects reasonable names
974  self.setObjectName('DiagnosticGui')
975 
976  # Create QWidget
977  self._widget = QWidget()
978 
979  # Get path to UI file which should be in the "resource" folder of this package
980  ui_file = os.path.join(rospkg.RosPack().get_path('mobility_base_tools'), 'resource', 'DiagnosticGui.ui')
981  # Extend the widget with all attributes and children from UI file
982  loadUi(ui_file, self._widget)
983  # Give QObjects reasonable names
984  self._widget.setObjectName('DiagnosticGui' + str(self.widget_count))
985  self.widget_count += 1
986  # Add widget to the user interface
987  self.context_.add_widget(self._widget)
988 
989  def spawn_tab_gui(self):
990  super(DiagnosticGui, self).__init__(self.context_)
991  # Give QObjects reasonable names
992  self.setObjectName('DiagnosticGui')
993 
994  # Create QWidget
995  self._widget = QWidget()
996 
997  # Get path to UI file which should be in the "resource" folder of this package
998  ui_file = os.path.join(rospkg.RosPack().get_path('mobility_base_tools'), 'resource', 'DiagnosticGuiTabs.ui')
999  # Extend the widget with all attributes and children from UI file
1000  loadUi(ui_file, self._widget)
1001  # Give QObjects reasonable names
1002  self._widget.setObjectName('DiagnosticGui' + str(self.widget_count))
1003  self.widget_count += 1
1004  # Add widget to the user interface
1005  self.context_.add_widget(self._widget)
1006 
1007  def update_right_stick_indicator(self, lat_val, forward_val):
1008  horiz_val = -self.stick_ind_range_factor * (lat_val - self.stick_ind_range_mid)
1009  vert_val = -self.stick_ind_range_factor * (forward_val - self.stick_ind_range_mid)
1010  r = sqrt(horiz_val * horiz_val + vert_val * vert_val)
1011  if r > self.stick_ind_range_pix / 2:
1012  r = self.stick_ind_range_pix / 2
1013  ang = atan2(vert_val, horiz_val)
1014  px = r * cos(ang)
1015  py = r * sin(ang)
1016  self.stick_ind_r.setPos(QPoint(px, py))
1017  self.stick_line_r.setLine(self.stick_ind_rox, self.stick_ind_roy, self.stick_ind_rox + px, self.stick_ind_roy + py)
1018 
1019  def update_left_stick_indicator(self, yaw_val, enable_val):
1020  horiz_val = -self.stick_ind_range_factor * (yaw_val - self.stick_ind_range_mid)
1021  vert_val = -self.stick_ind_range_factor * (enable_val - self.stick_ind_range_mid)
1022  r = sqrt(horiz_val * horiz_val + vert_val * vert_val)
1023  if r > self.stick_ind_range_pix / 2:
1024  r = self.stick_ind_range_pix / 2
1025  ang = atan2(vert_val, horiz_val)
1026  px = r * cos(ang)
1027  py = r * sin(ang)
1028  self.stick_ind_l.setPos(QPoint(px, py))
1029  self.stick_line_l.setLine(self.stick_ind_lox, self.stick_ind_loy, self.stick_ind_lox + px, self.stick_ind_loy + py)
1030 
1031  def shutdown_plugin(self):
1032  pass
def update_right_stick_indicator(self, lat_val, forward_val)
def bumper_visible_switch(self, idx, bumper_state)
def update_left_stick_indicator(self, yaw_val, enable_val)


mobility_base_tools
Author(s): Dataspeed Inc.
autogenerated on Sun Oct 6 2019 03:40:06