00001
00002 import numpy as np, math
00003 import copy
00004 from threading import RLock
00005
00006 import roslib; roslib.load_manifest('hrl_pr2_door_opening')
00007 roslib.load_manifest('equilibrium_point_control')
00008 import rospy
00009
00010 from equilibrium_point_control.msg import MechanismKinematicsRot
00011 from equilibrium_point_control.msg import MechanismKinematicsJac
00012 from equilibrium_point_control.msg import ForceTrajectory
00013 from geometry_msgs.msg import Point32
00014 from std_msgs.msg import Empty
00015
00016 import epc
00017 import hrl_lib.util as ut
00018
00019 class Door_EPC(epc.EPC):
00020 def __init__(self, robot):
00021 epc.EPC.__init__(self, robot)
00022
00023 self.mech_kinematics_lock = RLock()
00024 self.fit_circle_lock = RLock()
00025
00026 rospy.Subscriber('mechanism_kinematics_rot',
00027 MechanismKinematicsRot,
00028 self.mechanism_kinematics_rot_cb)
00029 rospy.Subscriber('epc/stop', Empty, self.stop_cb)
00030
00031 self.force_traj_pub = rospy.Publisher('epc/force_test', ForceTrajectory)
00032 self.mech_traj_pub = rospy.Publisher('mechanism_trajectory', Point32)
00033
00034 def init_log(self):
00035 self.f_list = []
00036 self.f_list_ati = []
00037 self.f_list_estimate = []
00038 self.f_list_torques = []
00039 self.cep_list = []
00040 self.ee_list = []
00041 self.ft = ForceTrajectory()
00042 if self.mechanism_type != '':
00043 self.ft.type = self.mechanism_type
00044 else:
00045 self.ft.type = 'rotary'
00046
00047 def log_state(self, arm):
00048
00049 f = self.robot.get_wrist_force_ati(arm, base_frame=True)
00050 self.f_list_ati.append(f.A1.tolist())
00051
00052 f = self.robot.get_wrist_force_estimate(arm, base_frame=True)
00053 self.f_list_estimate.append(f.A1.tolist())
00054
00055 f = self.robot.get_force_from_torques(arm)
00056 self.f_list_torques.append(f.A1.tolist())
00057
00058 f = self.robot.get_wrist_force(arm, base_frame=True)
00059 self.f_list.append(f.A1.tolist())
00060
00061 cep, _ = self.robot.get_cep_jtt(arm, hook_tip=True)
00062 self.cep_list.append(cep.A1.tolist())
00063
00064 ee, _ = self.robot.end_effector_pos(arm)
00065 self.ee_list.append(ee.A1.tolist())
00066
00067 if self.started_pulling_on_handle == False:
00068 if f[0,0] > 10.:
00069 self.started_pulling_on_handle_count += 1
00070 else:
00071 self.started_pulling_on_handle_count = 0
00072 self.init_log()
00073 self.init_tangent_vector = None
00074
00075 if self.started_pulling_on_handle_count > 1:
00076 self.started_pulling_on_handle = True
00077
00078 return ''
00079
00080
00081 def stop_cb(self, cmd):
00082 self.stopping_string = 'stop_cb called.'
00083
00084 def common_stopping_conditions(self):
00085 stop = ''
00086
00087 wrist_force = self.robot.get_wrist_force(0, base_frame=True)
00088 mag = np.linalg.norm(wrist_force)
00089 if mag > self.eq_force_threshold:
00090 stop = 'force exceed'
00091
00092 if mag < 1.2 and self.hooked_location_moved:
00093 if (self.prev_force_mag - mag) > 30.:
00094 stop = 'slip: force step decrease and below thresold.'
00095 else:
00096 self.slip_count += 1
00097 else:
00098 self.slip_count = 0
00099
00100 if self.slip_count == 10:
00101 stop = 'slip: force below threshold for too long.'
00102 return stop
00103
00104 def mechanism_kinematics_rot_cb(self, mk):
00105 self.fit_circle_lock.acquire()
00106 self.cx_start = mk.cx
00107 self.cy_start = mk.cy
00108 self.cz_start = mk.cz
00109 self.rad = mk.rad
00110 self.fit_circle_lock.release()
00111
00112
00113
00114
00115
00116
00117
00118
00119
00120 def cep_gen_control_radial_force(self, arm, cep, cep_vel):
00121 self.log_state(arm)
00122 if self.started_pulling_on_handle == False:
00123 cep_vel = 0.02
00124
00125
00126 step_size = 0.1 * cep_vel
00127 stop = self.common_stopping_conditions()
00128 wrist_force = self.robot.get_wrist_force(arm, base_frame=True)
00129 mag = np.linalg.norm(wrist_force)
00130
00131 curr_pos, _ = self.robot.get_ee_jtt(arm)
00132 if len(self.ee_list)>1:
00133 start_pos = np.matrix(self.ee_list[0]).T
00134 else:
00135 start_pos = curr_pos
00136
00137
00138 if self.started_pulling_on_handle:
00139 self.mech_traj_pub.publish(Point32(curr_pos[0,0],
00140 curr_pos[1,0], curr_pos[2,0]))
00141
00142 self.fit_circle_lock.acquire()
00143 rad = self.rad
00144 cx_start, cy_start = self.cx_start, self.cy_start
00145 cz_start = self.cz_start
00146 self.fit_circle_lock.release()
00147 cx, cy = cx_start, cy_start
00148 cz = cz_start
00149 print 'cx, cy, r:', cx, cy, rad
00150
00151 radial_vec = curr_pos - np.matrix([cx,cy,cz]).T
00152 radial_vec = radial_vec/np.linalg.norm(radial_vec)
00153 if cy_start < start_pos[1,0]:
00154 tan_x,tan_y = -radial_vec[1,0],radial_vec[0,0]
00155 else:
00156 tan_x,tan_y = radial_vec[1,0],-radial_vec[0,0]
00157
00158 if tan_x > 0. and (start_pos[0,0]-curr_pos[0,0]) < 0.09:
00159 tan_x = -tan_x
00160 tan_y = -tan_y
00161
00162 if cy_start > start_pos[1,0]:
00163 radial_vec = -radial_vec
00164
00165 rv = radial_vec
00166 force_vec = np.matrix([rv[0,0], rv[1,0], 0.]).T
00167 tangential_vec = np.matrix([tan_x, tan_y, 0.]).T
00168
00169 tangential_vec_ts = tangential_vec
00170 radial_vec_ts = radial_vec
00171 force_vec_ts = force_vec
00172
00173 if arm == 'right_arm' or arm == 0:
00174 if force_vec_ts[1,0] < 0.:
00175 force_vec_ts = -force_vec_ts
00176 else:
00177 if force_vec_ts[1,0] > 0.:
00178 force_vec_ts = -force_vec_ts
00179
00180 f_vec = -1*np.array([wrist_force[0,0], wrist_force[1,0],
00181 wrist_force[2,0]])
00182 f_rad_mag = np.dot(f_vec, force_vec.A1)
00183 err = f_rad_mag-4.
00184 if err>0.:
00185 kp = -0.1
00186 else:
00187 kp = -0.2
00188 radial_motion_mag = kp * err
00189 radial_motion_vec = force_vec * radial_motion_mag
00190 print 'tangential_vec:', tangential_vec.A1
00191 eq_motion_vec = copy.copy(tangential_vec)
00192 eq_motion_vec += radial_motion_vec
00193
00194 self.prev_force_mag = mag
00195
00196 if self.init_tangent_vector == None or self.started_pulling_on_handle == False:
00197 self.init_tangent_vector = copy.copy(tangential_vec_ts)
00198 c = np.dot(tangential_vec_ts.A1, self.init_tangent_vector.A1)
00199 ang = np.arccos(c)
00200 if np.isnan(ang):
00201 ang = 0.
00202
00203 tangential_vec = tangential_vec / np.linalg.norm(tangential_vec)
00204 dist_moved = np.dot((curr_pos - start_pos).A1, tangential_vec_ts.A1)
00205 ftan = abs(np.dot(wrist_force.A1, tangential_vec.A1))
00206 self.ft.tangential_force.append(ftan)
00207 self.ft.radial_force.append(f_rad_mag)
00208
00209 if self.ft.type == 'rotary':
00210 self.ft.configuration.append(ang)
00211 else:
00212 print 'dist_moved:', dist_moved
00213 self.ft.configuration.append(dist_moved)
00214
00215 if self.started_pulling_on_handle:
00216 self.force_traj_pub.publish(self.ft)
00217
00218
00219
00220
00221
00222
00223
00224
00225
00226
00227
00228
00229
00230
00231 if abs(dist_moved) > 0.09 and self.hooked_location_moved == False:
00232
00233 self.hooked_location_moved = True
00234 self.eq_force_threshold = ut.bound(mag+30.,20.,80.)
00235 self.ftan_threshold = 1.2 * self.ftan_threshold + 20.
00236 if self.hooked_location_moved:
00237 if abs(tangential_vec_ts[2,0]) < 0.2 and ftan > self.ftan_threshold:
00238 stop = 'ftan threshold exceed: %f'%ftan
00239 else:
00240 self.ftan_threshold = max(self.ftan_threshold, ftan)
00241
00242 if self.hooked_location_moved and ang > math.radians(90.):
00243 print 'Angle:', math.degrees(ang)
00244 self.open_ang_exceed_count += 1
00245 if self.open_ang_exceed_count > 2:
00246 stop = 'opened mechanism through large angle: %.1f'%(math.degrees(ang))
00247 else:
00248 self.open_ang_exceed_count = 0
00249
00250 cep_t = cep + eq_motion_vec * step_size
00251 cep[0,0] = cep_t[0,0]
00252 cep[1,0] = cep_t[1,0]
00253 cep[2,0] = cep_t[2,0]
00254
00255 print 'CEP:', cep.A1
00256
00257 stop = stop + self.stopping_string
00258 return stop, (cep, None)
00259
00260 def pull(self, arm, force_threshold, cep_vel, mechanism_type=''):
00261 self.mechanism_type = mechanism_type
00262 self.stopping_string = ''
00263 self.eq_pt_not_moving_counter = 0
00264
00265 self.init_log()
00266
00267 self.init_tangent_vector = None
00268 self.open_ang_exceed_count = 0.
00269
00270 self.eq_force_threshold = force_threshold
00271 self.ftan_threshold = 2.
00272 self.hooked_location_moved = False
00273 self.prev_force_mag = np.linalg.norm(self.robot.get_wrist_force(arm))
00274 self.slip_count = 0
00275
00276 self.started_pulling_on_handle = False
00277 self.started_pulling_on_handle_count = 0
00278
00279 ee_pos, _ = self.robot.get_ee_jtt(arm)
00280
00281 self.cx_start = ee_pos[0,0]
00282 self.rad = 10.0
00283 self.cy_start = ee_pos[1,0]-self.rad
00284 self.cz_start = ee_pos[2,0]
00285
00286 cep, _ = self.robot.get_cep_jtt(arm)
00287 arg_list = [arm, cep, cep_vel]
00288 result, _ = self.epc_motion(self.cep_gen_control_radial_force,
00289 0.1, arm, arg_list, self.log_state,
00290
00291 control_function = self.robot.set_cep_jtt)
00292
00293 print 'EPC motion result:', result
00294 print 'Original force threshold:', force_threshold
00295 print 'Adapted force threshold:', self.eq_force_threshold
00296 print 'Adapted ftan threshold:', self.ftan_threshold
00297
00298 d = {
00299 'f_list': self.f_list, 'ee_list': self.ee_list,
00300 'cep_list': self.cep_list, 'ftan_list': self.ft.tangential_force,
00301 'config_list': self.ft.configuration, 'frad_list': self.ft.radial_force,
00302 'f_list_ati': self.f_list_ati,
00303 'f_list_estimate': self.f_list_estimate,
00304 'f_list_torques': self.f_list_torques
00305 }
00306 ut.save_pickle(d,'pr2_pull_'+ut.formatted_time()+'.pkl')
00307
00308 def search_and_hook(self, arm, hook_loc, hooking_force_threshold = 5.,
00309 hit_threshold=15., hit_motions = 1,
00310 hook_direction = 'left'):
00311
00312
00313
00314
00315
00316
00317
00318
00319
00320
00321
00322 if hook_direction == 'left':
00323 offset = np.matrix([0., -0.03, 0.]).T
00324 move_dir = np.matrix([0., 1., 0.]).T
00325 elif hook_direction == 'up':
00326 offset = np.matrix([0., 0., -0.03]).T
00327 move_dir = np.matrix([0., 0., 1.]).T
00328 start_loc = hook_loc + offset
00329
00330
00331 normal_tl = np.matrix([1.0, 0., 0.]).T
00332
00333 pt1 = start_loc - normal_tl * 0.1
00334 self.robot.go_cep_jtt(arm, pt1)
00335
00336 raw_input('Hit ENTER to go')
00337
00338 vec = normal_tl * 0.2
00339 rospy.sleep(1.)
00340 for i in range(hit_motions):
00341 s = self.move_till_hit(arm, vec=vec, force_threshold=hit_threshold, speed=0.07)
00342
00343 cep_start, _ = self.robot.get_cep_jtt(arm)
00344 cep = copy.copy(cep_start)
00345 arg_list = [arm, move_dir, hooking_force_threshold, cep, cep_start]
00346 print 'Hi there.'
00347 s = self.epc_motion(self.cep_gen_surface_follow, 0.1, arm,
00348 arg_list, control_function = self.robot.set_cep_jtt)
00349 print 'result:', s
00350 return s
00351
00352
00353 if __name__ == '__main__':
00354 import pr2_arms as pa
00355 rospy.init_node('epc_pr2', anonymous = True)
00356 rospy.logout('epc_pr2: ready')
00357
00358
00359 pr2_arms = pa.PR2Arms(primary_ft_sensor='estimate')
00360 door_epc = Door_EPC(pr2_arms)
00361
00362 r_arm, l_arm = 0, 1
00363 arm = r_arm
00364
00365 tip = np.matrix([0.35, 0., 0.]).T
00366 pr2_arms.arms.set_tooltip(arm, tip)
00367
00368 raw_input('Hit ENTER to close')
00369 pr2_arms.close_gripper(arm, effort=80)
00370 raw_input('Hit ENTER to start Door Opening')
00371
00372
00373
00374
00375 p1 = np.matrix([0.8, -0.35, 0.1]).T
00376 door_epc.search_and_hook(arm, p1, hook_direction='left')
00377 door_epc.pull(arm, force_threshold=40., cep_vel=0.05)
00378
00379
00380
00381
00382
00383
00384