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 import m3.toolbox as m3t
00033
00034 import mekabot.hrl_robot as hr
00035 import mekabot.coord_frames as mcf
00036 import util as uto
00037 import camera
00038
00039 import segway_motion_calc as smc
00040 import arm_trajectories as at
00041
00042 import roslib; roslib.load_manifest('2010_icra_epc_pull')
00043 import rospy
00044 from geometry_msgs.msg import Point32
00045
00046
00047 import hrl_hokuyo.hokuyo_scan as hs
00048 import hrl_tilting_hokuyo.tilt_hokuyo_servo as ths
00049 import hrl_lib.util as ut, hrl_lib.transforms as tr
00050 import segway_vo.segway_command as sc
00051 import vis_odometry_feat.vo_pose as vop
00052 import zenither.zenither as zenither
00053 import zenither.zenither_client as zc
00054
00055 from equilibrium_point_control.msg import MechanismKinematicsRot
00056 from equilibrium_point_control.msg import MechanismKinematicsJac
00057
00058 import sys, time, os, optparse
00059 import math, numpy as np
00060 import copy
00061
00062 from opencv.cv import *
00063 from opencv.highgui import *
00064
00065 from threading import RLock
00066 import thread
00067
00068
00069
00070
00071
00072
00073
00074
00075
00076 def rot_mat_from_angles(hook, surface):
00077 rot_mat = tr.Rz(hook) * tr.Rx(surface) * tr.Ry(math.radians(-90))
00078 return rot_mat
00079
00080
00081
00082 class CompliantMotionGenerator():
00083 ''' a specific form of compliant motion.
00084 class name might be inappropriate.
00085 '''
00086
00087
00088
00089 def __init__(self, move_segway=False, use_right_arm=True,
00090 use_left_arm=True, set_wrist_theta_gc=False, end_effector_length=0.12818):
00091
00092 self.mech_kinematics_lock = RLock()
00093 self.fit_circle_lock = RLock()
00094
00095 if use_right_arm:
00096
00097
00098
00099 settings_r = hr.MekaArmSettings(stiffness_list=[0.1939,0.6713,0.997,0.7272,0.75])
00100
00101 else:
00102 settings_r = None
00103
00104 if use_left_arm:
00105 if set_wrist_theta_gc:
00106 settings_l = hr.MekaArmSettings(stiffness_list=[0.1939,0.6713,0.748,0.7272,.8,.3,1.],
00107 control_mode = 'wrist_theta_gc')
00108 else:
00109 settings_l = hr.MekaArmSettings(stiffness_list=[0.1939,0.6713,0.748,0.7272,0.75])
00110 print 'left arm assigned'
00111
00112 else:
00113 settings_l = None
00114 print 'left arm NOT assigned'
00115
00116 self.firenze = hr.M3HrlRobot(connect = True, left_arm_settings = settings_l,
00117 right_arm_settings = settings_r, end_effector_length = end_effector_length)
00118
00119
00120 rospy.init_node('compliant_trajectory', anonymous = False)
00121 rospy.Subscriber('mechanism_kinematics_rot',
00122 MechanismKinematicsRot,
00123 self.mechanism_kinematics_rot_cb)
00124 rospy.Subscriber('mechanism_kinematics_jac',
00125 MechanismKinematicsJac,
00126 self.mechanism_kinematics_jac_cb)
00127 self.mech_traj_pub = rospy.Publisher('mechanism_trajectory', Point32)
00128
00129 self.hok = hs.Hokuyo('utm', 0, flip = True, ros_init_node = False)
00130 self.thok = ths.tilt_hokuyo('/dev/robot/servo0',5,self.hok,l1=0.,l2=-0.055)
00131
00132 self.cam = camera.Camera('mekabotUTM')
00133 self.set_camera_settings()
00134
00135 self.z = zenither.Zenither(robot='HRL2', pose_read_thread=True)
00136 self.zenither_client = zc.ZenitherClient()
00137 self.zenither_list = []
00138 self.zenither_moving = False
00139
00140 self.move_segway_flag = move_segway
00141 self.segway_trajectory = at.PlanarTajectory()
00142 self.move_segway_lock = RLock()
00143 self.segway_motion_tup = (0.0,0.0,0.0)
00144 self.new_segway_command = False
00145
00146 self.dist_boundary = 0.05
00147 self.eq_pt_close_to_bndry = False
00148
00149 self.workspace_dict = ut.load_pickle(os.environ['HRLBASEPATH']+'/src/projects/equilibrium_point_control/pkls/workspace_dict_2010Feb20_225427.pkl')
00150
00151 if move_segway:
00152 self.segway_command_node = sc.SegwayCommand(vel_topic='/hrl/segway/command',
00153 pose_local_topic='/hrl/segway/pose_local',
00154 pose_global_topic='/hrl/segway/pose_global',
00155 stop_topic='/hrl/segway/stop',
00156 max_vel_topic='/hrl/segway/max_vel',
00157 ros_init_node=False)
00158
00159 self.segway_pose = vop.vo_pose('pose',ros_init_node=False)
00160
00161 self.eq_pt_not_moving_counter = 0
00162
00163 def movement_posture(self):
00164 q = [math.radians(-45), 0, 0, math.radians(125.), 0, 0, 0]
00165 self.firenze.go_jointangles('right_arm',q)
00166
00167
00168 def stop(self):
00169 self.run_fit_circle_thread = False
00170 self.run_move_segway_thread = False
00171 self.z.estop()
00172 self.z.broadcaster.stop()
00173 self.firenze.stop()
00174
00175
00176
00177
00178
00179
00180
00181
00182
00183 def reposition_robot(self,hook_location,turn_angle,hook_angle,position_number=2):
00184 h = self.workspace_dict[hook_angle]['height']
00185 max_z_height = 1.3
00186 min_z_height = 0.5
00187 h_desired = self.z.get_position_meters()+hook_location[2,0]-h
00188 print 'h_desired:',h_desired
00189 print 'h:',h
00190 h_achieve = ut.bound(h_desired,max_z_height,min_z_height)
00191 h_err = h_desired-h_achieve
00192 h = h+h_err
00193 print 'h_achieve:',h_achieve
00194
00195 wkd = self.workspace_dict[hook_angle]['pts']
00196 k = wkd.keys()
00197 k_idx = np.argmin(np.abs(np.array(k)-h))
00198 wrkspc_pts = wkd[k[k_idx]]
00199
00200
00201 good_location = wrkspc_pts.mean(1)
00202 good_location = np.matrix(good_location.A1.tolist()+[h]).T
00203
00204 if position_number == 1:
00205 good_location[0,0] += 0.0
00206 good_location[1,0] -= 0.1
00207 elif position_number == 2:
00208 good_location[0,0] += 0.0
00209 good_location[1,0] -= 0.0
00210 elif position_number == 3:
00211 good_location[0,0] += 0.0
00212 good_location[1,0] += 0.1
00213 else:
00214 good_location[0,0] -= 0.1
00215 good_location[1,0] -= 0.0
00216
00217 good_location = mcf.mecanumTglobal(mcf.globalTtorso(good_location))
00218 hook_location = mcf.mecanumTglobal(mcf.globalTtorso(hook_location))
00219
00220 v = tr.Rz(-turn_angle)*good_location
00221 move_vector = hook_location - v
00222
00223 pose1 = self.segway_pose.get_pose()
00224 self.segway_command_node.go_xya_pos_local(move_vector[0,0],move_vector[1,0],
00225 turn_angle,blocking=False)
00226
00227 self.z.torque_move_position(h_achieve)
00228 print 'before waiting for segway to stop moving.'
00229 self.segway_command_node.wait_for_tolerance_pos(0.03,0.03,math.radians(4))
00230 print 'after segway has stopped moving.'
00231
00232 pose2 = self.segway_pose.get_pose()
00233 hl_new = vop.transform_pts_local(hook_location[0:2,:],pose1,pose2)
00234 h_err = h_desired-self.z.get_position_meters()
00235
00236 g = np.matrix(hl_new.A1.tolist()+[good_location[2,0]+h_err]).T
00237 g = mcf.torsoTglobal(mcf.globalTmecanum(g))
00238 angle_turned = pose2[2]-pose1[2]
00239 angle_error = tr.angle_within_mod180(turn_angle-angle_turned)
00240 self.segway_pose.set_origin()
00241 return g, angle_error
00242
00243 def set_camera_settings(self):
00244 self.cam.set_frame_rate(30)
00245 self.cam.set_auto()
00246 self.cam.set_gamma(1)
00247 self.cam.set_whitebalance(r_val=512,b_val=544)
00248
00249
00250
00251
00252
00253
00254
00255
00256 def compliant_motion(self, equi_pt_generator, time_step, arm, arg_list, record=False,
00257 rapid_call_func=None):
00258
00259
00260
00261 stop, q = equi_pt_generator(*arg_list)
00262
00263
00264 threshold = 100.
00265 ratio_j4 = 50.
00266 ratio_j5 = 100.
00267
00268 t_end = time.time()
00269 while stop == '':
00270
00271
00272
00273
00274
00275
00276
00277
00278
00279
00280
00281 t_end += time_step
00282 self.firenze.set_joint_angles(arm, q)
00283 self.firenze.step()
00284 t1 = time.time()
00285
00286 if record:
00287 f = self.firenze.get_wrist_force(arm)
00288 t = self.firenze.get_wrist_torque(arm,base_frame=True)
00289 p = self.firenze.FK(arm, q)
00290 print >> self.file, t1,f[0,0],f[1,0],f[2,0],t[0,0],t[1,0],t[2,0],p[0,0],p[1,0],p[2,0],q[0],q[1],q[2],q[3],q[4],q[5],q[6]
00291
00292 if stop != '':
00293 break
00294
00295 while t1<t_end:
00296 if rapid_call_func != None:
00297 stop = rapid_call_func(arm)
00298 if stop != '':
00299 break
00300 self.firenze.step()
00301 t1 = time.time()
00302
00303
00304
00305
00306
00307 stop,q = equi_pt_generator(*arg_list)
00308
00309 if stop == 'reset timing':
00310 stop = ''
00311 t_end = time.time()
00312
00313 return stop, q
00314
00315
00316 def log_state(self, arm):
00317 t_now = time.time()
00318 q_now = self.firenze.get_joint_angles(arm)
00319 qdot_now = self.firenze.get_joint_velocities(arm)
00320 qdotdot_now = self.firenze.get_joint_accelerations(arm)
00321
00322 tau_now = self.firenze.get_joint_torques(arm)
00323 self.jt_torque_trajectory.q_list.append(tau_now)
00324 self.jt_torque_trajectory.time_list.append(t_now)
00325
00326 self.pull_trajectory.q_list.append(q_now)
00327 self.pull_trajectory.qdot_list.append(qdot_now)
00328 self.pull_trajectory.qdotdot_list.append(qdotdot_now)
00329 self.pull_trajectory.time_list.append(t_now)
00330
00331 self.eq_pt_trajectory.q_list.append(self.q_guess)
00332 self.eq_pt_trajectory.time_list.append(t_now)
00333
00334 wrist_force = self.firenze.get_wrist_force(arm, base_frame=True)
00335 self.force_trajectory.f_list.append(wrist_force.A1.tolist())
00336 self.force_trajectory.time_list.append(t_now)
00337
00338 wrist_torque = self.firenze.get_wrist_torque(arm)
00339 self.torque_trajectory.f_list.append(wrist_torque.A1.tolist())
00340 self.torque_trajectory.time_list.append(t_now)
00341
00342 if self.move_segway_flag:
00343 x,y,a = self.segway_pose.get_pose()
00344 else:
00345 x,y,a = 0.,0.,0.
00346
00347 self.segway_trajectory.time_list.append(t_now)
00348 self.segway_trajectory.x_list.append(x)
00349 self.segway_trajectory.y_list.append(y)
00350 self.segway_trajectory.a_list.append(a)
00351
00352 self.zenither_list.append(self.zenither_client.height())
00353
00354 return ''
00355
00356 def common_stopping_conditions(self):
00357 stop = ''
00358 if self.q_guess == None:
00359 stop = 'IK fail'
00360
00361 wrist_force = self.firenze.get_wrist_force('right_arm',base_frame=True)
00362 mag = np.linalg.norm(wrist_force)
00363 print 'force magnitude:', mag
00364 if mag > self.eq_force_threshold:
00365 stop = 'force exceed'
00366
00367 if mag < 1.2 and self.hooked_location_moved:
00368 if (self.prev_force_mag - mag) > 30.:
00369 stop = 'slip: force step decrease and below thresold.'
00370
00371 else:
00372 self.slip_count += 1
00373 else:
00374 self.slip_count = 0
00375
00376 if self.slip_count == 10:
00377 stop = 'slip: force below threshold for too long.'
00378 print stop
00379
00380
00381 curr_pos = self.firenze.FK('right_arm',self.pull_trajectory.q_list[-1])
00382 if curr_pos[0,0] < 0.29 and curr_pos[1,0] > -0.2 and \
00383 curr_pos[2,0] > -0.28:
00384 print 'curr_pos:', curr_pos.A1.tolist()
00385 stop = 'danger of self collision'
00386
00387 if self.firenze.is_motor_power_on() == False:
00388 stop = 'estop pressed'
00389
00390 if self.eq_pt_not_moving_counter > 20:
00391 stop = 'unable to move equilibrium point away from bndry'
00392
00393 return stop
00394
00395
00396
00397
00398
00399
00400
00401 def update_eq_point(self, arm, motion_vec, step_size, rot_mat):
00402 x,y,a,dx,dy,da = 0.,0.,0.,0.,0.,0.
00403 st = self.segway_trajectory
00404 if len(st.x_list)>0:
00405 x,y,a = st.x_list[-1],st.y_list[-1],st.a_list[-1]
00406 if len(st.x_list)>1:
00407 dx = x-st.x_list[-2]
00408 dy = y-st.y_list[-2]
00409 da = tr.angle_within_mod180(x-st.a_list[-2])
00410
00411 self.eq_pt_cartesian = smc.tlTts(self.eq_pt_cartesian_ts,x,y,a)
00412 if len(self.zenither_list) > 2:
00413 h = self.zenither_list[-1] - self.zenither_list[-2]
00414 self.eq_pt_cartesian[2,0] -= h
00415
00416 next_pt = self.eq_pt_cartesian + step_size * motion_vec
00417
00418 if self.q_guess != None:
00419 if arm == 'right_arm':
00420 self.q_guess[1] = ut.bound(self.q_guess[1],math.radians(20),math.radians(5))
00421
00422 q_eq = self.firenze.IK(arm,next_pt,rot_mat,self.q_guess)
00423 self.eq_pt_cartesian = next_pt
00424 self.eq_pt_cartesian_ts = smc.tsTtl(self.eq_pt_cartesian,x,y,a)
00425 self.q_guess = q_eq
00426 return q_eq
00427
00428 def segway_mover(self):
00429 self.run_move_segway_thread = True
00430 print 'Starting the segway moving thread.'
00431
00432 send_command = False
00433 while self.run_move_segway_thread:
00434 self.move_segway_lock.acquire()
00435 if self.new_segway_command == True:
00436 send_command = True
00437 self.new_segway_command = False
00438 t = self.segway_motion_tup
00439 self.move_segway_lock.release()
00440
00441 if send_command:
00442 send_command = False
00443 if t == (0.,0.,0.):
00444 self.segway_command_node.stop()
00445 else:
00446
00447 self.segway_command_node.set_velocity(t[0],t[1],t[2])
00448 time.sleep(0.05)
00449 time.sleep(0.005)
00450
00451 self.segway_command_node.stop()
00452 time.sleep(0.1)
00453 print 'Ended the segway moving thread.'
00454
00455 def mechanism_kinematics_rot_cb(self, mk):
00456 self.fit_circle_lock.acquire()
00457 self.cx_start = mk.cx
00458 self.cy_start = mk.cy
00459 self.cz_start = mk.cz
00460 self.rad = mk.rad
00461 self.fit_circle_lock.release()
00462
00463
00464 def segway_motion_local(self, curr_pos_tl, sa):
00465 k = self.wkd['pts'].keys()
00466 z = min(self.eq_pt_cartesian[2,0], curr_pos_tl[2,0])
00467 k_idx = np.argmin(np.abs(np.array(k)-z))
00468 wrkspc_pts = self.wkd['pts'][k[k_idx]]
00469 bndry = self.wkd['bndry'][k[k_idx]]
00470
00471 self.eq_pt_close_to_bndry = False
00472 if z < -0.4:
00473
00474 self.eq_motion_vec = np.matrix([0.,0.,0.]).T
00475 self.eq_pt_close_to_bndry = True
00476
00477 if self.zenither_client.height() > 0.6:
00478 if z < -0.35 and self.zenither_moving == False:
00479
00480 self.z.nadir(0)
00481 self.zenither_moving = True
00482 if z > -0.25 and self.zenither_moving == True:
00483 self.z.estop()
00484 self.zenither_moving = False
00485 else:
00486 if self.zenither_moving:
00487 self.z.estop()
00488 self.zenither_moving = False
00489
00490 ht = smc.segway_motion_repulse(curr_pos_tl, self.eq_pt_cartesian, bndry,
00491 wrkspc_pts)
00492
00493 self.vec_bndry = smc.vec_from_boundary(self.eq_pt_cartesian, bndry)
00494 self.dist_boundary = smc.dist_from_boundary(self.eq_pt_cartesian, bndry,
00495 wrkspc_pts)
00496 dist_bndry_ee = smc.dist_from_boundary(curr_pos_tl,bndry,wrkspc_pts)
00497 self.vec_bndry = self.vec_bndry/self.dist_boundary
00498 vec_bndry = self.vec_bndry
00499 dist_boundary = self.dist_boundary
00500
00501 avel = -sa * 0.05
00502
00503 eq_mec = mcf.mecanumTglobal(mcf.globalTtorso(self.eq_pt_cartesian))
00504 svel_rot_y = -avel*eq_mec[0,0]
00505 svel_rot_x = avel*eq_mec[1,0]
00506
00507 if self.zenither_moving:
00508 sp = 0.075
00509 else:
00510 sp = 0.075
00511 st = ht*sp + np.matrix([svel_rot_x,svel_rot_y]).T
00512 st[0,0] = min(st[0,0],0.)
00513
00514 self.move_segway_lock.acquire()
00515 self.segway_motion_tup = (st[0,0],st[1,0],avel)
00516 self.new_segway_command = True
00517 self.move_segway_lock.release()
00518
00519 proj = (self.eq_motion_vec[0:2,0].T*vec_bndry)[0,0]
00520 proj_threshold = math.cos(math.radians(100))
00521 if (dist_boundary<= 0.04 and proj<proj_threshold) or \
00522 dist_boundary<0.03:
00523
00524 self.eq_motion_vec = np.matrix([0.,0.,0.]).T
00525 self.eq_pt_close_to_bndry = True
00526
00527 if self.eq_pt_close_to_bndry:
00528 if not self.zenither_moving:
00529 self.eq_pt_not_moving_counter += 1
00530 else:
00531 self.eq_pt_not_moving_counter = 0
00532 else:
00533 self.eq_pt_not_moving_counter = 0
00534
00535
00536 print '-------------------------------------'
00537 print 'segway_translation:',st[0,0],st[1,0]
00538 print 'avel:',math.degrees(avel)
00539 print 'dist_boundary:', dist_boundary
00540 print 'proj,proj_threshold:',proj,proj_threshold
00541 print 'self.eq_pt_cartesian:',self.eq_pt_cartesian.A1.tolist()
00542 print 'self.eq_pt_close_to_bndry?',self.eq_pt_close_to_bndry
00543 print 'dist_bndry_ee:',dist_bndry_ee
00544
00545
00546
00547
00548
00549
00550
00551
00552
00553 def equi_pt_generator_control_radial_force(self, arm, rot_mat,
00554 h_force_possible, v_force_possible, cep_vel):
00555 self.log_state(arm)
00556 step_size = 0.1 * cep_vel
00557 q_eq = self.update_eq_point(arm, self.eq_motion_vec, step_size,
00558 rot_mat)
00559
00560 stop = self.common_stopping_conditions()
00561
00562 wrist_force = self.firenze.get_wrist_force(arm, base_frame=True)
00563 mag = np.linalg.norm(wrist_force)
00564
00565 curr_pos_tl = self.firenze.FK(arm,self.pull_trajectory.q_list[-1])
00566 st = self.segway_trajectory
00567 x,y,a = st.x_list[-1],st.y_list[-1],st.a_list[-1]
00568 curr_pos_ts = smc.tsTtl(curr_pos_tl,x,y,a)
00569 curr_pos = curr_pos_ts
00570 if len(self.zenither_list) > 1:
00571 h = self.zenither_list[-1] - self.zenither_list[0]
00572 curr_pos[2,0] += h
00573
00574 if len(self.pull_trajectory.q_list)>1:
00575 start_pos = np.matrix(self.cartesian_pts_list[0]).T
00576 else:
00577 start_pos = curr_pos
00578
00579
00580 self.mech_traj_pub.publish(Point32(curr_pos[0,0],
00581 curr_pos[1,0], curr_pos[2,0]))
00582
00583 if self.use_jacobian:
00584 self.mech_kinematics_lock.acquire()
00585
00586 self.cartesian_pts_list.append(curr_pos.A1.tolist())
00587 tangential_vec_ts = self.tangential_vec_ts
00588 force_vec_ts = self.constraint_vec_1_ts + self.constraint_vec_2_ts
00589
00590
00591
00592 if h_force_possible:
00593 force_vec_ts[2,0] = 0.
00594 if v_force_possible:
00595 force_vec_ts[1,0] = 0.
00596 force_vec_ts = force_vec_ts / np.linalg.norm(force_vec_ts)
00597 if force_vec_ts[2,0] < 0.:
00598 force_vec_ts = -force_vec_ts
00599 if force_vec_ts[1,0] < 0.:
00600 force_vec_ts = -force_vec_ts
00601
00602 self.mech_kinematics_lock.release()
00603
00604 force_vec = smc.tlRts(force_vec_ts, a)
00605 tangential_vec = smc.tlRts(tangential_vec_ts, a)
00606 print 'tangential vec right at the transformation:', tangential_vec.A1
00607 print 'tangential vec ts right at the transformation:', tangential_vec_ts.A1
00608 print 'a:', a
00609
00610 if self.use_rotation_center:
00611 self.fit_circle_lock.acquire()
00612 self.cartesian_pts_list.append(curr_pos.A1.tolist())
00613 rad = self.rad
00614 cx_start, cy_start = self.cx_start, self.cy_start
00615 cz_start = self.cz_start
00616 self.fit_circle_lock.release()
00617 c_ts = np.matrix([cx_start,cy_start,0.]).T
00618 c_tl = smc.tlTts(c_ts,x,y,a)
00619 cx,cy = c_tl[0,0],c_tl[1,0]
00620 cz = cz_start
00621
00622 z_start = start_pos[2,0]
00623 parallel_to_floor = abs(z_start - cz) < 0.1
00624 print 'abs(z_start - cz)', abs(z_start - cz)
00625 if parallel_to_floor:
00626 print 'Mechanism is in the XY plane.'
00627
00628
00629 radial_vec_tl = curr_pos_tl-np.matrix([cx,cy,cz]).T
00630 radial_vec = radial_vec_tl
00631 radial_vec = radial_vec/np.linalg.norm(radial_vec)
00632 if cy_start<start_pos[1,0]:
00633
00634 tan_x,tan_y = -radial_vec[1,0],radial_vec[0,0]
00635 else:
00636 tan_x,tan_y = radial_vec[1,0],-radial_vec[0,0]
00637
00638 if tan_x > 0. and (start_pos[0,0]-curr_pos[0,0]) < 0.09:
00639 tan_x = -tan_x
00640 tan_y = -tan_y
00641
00642 if cy_start>start_pos[1,0]:
00643 radial_vec = -radial_vec
00644
00645 rv = radial_vec
00646 force_vec = np.matrix([rv[0,0], rv[1,0], 0.]).T
00647 tangential_vec = np.matrix([tan_x, tan_y, 0.]).T
00648 else:
00649 print 'Mechanism is in the XZ plane.'
00650
00651
00652 radial_vec_tl = curr_pos_tl-np.matrix([cx,cy,cz]).T
00653 radial_vec = radial_vec_tl
00654 radial_vec = radial_vec/np.linalg.norm(radial_vec)
00655 tan_x, tan_z = -radial_vec[2,0], radial_vec[0,0]
00656
00657 if tan_x > 0. and (start_pos[0,0]-curr_pos[0,0]) < 0.09:
00658 tan_x = -tan_x
00659 tan_z = -tan_z
00660
00661 rv = radial_vec
00662 force_vec = np.matrix([rv[0,0], 0., rv[2,0]]).T
00663 tangential_vec = np.matrix([tan_x, 0., tan_z]).T
00664
00665 if abs(curr_pos[2,0] - z_start) > 0.03 and parallel_to_floor:
00666 force_vec += np.matrix([0.,0.,1]).T
00667 parallel_to_floor = False
00668
00669 tangential_vec_ts = smc.tsRtl(tangential_vec, a)
00670 radial_vec_ts = smc.tsRtl(radial_vec, a)
00671 force_vec_ts = smc.tsRtl(force_vec, a)
00672
00673 f_vec = -1*np.array([wrist_force[0,0], wrist_force[1,0],
00674 wrist_force[2,0]])
00675 f_rad_mag = np.dot(f_vec, force_vec.A1)
00676 err = f_rad_mag-5.
00677 if err>0.:
00678 kp = -0.1
00679 else:
00680 kp = -0.2
00681 radial_motion_mag = kp * err
00682
00683 if self.use_rotation_center:
00684 if h_force_possible == False and parallel_to_floor:
00685 radial_motion_mag = 0.
00686 if v_force_possible == False and parallel_to_floor == False:
00687 radial_motion_mag = 0.
00688
00689 radial_motion_vec = force_vec * radial_motion_mag
00690 self.eq_motion_vec = copy.copy(tangential_vec)
00691 self.eq_motion_vec += radial_motion_vec
00692
00693 if self.move_segway_flag:
00694 self.segway_motion_local(curr_pos_tl, a)
00695
00696 self.prev_force_mag = mag
00697
00698 if self.init_tangent_vector == None:
00699 self.init_tangent_vector = copy.copy(tangential_vec_ts)
00700 c = np.dot(tangential_vec_ts.A1, self.init_tangent_vector.A1)
00701 ang = np.arccos(c)
00702
00703 dist_moved = np.dot((curr_pos - start_pos).A1, self.tangential_vec_ts.A1)
00704 ftan = abs(np.dot(wrist_force.A1, tangential_vec.A1))
00705
00706
00707
00708
00709
00710 if abs(dist_moved) > 0.09 and self.hooked_location_moved == False:
00711
00712 self.hooked_location_moved = True
00713 self.eq_force_threshold = ut.bound(mag+30.,20.,80.)
00714 self.ftan_threshold = self.ftan_threshold + max(10., 1.5*ftan)
00715 if self.hooked_location_moved:
00716 if abs(tangential_vec_ts[2,0]) < 0.2 and ftan > self.ftan_threshold:
00717
00718 stop = 'ftan threshold exceed: %f'%ftan
00719 else:
00720 self.ftan_threshold = max(self.ftan_threshold, ftan)
00721
00722
00723 if self.hooked_location_moved and ang > math.radians(90.):
00724 print 'Angle:', math.degrees(ang)
00725 self.open_ang_exceed_count += 1
00726 if self.open_ang_exceed_count > 2:
00727 stop = 'opened mechanism through large angle: %.1f'%(math.degrees(ang))
00728 else:
00729 self.open_ang_exceed_count = 0
00730
00731 self.move_segway_lock.acquire()
00732 if stop != '' and stop != 'reset timing':
00733 self.segway_motion_tup = (0.0,0.0,0.0)
00734 self.new_segway_command = True
00735 self.move_segway_lock.release()
00736
00737 self.mech_time_list.append(time.time())
00738 self.mech_x_list.append(ang)
00739 self.f_rad_list.append(f_rad_mag)
00740 self.f_tan_list.append(np.dot(f_vec, tangential_vec.A1))
00741 self.tan_vec_list.append(tangential_vec_ts.A1.tolist())
00742 self.rad_vec_list.append(force_vec_ts.A1.tolist())
00743
00744 return stop, q_eq
00745
00746
00747
00748
00749
00750
00751
00752
00753 def search_and_hook(self, arm, hook_angle, hook_loc, angle,
00754 hooking_force_threshold = 5.):
00755
00756 rot_mat = rot_mat_from_angles(hook_angle, angle)
00757
00758 if arm == 'right_arm':
00759 hook_dir = np.matrix([0.,1.,0.]).T
00760 elif arm == 'left_arm':
00761 hook_dir = np.matrix([0.,-1.,0.]).T
00762 else:
00763 raise RuntimeError('Unknown arm: %s', arm)
00764 start_loc = hook_loc + rot_mat.T * hook_dir * -0.03
00765
00766
00767 normal_tl = tr.Rz(-angle) * np.matrix([1.0,0.,0.]).T
00768
00769 pt1 = start_loc - normal_tl * 0.1
00770 pt1[2,0] -= 0.02
00771 self.firenze.go_cartesian(arm, pt1, rot_mat, speed=0.2)
00772
00773 vec = normal_tl * 0.2
00774 s, jep = self.firenze.move_till_hit(arm, vec=vec, force_threshold=2.0,
00775 rot=rot_mat, speed=0.07)
00776
00777 self.eq_pt_cartesian = self.firenze.FK(arm, jep)
00778 self.eq_pt_cartesian_ts = self.firenze.FK(arm, jep)
00779 self.start_pos = copy.copy(self.eq_pt_cartesian)
00780 self.q_guess = jep
00781 move_dir = rot_mat.T * hook_dir
00782
00783 arg_list = [arm, move_dir, rot_mat, hooking_force_threshold]
00784 s, jep = self.compliant_motion(self.equi_generator_surface_follow, 0.05,
00785 arm, arg_list)
00786 return s, jep
00787
00788
00789
00790
00791
00792
00793
00794
00795
00796
00797 def equi_generator_surface_follow(self, arm, move_dir, rot_mat,
00798 force_threshold):
00799 wrist_force = self.firenze.get_wrist_force(arm, base_frame=True)
00800 if wrist_force[0,0] < -3.:
00801 self.eq_pt_cartesian_ts[0,0] -= 0.002
00802 if wrist_force[0,0] > -1.:
00803 self.eq_pt_cartesian_ts[0,0] += 0.003
00804
00805 if self.eq_pt_cartesian_ts[0,0] > (self.start_pos[0,0]+0.05):
00806 self.eq_pt_cartesian_ts[0,0] = self.start_pos[0,0]+0.05
00807
00808 q_eq = self.update_eq_point(arm, move_dir, 0.002, rot_mat)
00809
00810 v = self.eq_pt_cartesian-self.start_pos
00811 if (wrist_force.T * move_dir)[0,0] < -force_threshold:
00812 stop = 'got a hook'
00813 elif np.linalg.norm(wrist_force) > 30.:
00814 stop = 'force is large %f'%(np.linalg.norm(wrist_force))
00815 elif (v.T * move_dir)[0,0] > 0.20:
00816 stop = 'moved a lot without a hook'
00817 else:
00818 stop = ''
00819 return stop, q_eq
00820
00821
00822
00823
00824
00825
00826
00827
00828
00829
00830
00831
00832
00833
00834
00835
00836 def pull(self, arm, hook_angle, surface_angle, force_threshold, jep, use_utm=False,
00837 use_camera=False, strategy='line_neg_x', info_string='',
00838 cep_vel = 0.1, kinematics_estimation='rotation_center',
00839 pull_left = False):
00840
00841 self.init_tangent_vector = None
00842 self.open_ang_exceed_count = 0.
00843 if kinematics_estimation == 'rotation_center':
00844 self.use_rotation_center = True
00845 else:
00846 self.use_rotation_center = False
00847
00848 if kinematics_estimation == 'jacobian':
00849 self.use_jacobian = True
00850 else:
00851 self.use_jacobian = False
00852
00853 if use_utm:
00854 self.firenze.step()
00855 armconfig1 = self.firenze.get_joint_angles('right_arm')
00856 plist1,slist1 = self.scan_3d()
00857
00858 if use_camera:
00859 cam_plist1, cam_imlist1 = self.image_region()
00860 else:
00861 cam_plist1,cam_imlist1 = None,None
00862
00863
00864 rot_mat = rot_mat_from_angles(hook_angle, surface_angle)
00865
00866 if self.move_segway_flag:
00867 self.segway_pose.set_origin()
00868 self.segway_command_node.set_max_velocity(0.15,0.1,math.radians(15))
00869
00870 time_dict = {}
00871 time_dict['before_pull'] = time.time()
00872
00873 stiffness_scale = self.firenze.arm_settings[arm].stiffness_scale
00874
00875 self.pull_trajectory = at.JointTrajectory()
00876 self.jt_torque_trajectory = at.JointTrajectory()
00877 self.eq_pt_trajectory = at.JointTrajectory()
00878 self.force_trajectory = at.ForceTrajectory()
00879 self.torque_trajectory = at.ForceTrajectory()
00880
00881 self.firenze.step()
00882 start_config = self.firenze.get_joint_angles(arm)
00883
00884 self.eq_force_threshold = force_threshold
00885 self.ftan_threshold = 2.
00886 self.hooked_location_moved = False
00887 self.prev_force_mag = np.linalg.norm(self.firenze.get_wrist_force(arm))
00888 self.eq_motion_vec = np.matrix([-1.,0.,0.]).T
00889 self.slip_count = 0
00890
00891 self.eq_pt_cartesian = self.firenze.FK(arm, jep)
00892 self.eq_pt_cartesian_ts = self.firenze.FK(arm, jep)
00893 self.start_pos = copy.copy(self.eq_pt_cartesian)
00894 self.q_guess = jep
00895
00896 if strategy == 'control_radial_force':
00897 if not pull_left:
00898 self.tangential_vec_ts = np.matrix([-1.,0.,0.]).T
00899 self.constraint_vec_2_ts = np.matrix([0.,0.,1.]).T
00900 self.constraint_vec_1_ts = np.matrix([0.,1.,0.]).T
00901 else:
00902 self.tangential_vec_ts = np.matrix([0.,1.,0.]).T
00903 self.constraint_vec_2_ts = np.matrix([0.,0.,1.]).T
00904 self.constraint_vec_1_ts = np.matrix([1.,0.,0.]).T
00905
00906 self.mech_time_list = []
00907 self.mech_x_list = []
00908 self.f_rad_list = []
00909 self.f_tan_list = []
00910 self.tan_vec_list = []
00911 self.rad_vec_list = []
00912
00913 self.cartesian_pts_list = []
00914 ee_pos = self.firenze.end_effector_pos(arm)
00915
00916 if self.use_rotation_center:
00917
00918
00919
00920 self.cx_start = ee_pos[0,0]
00921 self.cy_start = ee_pos[1,0]-1.0
00922 self.cz_start = ee_pos[2,0]
00923 self.rad = 5.0
00924
00925 z = ee_pos[2,0]
00926 print 'ee_pos[2,0]:',z
00927 self.wkd = self.workspace_dict[hook_angle]
00928 k = self.wkd['pts'].keys()
00929 k_idx = np.argmin(np.abs(np.array(k)-z))
00930 self.wrkspc_pts = self.wkd['pts'][k[k_idx]]
00931 self.bndry = self.wkd['bndry'][k[k_idx]]
00932
00933
00934
00935
00936 if self.move_segway_flag:
00937 thread.start_new_thread(self.segway_mover,())
00938 self.segway_command_node.set_max_velocity(0.1,0.1,math.radians(2.5))
00939
00940 h_force_possible = abs(hook_angle) < math.radians(30.)
00941 v_force_possible = abs(hook_angle) > math.radians(60.)
00942 arg_list = [arm, rot_mat, h_force_possible, v_force_possible, cep_vel]
00943 result, jep = self.compliant_motion(self.equi_pt_generator_control_radial_force,
00944 0.1, arm, arg_list, self.log_state)
00945 if self.move_segway_flag:
00946 self.segway_command_node.stop()
00947 self.z.estop()
00948 else:
00949 raise RuntimeError('unknown pull strategy: ', strategy)
00950
00951 if result == 'slip: force step decrease' or result == 'danger of self collision':
00952 self.firenze.motors_off()
00953 print 'powered off the motors.'
00954
00955 print 'Compliant motion result:', result
00956 print 'Original force threshold:', force_threshold
00957 print 'Adapted force threshold:', self.eq_force_threshold
00958 print 'Adapted ftan threshold:', self.ftan_threshold
00959
00960 time_dict['after_pull'] = time.time()
00961
00962 d = {'actual': self.pull_trajectory, 'eq_pt': self.eq_pt_trajectory,
00963 'force': self.force_trajectory, 'torque': self.jt_torque_trajectory,
00964 'torque_ft': self.torque_trajectory,
00965 'stiffness': self.firenze.arm_settings[arm],
00966 'info': info_string, 'force_threshold': force_threshold,
00967 'eq_force_threshold': self.eq_force_threshold, 'hook_angle':hook_angle,
00968 'result':result, 'strategy':strategy, 'time_dict':time_dict,
00969 'segway':self.segway_trajectory, 'wrkspc':self.wrkspc_pts,
00970 'bndry':self.bndry, 'cep_vel': cep_vel,
00971 'zenither_list': self.zenither_list, 'ftan_threshold': self.ftan_threshold}
00972
00973 self.firenze.step()
00974 if use_utm:
00975 armconfig2 = self.firenze.get_joint_angles(arm)
00976 plist2,slist2 = self.scan_3d()
00977 d['start_config'] = start_config
00978 d['armconfig1'] = armconfig1
00979 d['armconfig2'] = armconfig2
00980 d['l1'],d['l2'] = 0., -0.055
00981 d['scanlist1'], d['poslist1'] = slist1, plist1
00982 d['scanlist2'], d['poslist2'] = slist2, plist2
00983
00984 d['cam_plist1'] = cam_plist1
00985 d['cam_imlist1'] = cam_imlist1
00986
00987 ut.save_pickle(d,'pull_trajectories_'+d['info']+'_'+ut.formatted_time()+'.pkl')
00988
00989 dd = {'mechanism_x': self.mech_x_list,
00990 'mechanism_time': self.mech_time_list,
00991 'force_rad_list': self.f_rad_list,
00992 'force_tan_list': self.f_tan_list,
00993 'tan_vec_list': self.tan_vec_list,
00994 'rad_vec_list': self.rad_vec_list
00995 }
00996 ut.save_pickle(dd,'mechanism_trajectories_robot_'+d['info']+'_'+ut.formatted_time()+'.pkl')
00997
00998 def scan_3d(self):
00999 tilt_angles = (math.radians(20),math.radians(70))
01000 pos_list,scan_list = self.thok.scan(tilt_angles,speed=math.radians(10),save_scan=False)
01001 return pos_list,scan_list
01002
01003 def save_frame(self):
01004 cvim = self.cam.get_frame()
01005 cvSaveImage('im_'+ut.formatted_time()+'.png',cvim)
01006
01007 def image_region(self):
01008 ''' takes images from the UTM camera at different angles.
01009 returns list of servo angles, list of images.
01010 images are numpy images. so that they can be pickled.
01011 '''
01012 im_list = []
01013 p_list = []
01014
01015 for cmd_ang in [0,30,45]:
01016 self.thok.servo.move_angle(math.radians(cmd_ang))
01017 cvim = self.cam.get_frame()
01018 cvim = self.cam.get_frame()
01019 im_list.append(uto.cv2np(cvim,format='BGR'))
01020 p_list.append(self.thok.servo.read_angle())
01021
01022 self.thok.servo.move_angle(math.radians(0))
01023 return p_list,im_list
01024
01025 def test_IK(arm, rot_mat):
01026 ''' try out the IK at a number of different cartesian
01027 points in the workspace, with the given rotation
01028 matrix for the end effector.
01029 '''
01030 print 'press ENTER to start.'
01031 k=m3t.get_keystroke()
01032 while k=='\r':
01033 p = firenze.end_effector_pos(arm)
01034 firenze.go_cartesian(arm,p,rot_mat,speed=0.1)
01035 firenze.step()
01036 print 'press ENTER to save joint angles.'
01037 k=m3t.get_keystroke()
01038 if k == '\r':
01039 firenze.step()
01040 q = firenze.get_joint_angles(arm)
01041 ut.save_pickle(q,'arm_config_'+ut.formatted_time()+'.pkl')
01042 print 'press ENTER for next IK test. something else to exit.'
01043 k=m3t.get_keystroke()
01044
01045 def test_elbow_angle():
01046 firenze = hr.M3HrlRobot(connect=False)
01047 rot_mat = tr.Rz(math.radians(-90.))*tr.Ry(math.radians(-90))
01048
01049 x_list = [0.55,0.45,0.35]
01050 y = -0.2
01051 z = -0.23
01052 for x in x_list:
01053 p0 = np.matrix([x,y,z]).T
01054 q = firenze.IK('right_arm',p0,rot_mat)
01055
01056
01057 elbow_angle = firenze.elbow_plane_angle('right_arm',q)
01058 print '---------------------------------------'
01059 print 'ee position:', p0.A1
01060
01061 print 'elbow_angle:', math.degrees(elbow_angle)
01062
01063
01064 if __name__=='__main__':
01065 p = optparse.OptionParser()
01066 p.add_option('--ik_single_pos', action='store_true', dest='ik_single_pos',
01067 help='test IK at a single position.')
01068 p.add_option('--ik_test', action='store_true', dest='ik_test',
01069 help='test IK in a loop.')
01070 p.add_option('--la', action='store_true', dest='la',
01071 help='use the left arm.')
01072 p.add_option('--pull', action='store_true', dest='pull',
01073 help='pull.')
01074 p.add_option('--search_hook', action='store_true', dest='search_hook',
01075 help='search for a good hooking grasp.')
01076 p.add_option('--scan', action='store_true', dest='scan',
01077 help='take and save 3D scans. specify --pull also.')
01078 p.add_option('--camera', action='store_true', dest='camera',
01079 help='take and save images from UTM camera. specify --pull also.')
01080 p.add_option('--ha', action='store', dest='ha',type='float',
01081 default=None,help='hook angle (degrees).')
01082 p.add_option('--ft', action='store', dest='ft',type='float',
01083 default=None,help='force threshold (Newtons).')
01084 p.add_option('--info', action='store', type='string', dest='info_string',
01085 help='string to save in the pkl log.', default='')
01086 p.add_option('--eaf', action='store_true', dest='eaf',
01087 help='test elbow angle finding with the horizontal plane.')
01088 p.add_option('--move_segway', action='store_true', dest='ms',
01089 help='move the segway while pulling')
01090 p.add_option('--test_reposition', action='store_true', dest='rf',
01091 help='test repositioning the robot. Requires --move_segway')
01092
01093 opt, args = p.parse_args()
01094
01095 scan_flag = opt.scan
01096 camera_flag = opt.camera
01097 move_segway_flag = opt.ms
01098
01099 ha = opt.ha
01100 ft = opt.ft
01101 info_string = opt.info_string
01102
01103 elbow_angle_flag = opt.eaf
01104 reposition_flag = opt.rf
01105 ik_single_pos_flag = opt.ik_single_pos
01106 test_ik_flag = opt.ik_test
01107 pull_flag = opt.pull
01108 search_hook_flag = opt.search_hook or pull_flag
01109
01110 try:
01111 if pull_flag or reposition_flag or search_hook_flag:
01112 if ha == None:
01113 print 'please specify hook angle (--ha)'
01114 print 'Exiting...'
01115 sys.exit()
01116
01117 if ft == None and pull_flag:
01118 print 'please specify force threshold (--ft) along with --pull'
01119 print 'Exiting...'
01120 sys.exit()
01121
01122 if opt.la:
01123 use_left_arm = True
01124 use_right_arm = False
01125 arm = 'left_arm'
01126 else:
01127 use_left_arm = False
01128 use_right_arm = True
01129 arm = 'right_arm'
01130
01131 cmg = CompliantMotionGenerator(move_segway_flag, use_right_arm,
01132 use_left_arm)
01133
01134 print 'hit a key to power up the arms.'
01135 k=m3t.get_keystroke()
01136 cmg.firenze.power_on()
01137
01138 if reposition_flag:
01139 rot_mat = tr.Rz(hook_angle)*tr.Ry(math.radians(-90))
01140 cmg.firenze.pose_robot(arm,rot_mat)
01141 hook_location = cmg.firenze.end_effector_pos(arm)
01142 g = cmg.reposition_robot(hook_location)
01143 cmg.firenze.go_cartesian(arm,g,rot_mat,speed=0.1)
01144
01145 if search_hook_flag:
01146 hook_angle = math.radians(ha)
01147 surface_angle = math.radians(0.)
01148 p = np.matrix([0.45,-0.2,-0.23]).T
01149 if arm == 'left_arm':
01150 p[1,0] = p[1,0] * -1
01151 print 'hit a key to search and hook.'
01152 k=m3t.get_keystroke()
01153 res, jep = cmg.search_and_hook(arm, hook_angle, p,
01154 surface_angle)
01155 print 'Search and Hook result:', res
01156
01157 if pull_flag:
01158 cmg.pull(arm, hook_angle, surface_angle, ft, jep, scan_flag,
01159 camera_flag, 'control_radial_force', info_string)
01160
01161
01162 print 'hit a key to end everything'
01163 k=m3t.get_keystroke()
01164 cmg.stop()
01165
01166
01167
01168 if elbow_angle_flag:
01169 test_elbow_angle()
01170
01171 if ik_single_pos_flag or test_ik_flag:
01172 if ha == None:
01173 raise RuntimeError('You need to specify a hooking angle (--ha)')
01174
01175
01176 p = np.matrix([0.55,-0.2,-0.23]).T
01177 if opt.la:
01178 arm = 'left_arm'
01179 p[1,0] = p[1,0] * -1
01180 settings_l = hr.MekaArmSettings(stiffness_list=[0.15,0.7,0.8,0.8,0.8])
01181 settings_r = None
01182 else:
01183 arm = 'right_arm'
01184 settings_l = None
01185 settings_r = hr.MekaArmSettings(stiffness_list=[0.15,0.7,0.8,0.8,0.8])
01186
01187 firenze = hr.M3HrlRobot(connect = True, right_arm_settings = settings_r,
01188 left_arm_settings = settings_l)
01189 print 'hit a key to power up the arms.'
01190 k=m3t.get_keystroke()
01191 firenze.power_on()
01192
01193 print 'hit a key to test IK'
01194 k=m3t.get_keystroke()
01195
01196
01197 rot_mat = tr.Rz(math.radians(ha))*tr.Ry(math.radians(-90))
01198 firenze.go_cartesian(arm, p, rot_mat, speed=0.1)
01199
01200 if test_ik_flag:
01201 test_IK(arm, p, rot_mat)
01202
01203 print 'hit a key to end everything'
01204 k=m3t.get_keystroke()
01205 firenze.stop()
01206
01207 except (KeyboardInterrupt, SystemExit):
01208 cmg.stop()
01209
01210
01211
01212