biotac.py
Go to the documentation of this file.
1 # Copyright (c) 2013, Shadow Robot Company, SynTouch LLC
2 # All rights reserved.
3 #
4 # Redistribution and use in source and binary forms, with or without
5 # modification, are permitted provided that the following conditions
6 # are met:
7 #
8 # * Redistributions of source code must retain the above copyright
9 # notice, this list of conditions and the following disclaimer.
10 # * Redistributions in binary form must reproduce the above
11 # copyright notice, this list of conditions and the following
12 # disclaimer in the documentation and/or other materials provided
13 # with the distribution.
14 # * Neither the name of the TU Darmstadt nor the names of its
15 # contributors may be used to endorse or promote products derived
16 # from this software without specific prior written permission.
17 #
18 # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
19 # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
20 # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
21 # FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
22 # COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
23 # INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
24 # BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
25 # LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
26 # CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 # LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
28 # ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29 # POSSIBILITY OF SUCH DAMAGE.
30 
31 
32 import rospy
33 import rospkg
34 import os
35 
36 from qt_gui.plugin import Plugin
37 from python_qt_binding import loadUi
38 
39 from QtGui import QIcon, QColor, QPainter, QFont
40 from QtWidgets import QMessageBox, QWidget
41 from QtCore import QRectF, QTimer
42 from sr_robot_msgs.msg import Biotac, BiotacAll
43 from sr_utilities.hand_finder import HandFinder
44 
45 
47  _nb_electrodes_biotac = 19
48  _nb_electrodes_biotac_sp = 24
49 
50  def define_electrodes(self):
52  rospy.get_param(
53  "sr_gui_biotac/sensing_electrodes_x_locations",
54  [6.45, 3.65, 3.65, 6.45, 3.65, 6.45, 0.00, 1.95, -1.95,
55  0.00, -6.45, - 3.65, -3.65, -6.45, -3.65, -6.45, 0.00,
56  0.00, 0.00]) # Physical electrode locations on the sensor
58  rospy.get_param(
59  "sr_gui_biotac/sensing_electrodes_y_locations",
60  [7.58, 11.28, 14.78, 16.58, 19.08, 21.98, 4.38, 6.38, 6.38,
61  8.38, 7.58, 11.28, 14.78, 16.58, 19.08, 21.98, 11.38,
62  18.38, 22.18])
63 
65  rospy.get_param(
66  "sr_gui_biotac/excitation_electrodes_x_locations",
67  [6.45, 3.75, -3.75, -6.45])
69  rospy.get_param(
70  "sr_gui_biotac/excitation_electrodes_y_locations",
71  [12.48, 24.48, 24.48, 12.48])
72 
74  rospy.get_param(
75  "sr_gui_biotac/sensing_electrodes_x_locations",
76  [5.00, 3.65, 6.45, 4.40, 2.70, 6.45, 4.40, 1.50, 4.00, 4.50,
77  -5.00, - 3.65, -6.45, -4.40, -2.70, -6.45, -4.40, -1.50, -4.00, -4.50,
78  0.00, 1.95, -1.95, 0.00]) # Physical electrode locations on the sensor
80  rospy.get_param(
81  "sr_gui_biotac/sensing_electrodes_y_locations",
82  [4.38, 6.38, 14.78, 15.50, 18.50, 19.08, 20.00, 21.00, 23.00, 25.00,
83  4.38, 6.38, 14.78, 15.50, 18.50, 19.08, 20.00, 21.00, 23.00, 25.00,
84  7.38, 11.50, 11.50, 15.20])
85 
87  rospy.get_param(
88  "sr_gui_biotac/excitation_electrodes_x_locations",
89  [5.30, 6.00, -5.30, -6.00])
91  rospy.get_param(
92  "sr_gui_biotac/excitation_electrodes_y_locations",
93  [9.00, 22.00, 9.00, 22.00])
94 
95  def assign_electrodes(self, nb_electrodes):
96  if nb_electrodes == self._nb_electrodes_biotac:
101  self.factor = rospy.get_param(
102  "sr_gui_biotac/display_location_scale_factor",
103  17.5) # Sets the multiplier to go from physical electrode
104  # location on the sensor in mm to display location in pixels
105  elif nb_electrodes == self._nb_electrodes_biotac_sp:
110  self.factor = 25.0
111  else:
112  rospy.logerr("Number of electrodes %d not matching known biotac models. expected: %d or %d",
113  nb_electrodes, self._nb_electrodes_biotac, self._nb_electrodes_biotac_sp)
114  return
115 
116  for n in range(len(self.sensing_electrodes_x)):
117  self.sensing_electrodes_x[n] = (
118  self.sensing_electrodes_x[n] * self.factor +
119  self.x_display_offset[0])
120  self.sensing_electrodes_y[n] = (
121  self.sensing_electrodes_y[n] * self.factor +
122  self.y_display_offset[0])
123 
124  for n in range(len(self.excitation_electrodes_x)):
125  self.excitation_electrodes_x[n] = (
126  self.excitation_electrodes_x[n] * self.factor +
127  self.x_display_offset[0])
128  self.excitation_electrodes_y[n] = (
129  self.excitation_electrodes_y[n] * self.factor +
130  self.y_display_offset[0])
131 
132  def tactile_cb(self, msg):
133  if len(msg.tactiles[0].electrodes) != self._nb_electrodes:
134  self._nb_electrodes = len(msg.tactiles[0].electrodes)
136  self.latest_data = msg
137 
139  r = 0.0
140  g = 0.0
141  b = 255.0
142 
143  value = float(value)
144 
145  threshold = (0.0, 1000.0, 2000.0, 3000.0, 4095.0)
146 
147  if value <= threshold[0]:
148  pass
149 
150  elif value < threshold[1]:
151 
152  r = 255
153  g = 255 * ((value - threshold[0]) / (threshold[1] - threshold[0]))
154  b = 0
155 
156  elif value < threshold[2]:
157 
158  r = 255 * ((threshold[2] - value) / (threshold[2] - threshold[1]))
159  g = 255
160  b = 0
161 
162  elif value < threshold[3]:
163 
164  r = 0
165  g = 255
166  b = 255 * ((value - threshold[2]) / (threshold[3] - threshold[2]))
167 
168  elif value < threshold[4]:
169 
170  r = 0
171  g = 255 * ((threshold[4] - value) / (threshold[4] - threshold[3]))
172  b = 255
173 
174  return QColor(r, g, b)
175 
177  name = self._widget.btSelect.currentText()
178  fingers = ["FF", "MF", "RF", "LF", "TH"]
179  return fingers.index(name)
180 
181  def draw_electrode(self, painter, elipse_x, elipse_y, text_x, text_y,
182  colour, text):
183 
184  rect = QRectF(elipse_x, elipse_y, self.RECTANGLE_WIDTH,
185  self.RECTANGLE_HEIGHT)
186 
187  painter.setBrush(colour)
188  painter.drawEllipse(rect)
189 
190  rect.setX(text_x)
191  rect.setY(text_y)
192 
193  painter.drawText(rect, text)
194 
195  def paintEvent(self, paintEvent):
196  painter = QPainter(self._widget.scrollAreaWidgetContents)
197  which_tactile = self.biotac_id_from_dropdown()
198 
199  painter.setFont(QFont("Arial", self.label_font_size[0]))
200 
201  if len(self.sensing_electrodes_x) == len(self.latest_data.tactiles[which_tactile].electrodes):
202  for n in range(len(self.sensing_electrodes_x)):
203  value = self.latest_data.tactiles[which_tactile].electrodes[n]
204  eval("self._widget.lcdE%02d.display(%d)" % (n + 1, value))
205  colour = self.get_electrode_colour_from_value(value)
206 
207  elipse_x = self.sensing_electrodes_x[n]
208  elipse_y = self.sensing_electrodes_y[n]
209 
210  if n < 9:
211  text_x = elipse_x + self.x_display_offset[1]
212  text_y = elipse_y + self.y_display_offset[1]
213 
214  else:
215  text_x = elipse_x + self.x_display_offset[2]
216  text_y = elipse_y + self.y_display_offset[2]
217 
218  self.draw_electrode(painter, elipse_x, elipse_y, text_x, text_y,
219  colour, str(n + 1))
220 
221  painter.setFont(QFont("Arial", self.label_font_size[1]))
222 
223  for n in range(len(self.excitation_electrodes_x)):
224  elipse_x = self.excitation_electrodes_x[n]
225  elipse_y = self.excitation_electrodes_y[n]
226 
227  colour = QColor(127, 127, 127)
228 
229  text_x = elipse_x + self.x_display_offset[3]
230  text_y = elipse_y + self.y_display_offset[3]
231 
232  self.draw_electrode(painter, elipse_x, elipse_y, text_x, text_y,
233  colour, "X" + str(n + 1))
234 
235  self._widget.update()
236 
237  def subscribe_to_topic(self, prefix):
238  if prefix:
239  rospy.Subscriber(prefix + "tactile", BiotacAll, self.tactile_cb)
240 
241  def load_params(self):
242  self.RECTANGLE_WIDTH = rospy.get_param(
243  "sr_gui_biotac/electrode_display_width",
244  45) # Display sizes for electrodes in pixels
245  self.RECTANGLE_HEIGHT = rospy.get_param(
246  "sr_gui_biotac/electrode_display_height", 45)
247 
248  self.factor = rospy.get_param(
249  "sr_gui_biotac/display_location_scale_factor",
250  17.5) # Sets the multiplier to go from physical electrode
251  # location on the sensor in mm to display location in pixels
252  self.x_display_offset = rospy.get_param(
253  "sr_gui_biotac/x_display_offset", [200, 12.5, 4.5,
254  3.5]) # Pixel offsets for
255  # displaying electrodes. offset[0] is applied to each electrode.
256  # 1,2 and 3 are the label offsets for displaying electrode number.
257  self.y_display_offset = rospy.get_param(
258  "sr_gui_biotac/y_display_offset", [-50, 4.0, 4.0, 4.0])
259  self.label_font_size = rospy.get_param(
260  "sr_gui_biotac/electrode_label_font_sizes", [24,
261  22]) # Font sizes
262  # for labels on sensing + excitation electrodes
263 
264  if self._hand_parameters.mapping:
265  self.default_topic = (
266  self._hand_parameters.mapping.values()[0] + '/')
267  else:
268  self.default_topic = ""
269 
270  def __init__(self, context):
271 
272  super(SrGuiBiotac, self).__init__(context)
273  self.setObjectName('SrGuiBiotac')
274  self._hand_finder = HandFinder()
275  self._hand_parameters = self._hand_finder.get_hand_parameters()
276  self.load_params()
277 
278  self._publisher = None
279  self._widget = QWidget()
280 
281  self.latest_data = BiotacAll()
282 
283  self.define_electrodes()
286 
287  ui_file = os.path.join(rospkg.RosPack().get_path('sr_gui_biotac'),
288  'uis', 'SrGuiBiotac.ui')
289  loadUi(ui_file, self._widget)
290  self._widget.setObjectName('SrBiotacUi')
291 
292  self.timer = QTimer(self._widget)
293  # self._widget.connect(self.timer, SIGNAL("timeout()"),
294  # self._widget.scrollAreaWidgetContents.update)
295  self.timer.timeout.connect(self._widget.scrollAreaWidgetContents.update)
296  self._widget.scrollAreaWidgetContents.paintEvent = self.paintEvent
297 
299 
300  for hand in self._hand_parameters.mapping:
301  self._widget.select_prefix.addItem(
302  self._hand_parameters.mapping[hand])
303  if not self._hand_parameters.mapping:
304  rospy.logerr("No hand detected")
305  QMessageBox.warning(
306  self._widget, "warning", "No hand is detected")
307  else:
308  self._widget.select_prefix.setCurrentIndex(0)
309 
310  '''
311  self._widget.connect(self._widget.select_prefix,
312  SIGNAL("activated(QString)"),
313  self.subscribe_to_topic)
314  '''
315  self._widget.select_prefix.activated['QString'].connect(self.subscribe_to_topic)
316 
317  self.timer.start(50)
318 
319  context.add_widget(self._widget)
def get_electrode_colour_from_value(self, value)
Definition: biotac.py:138
def assign_electrodes(self, nb_electrodes)
Definition: biotac.py:95
def subscribe_to_topic(self, prefix)
Definition: biotac.py:237
def draw_electrode(self, painter, elipse_x, elipse_y, text_x, text_y, colour, text)
Definition: biotac.py:182
def paintEvent(self, paintEvent)
Definition: biotac.py:195
def __init__(self, context)
Definition: biotac.py:270


sr_gui_biotac
Author(s): Dan Greenwald
autogenerated on Wed Oct 14 2020 03:22:47