00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039 from __future__ import with_statement
00040
00041 TOUCH = 5000
00042 NUMSENSORS = 22
00043 MINVALUE = -100000
00044 RATE = 5
00045
00046 import roslib; roslib.load_manifest('qualification')
00047
00048 from fingertip_pressure.fingertip_panel import FingertipPressurePanel
00049
00050 import wx
00051 import threading
00052 from wx import xrc
00053
00054 from pr2_self_test_msgs.srv import TestResult, TestResultRequest
00055 from pr2_msgs.msg import PressureState
00056 import rospy
00057
00058 import sys
00059
00060
00061 class FingertipVerifyPanel(FingertipPressurePanel):
00062 def __init__(self, parent):
00063 FingertipPressurePanel.__init__(self, parent)
00064
00065 self.set_stale()
00066
00067
00068 def set_stale(self):
00069 self._max_values = [MINVALUE for i in range(0, NUMSENSORS)]
00070 for i in range(0, NUMSENSORS):
00071 self.pad[i].SetBackgroundColour("Light Blue")
00072 self.pad[i].SetValue("#%i\nStale" % i)
00073
00074 def check_ok(self):
00075 ok = True
00076 for i in range(0, NUMSENSORS):
00077 ok = ok and self._max_values[i] > TOUCH
00078
00079 return ok
00080
00081 def new_message(self, data):
00082 with self._mutex:
00083 for i in range(0, NUMSENSORS):
00084 self._max_values[i] = max(data[i], self._max_values[i])
00085
00086 if self._max_values[i] > TOUCH:
00087 self.pad[i].SetBackgroundColour("Light Green")
00088 else:
00089 self.pad[i].SetBackgroundColour("Red")
00090
00091 self.pad[i].SetValue("#%i\n%i\nMax: %i" % (i, data[i], self._max_values[i]))
00092
00093
00094 class FingerTipStatusPanel(wx.Panel):
00095 def __init__(self, parent, topic, result_cb, left = True):
00096 wx.Panel.__init__(self, parent, wx.ID_ANY)
00097
00098 self._mutex = threading.Lock()
00099
00100 sizer = wx.BoxSizer(wx.VERTICAL)
00101 self.verify_panel = FingertipVerifyPanel(self)
00102 sizer.Add(self.verify_panel.panel, 1, wx.EXPAND)
00103
00104 self.pass_button = wx.Button(self, wx.ID_OK, "Pass")
00105 self.fail_button = wx.Button(self, wx.ID_CANCEL, "Fail")
00106
00107 self.pass_button.Bind(wx.EVT_BUTTON, self.on_pass)
00108 self.fail_button.Bind(wx.EVT_BUTTON, self.on_fail)
00109
00110 self.pass_button.Enabled = False
00111
00112 button_sizer = wx.BoxSizer(wx.HORIZONTAL)
00113 button_sizer.Add(self.pass_button, 0, wx.ALIGN_CENTER | wx.ALL, 5)
00114 button_sizer.Add(self.fail_button, 0, wx.ALIGN_CENTER | wx.ALL, 5)
00115
00116 sizer.Add(button_sizer)
00117
00118 self.SetSizer(sizer)
00119 self.Layout()
00120
00121
00122 self._last_update_time = 0
00123 self._pressure_sub = rospy.Subscriber(topic, PressureState, self.pressure_cb)
00124
00125 self._left_side = left
00126
00127 self.timer = wx.Timer(self, 1)
00128 self.Bind(wx.EVT_TIMER, self.on_timer, self.timer)
00129
00130 self.stale_timer = wx.Timer(self, 2)
00131 self.Bind(wx.EVT_TIMER, self.on_stale_timer, self.stale_timer)
00132 self.stale_timer.Start(1000)
00133
00134 self.result_cb = result_cb
00135
00136 def on_close(self):
00137 if self._pressure_sub:
00138 self._pressure_sub.unregister()
00139 self._pressure_sub = None
00140
00141
00142 def on_pass(self, event):
00143 self.result_cb(True)
00144
00145 def on_fail(self, event):
00146 self.result_cb(False)
00147
00148
00149 def on_timer(self, event):
00150 pass
00151
00152 def on_stale_timer(self, event):
00153 if rospy.get_time() - self._last_update_time > 3:
00154 self.verify_panel.set_stale()
00155 self.pass_button.Enabled = False
00156
00157 def pressure_cb(self, msg):
00158 with self._mutex:
00159 if self._left_side:
00160 self._data = msg.l_finger_tip
00161 else:
00162 self._data = msg.r_finger_tip
00163
00164 self._last_update_time = rospy.get_time()
00165
00166 if not self.timer.IsRunning():
00167 self.timer.Start(1000/RATE, True)
00168 wx.CallAfter(self.display)
00169
00170 def display(self):
00171 with self._mutex:
00172 self.verify_panel.new_message(self._data)
00173
00174 if self.verify_panel.check_ok():
00175 self.pass_button.Enabled = True
00176
00177 self.Refresh()
00178
00179 class FingerTipVerifyFrame(wx.Frame):
00180 def __init__(self, parent, id, title):
00181 wx.Frame.__init__(self, parent, wx.ID_ANY, title)
00182
00183 sizer = wx.BoxSizer()
00184 self.SetSizer(sizer)
00185
00186 self._panel = FingerTipStatusPanel(self, 'pressure/r_gripper_motor', self.result_cb)
00187
00188 sizer.Add(self._panel, 1, wx.EXPAND)
00189
00190 self.data_sent = False
00191 self.result_service = rospy.ServiceProxy('/test_result', TestResult)
00192
00193 self.shutdown_timer = wx.Timer(self, 10)
00194 self.Bind(wx.EVT_TIMER, self.on_shutdown_timer, self.shutdown_timer)
00195
00196 self.Bind(wx.EVT_CLOSE, self.on_close)
00197
00198
00199 def send_results(self, result, msg = ''):
00200 if self.data_sent:
00201 return
00202
00203 r = TestResultRequest()
00204 if result:
00205 r.html_result = '<p>Fingertip verification OK</p>\n'
00206 r.text_summary = 'Fingertip verification OK'
00207 r.result = TestResultRequest.RESULT_PASS
00208 else:
00209 r.html_result = '<p>Fingertip verification failed</p>\n<p>%s</p>' % msg
00210 r.text_summary = 'Fingertip verification failed.'
00211 r.result = TestResultRequest.RESULT_FAIL
00212
00213 print 'Sending test result. Summary: %s' % r.text_summary
00214 try:
00215 rospy.wait_for_service('test_result', 2)
00216 except Exception, e:
00217 return False
00218 self.result_service.call(r)
00219 self.data_sent = True
00220 return True
00221
00222 def result_cb(self, result, msg = ''):
00223 self.send_results(result, msg = '')
00224 self.Close(True)
00225
00226 def on_close(self, event):
00227 try:
00228 if event.CanVeto():
00229 dialog = wx.MessageDialog(self, 'Are you sure you want to close this window? Fingertip verification will automatically fail.', 'Confirm Close', wx.OK|wx.CANCEL)
00230 if dialog.ShowModal() != wx.ID_OK:
00231 print 'Vetoing'
00232 event.Veto()
00233 return
00234
00235 self._panel.on_close()
00236 self.send_results(False, 'Window closed')
00237
00238 except Exception, e:
00239 print >> sys.stderr, "Caught exception on close:\n%s" % str(e)
00240
00241 self.Destroy()
00242
00243 def on_exit(self, event):
00244 self.Close(True)
00245
00246 def on_shutdown_timer(self, event):
00247 if rospy.is_shutdown():
00248 self.Close(True)
00249
00250 class FingerTipVerifyApp(wx.App):
00251 def __init__(self):
00252 wx.App.__init__(self, clearSigInt = False)
00253
00254 def OnInit(self):
00255 self._frame = FingerTipVerifyFrame(None, -1, "Fingertip Sensor Check")
00256 self._frame.SetMinSize(self._frame.GetEffectiveMinSize())
00257 self._frame.Layout()
00258 self._frame.Show()
00259
00260 return True
00261
00262 if __name__ == '__main__':
00263 rospy.init_node('finger_verifier')
00264
00265 app = FingerTipVerifyApp()
00266 try:
00267 app.MainLoop()
00268
00269 except KeyboardInterrupt:
00270 raise
00271 except Exception, e:
00272 print 'Caught exception'
00273 import traceback
00274 rospy.logerr(traceback.format_exc())
00275
00276 sys.exit(0)
00277
00278