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