fingertip_verify.py
Go to the documentation of this file.
00001 #!/usr/bin/env python
00002 # Software License Agreement (BSD License)
00003 #
00004 # Copyright (c) 2010, Willow Garage, Inc.
00005 # All rights reserved.
00006 #
00007 # Redistribution and use in source and binary forms, with or without
00008 # modification, are permitted provided that the following conditions
00009 # are met:
00010 #
00011 #  * Redistributions of source code must retain the above copyright
00012 #    notice, this list of conditions and the following disclaimer.
00013 #  * Redistributions in binary form must reproduce the above
00014 #    copyright notice, this list of conditions and the following
00015 #    disclaimer in the documentation and/or other materials provided
00016 #    with the distribution.
00017 #  * Neither the name of the Willow Garage nor the names of its
00018 #    contributors may be used to endorse or promote products derived
00019 #    from this software without specific prior written permission.
00020 #
00021 # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
00022 # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
00023 # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
00024 # FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
00025 # COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
00026 # INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
00027 # BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
00028 # LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
00029 # CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
00030 # LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
00031 # ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
00032 # POSSIBILITY OF SUCH DAMAGE.
00033 #
00034 
00035 ##\author Kevin Watts
00036 
00037 ##\brief Displays fingertip pressure GUI. Display turns green after sensor is pressed
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         #rospy.spin()
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     # Need an arg for left/right gripper


qualification
Author(s): Kevin Watts (watts@willowgarage.com), Josh Faust (jfaust@willowgarage.com)
autogenerated on Sat Dec 28 2013 17:57:34