00001 import roslib; roslib.load_manifest('rcommander')
00002 import rospy
00003 from PyQt4.QtGui import *
00004 from PyQt4.QtCore import *
00005 import pr2_gripper_sensor_msgs.msg as gr
00006 import actionlib_msgs.msg as am
00007 import actionlib
00008 import tool_utils as tu
00009 import smach
00010 import graph_model as gm
00011 import sm_thread_runner as smtr
00012
00013 class GripperEventTool(tu.ToolBase):
00014
00015 def __init__(self, rcommander):
00016 tu.ToolBase.__init__(self, rcommander, 'gripper_event', 'Gripper Event')
00017 self.child_gm = None
00018
00019
00020 def get_smach_class(self):
00021 return GripperEventState
00022
00023
00024 def set_child_node(self, child_smach):
00025 self.child_gm = gm.GraphModel()
00026 self.child_gm.add_node(child_smach)
00027 self.child_gm.set_start_state(child_smach.get_name())
00028 self.child_gm.set_document(gm.FSMDocument(child_smach.get_name(), modified=False, real_filename=False))
00029
00030 def fill_property_box(self, pbox):
00031 formlayout = pbox.layout()
00032
00033 self.gripper_radio_boxes, self.gripper_radio_buttons = tu.make_radio_box(pbox, ['Left', 'Right'], 'gripper_event_arm')
00034 self.event_box = QComboBox(pbox)
00035 for event in GripperEventState.EVENT_LIST:
00036 self.event_box.addItem(event)
00037 self.accel_box = tu.SliderBox(pbox, 8.25, 30, 0., .25, 'gripper_accel', units='m/s^2')
00038 self.slip_box = tu.SliderBox(pbox, .01, -.5, .5, .1, 'gripper_slip', units='')
00039
00040 formlayout.addRow('&Gripper', self.gripper_radio_boxes)
00041 formlayout.addRow('&Event', self.event_box)
00042 formlayout.addRow('&Acceleration', self.accel_box.container)
00043 formlayout.addRow('&Slip', self.slip_box.container)
00044 pbox.update()
00045
00046 def _create_node(self, name=None):
00047 if self.child_gm == None:
00048 raise RuntimeError('No child node!')
00049 selected_arm = None
00050 for r in self.gripper_radio_buttons:
00051 if r.isChecked():
00052 selected_arm = str(r.text()).lower()
00053 if selected_arm == None:
00054 raise RuntimeError('No arm selected!')
00055
00056 event_type = str(self.event_box.currentText())
00057 accel_val = self.accel_box.value()
00058 slip_val = self.slip_box.value()
00059
00060 if name == None:
00061 nname = self.name + str(self.counter)
00062 else:
00063 nname = name
00064
00065 return GripperEventState(nname, self.child_gm, selected_arm, event_type, accel_val, slip_val)
00066
00067 def _node_selected(self, gripper_event_state):
00068 if gripper_event_state.arm == 'left':
00069 self.gripper_radio_buttons[0].setChecked(True)
00070 if gripper_event_state.arm == 'right':
00071 self.gripper_radio_buttons[1].setChecked(True)
00072
00073 self.event_box.setCurrentIndex(self.event_box.findText(gripper_event_state.event_type))
00074 self.accel_box.set_value(gripper_event_state.accel)
00075 self.slip_box.set_value(gripper_event_state.slip)
00076 self.child_gm = gripper_event_state.child_gm
00077
00078
00079
00080 def reset(self):
00081 self.gripper_radio_buttons[0].setChecked(True)
00082 self.event_box.setCurrentIndex(self.event_box.findText(GripperEventState.EVENT_LIST[0]))
00083 self.accel_box.set_value(8.25)
00084 self.slip_box.set_value(.01)
00085 self.child_gm = None
00086
00087
00088 class GripperEventState(smach.State, tu.EmbeddableState):
00089
00090 EVENT_LIST = ['acceleration', 'slip', 'finger side impact or acceleration', 'slip and acceleration', 'finger side impact, slip or acceleration']
00091 EVENT_CODES = {'acceleration': gr.PR2GripperEventDetectorCommand.ACC,
00092 'slip': gr.PR2GripperEventDetectorCommand.SLIP,
00093 'finger side impact or acceleration': gr.PR2GripperEventDetectorCommand.FINGER_SIDE_IMPACT_OR_ACC,
00094 'slip and acceleration': gr.PR2GripperEventDetectorCommand.SLIP_AND_ACC,
00095 'finger side impact, slip or acceleration': gr.PR2GripperEventDetectorCommand.FINGER_SIDE_IMPACT_OR_SLIP_OR_ACC}
00096 EVENT_OUTCOME = 'detected_event'
00097
00098 def __init__(self, name, child_gm, arm, event_type, accel, slip):
00099 tu.EmbeddableState.__init__(self, name, child_gm)
00100 self.arm = arm
00101 self.event_type = event_type
00102 self.accel = accel
00103 self.slip = slip
00104 self.__init_unpicklables__()
00105
00106 def __init_unpicklables__(self):
00107
00108 input_keys = []
00109 output_keys = []
00110 outcomes = []
00111
00112 if self.get_child() != None:
00113 sm = self.get_child().create_state_machine()
00114 input_keys = list(sm.get_registered_input_keys())
00115 output_keys = list(sm.get_registered_output_keys())
00116 outcomes = list(sm.get_registered_outcomes()) + [GripperEventState.EVENT_OUTCOME]
00117 smach.State.__init__(self, outcomes = outcomes, input_keys = input_keys, output_keys = output_keys)
00118
00119
00120 if self.arm == 'left':
00121 a = 'l'
00122 elif self.arm == 'right':
00123 a = 'r'
00124 else:
00125 raise RuntimeError('Error')
00126 evd_name = a + '_gripper_sensor_controller/event_detector'
00127 self.action_client = actionlib.SimpleActionClient(evd_name, gr.PR2GripperEventDetectorAction)
00128
00129
00130 def __getstate__(self):
00131 state = tu.EmbeddableState.__getstate__(self)
00132 my_state = [self.arm, self.event_type, self.accel, self.slip]
00133 return {'embeddable': state, 'self': my_state}
00134
00135
00136 def __setstate__(self, state):
00137 tu.EmbeddableState.__setstate__(self, state['embeddable'])
00138 self.arm, self.event_type, self.accel, self.slip = state['self']
00139 self.__init_unpicklables__()
00140
00141
00142 def recreate(self, new_graph_model):
00143 return GripperEventState(self.name, new_graph_model, self.arm, self.event_type, self.accel, self.slip)
00144
00145 def _detected_event(self):
00146 state = self.action_client.get_state()
00147 gripper_event_detected = state not in [am.GoalStatus.ACTIVE, am.GoalStatus.PENDING]
00148 return gripper_event_detected
00149
00150 def execute(self, userdata):
00151 print '>> executing, got userdata:', userdata, 'keys', userdata.keys()
00152 print 'input keys', self.get_registered_input_keys(), 'ud_keys', userdata._ud.keys()
00153 rospy.sleep(2)
00154
00155 goal = gr.PR2GripperEventDetectorGoal()
00156 goal.command.acceleration_trigger_magnitude = self.accel
00157 goal.command.slip_trigger_magnitude = self.slip
00158 goal.command.trigger_conditions = GripperEventState.EVENT_CODES[self.event_type]
00159
00160 self.action_client.send_goal(goal)
00161
00162
00163
00164 child_gm = self.get_child()
00165
00166
00167
00168 sm = child_gm.create_state_machine(userdata=userdata._ud)
00169
00170 child_gm.run(self.child_gm.get_start_state(), state_machine=sm)
00171 rthread = child_gm.sm_thread['run_sm']
00172
00173
00174
00175
00176
00177 event = self._detected_event()
00178 preempted = False
00179 r = rospy.Rate(100)
00180 while not event:
00181 if rthread.exception != None:
00182 raise rthread.exception
00183
00184 if rthread.outcome != None:
00185 rospy.loginfo('Gripper Event Tool: child node finished with outcome ' + rthread.outcome)
00186 break
00187
00188 if not rthread.isAlive():
00189 rospy.loginfo('Gripper Event Tool: child node died')
00190 break
00191
00192 if self.preempt_requested():
00193 rospy.loginfo('Gripper Event Tool: preempt requested')
00194 self.service_preempt()
00195 preempted = True
00196 break
00197
00198 event = self._detected_event()
00199 if event:
00200 rospy.loginfo('Gripper Event Tool: DETECTED EVENT')
00201
00202 r.sleep()
00203
00204
00205
00206
00207 rthread.preempt()
00208 rthread.except_preempt()
00209
00210 child_gm.sm_thread = {}
00211
00212 if preempted:
00213 return 'preempted'
00214
00215 if event:
00216 return self.EVENT_OUTCOME
00217 else:
00218
00219
00220
00221
00222
00223
00224
00225 return rthread.outcome
00226
00227
00228
00229
00230
00231
00232
00233
00234
00235
00236
00237
00238
00239
00240
00241
00242
00243
00244
00245
00246
00247
00248
00249
00250
00251
00252