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