compliant_trajectories.py
Go to the documentation of this file.
00001 #
00002 #
00003 # Copyright (c) 2010, Georgia Tech Research Corporation
00004 # All rights reserved.
00005 # 
00006 # Redistribution and use in source and binary forms, with or without
00007 # modification, are permitted provided that the following conditions are met:
00008 #     * Redistributions of source code must retain the above copyright
00009 #       notice, this list of conditions and the following disclaimer.
00010 #     * Redistributions in binary form must reproduce the above copyright
00011 #       notice, this list of conditions and the following disclaimer in the
00012 #       documentation and/or other materials provided with the distribution.
00013 #     * Neither the name of the Georgia Tech Research Corporation nor the
00014 #       names of its contributors may be used to endorse or promote products
00015 #       derived from this software without specific prior written permission.
00016 # 
00017 # THIS SOFTWARE IS PROVIDED BY GEORGIA TECH RESEARCH CORPORATION ''AS IS'' AND
00018 # ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
00019 # WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
00020 # DISCLAIMED. IN NO EVENT SHALL GEORGIA TECH BE LIABLE FOR ANY DIRECT, INDIRECT,
00021 # INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
00022 # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
00023 # OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
00024 # LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
00025 # OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
00026 # ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00027 #
00028 
00029 # \author Advait Jain (Healthcare Robotics Lab, Georgia Tech.)
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 # hrl ros imports
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 # compute the end effector rotation matrix.
00072 # @param hook - hook angle. RADIANS(0, -90, 90) (hor, up, down)
00073 # @param angle - angle between robot and surface normal.
00074 # Angle about the Z axis through which the robot must turn to face
00075 # the surface.
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     # @param move_segway - if True then move the segway while pulling.
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             # stiffness in Nm/rad: [20,50,15,25,2.5]
00097             #settings_r = hr.MekaArmSettings(stiffness_list=[0.1939,0.6713,0.748,0.7272,0.75])
00098             # stiffness in Nm/rad: [20,50,20,25,2.5]
00099             settings_r = hr.MekaArmSettings(stiffness_list=[0.1939,0.6713,0.997,0.7272,0.75])
00100             #settings_r = hr.MekaArmSettings(stiffness_list=[0.7,0.7,0.9,0.9,0.7]) # for RIP project
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             #settings_l = hr.MekaArmSettings(stiffness_list=[0.7,0.7,0.9,0.9,0.7]) # for RIP project
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 # used in segway_motion_local
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             #self.segway_pose = vop.vo_pose('/hrl/segway/pose',ros_init_node=False)
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         #self.firenze.go_jointangles('right_arm',q,arm2='left_arm',q2=q)
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     # move the robot so that hooking location is at a better position
00177     # relative to the robot.
00178     # @param hook_location - 3x1 np matrix (in torso coord frame)
00179     # @param turn_angle - angle (in RADIANS) through which the segway
00180     # should rotate.
00181     # @param hook_angle - angle of the hook. (to determine good height)
00182     # @return new hooking location (3x1) in torso coord frame.
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 #        good_location = np.matrix([0.45,-0.35,h]).T
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() # re-origining for the manipulation behaviors
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     # @param equi_pt_generator: function that returns stop, q  where q: list of 7 joint angles and  stop: string which is '' for compliant motion to continue
00251     # @param rapid_call_func: called in the time between calls to the equi_pt_generator can be used for logging, safety etc.  returns string which is '' for compliant motion to continue
00252     # @param time_step: time between successive calls to equi_pt_generator
00253     # @param arg_list - list of arguments to be passed to the equi_pt_generator
00254     # @return stop (the string which has the reason why the compliant
00255     # motion stopped.), JEP (last commanded JEP)
00256     def compliant_motion(self, equi_pt_generator, time_step, arm, arg_list, record=False,
00257                          rapid_call_func=None):
00258 
00259 #        self.init_wrist_torque = self.firenze.get_wrist_torque(arm)
00260 #        self.firenze.step()
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 #            wrist_torque = self.firenze.get_wrist_torque(arm,base_frame=True)
00271 #            self.firenze.step()
00272 #            if follow_contours:
00273 #                if abs(wrist_torque[0,0]) > threshold:     #If surface is applying a positive torque about roll axis...
00274 #                    q[4] = q[4] + math.radians(wrist_torque[0,0]/ratio_j4) #roll the wrist in the same direction as the torque to get zero net torque.
00275 #                    print 'Roll change: j4=', q[4]
00276 
00277 #                if abs(wrist_torque[1,0]) > threshold:     #If surface is applying a positive torque about pitch axis...
00278 #                    q[5] = q[5] - math.radians(wrist_torque[1,0]/ratio_j5) #pitch the wrist in the same direction as the torque to get zero net torque.
00279 #                    print 'Pitch change: j5=', q[5]
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 #            print 'Commanded JEP:', np.degrees(q)
00304 #            print 'Just called equi_pt_generator once. Hit a key to loop again'
00305 #            k=m3t.get_keystroke()
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     ## log the joint angles, equi pt joint angles and forces.
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) # see equi_pt_generator - q_guess is the config for the eq point.
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 '' # log_state also used as a rapid_call_func
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                 #stop = ''
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             #stop = ''
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     # @param arm - 'right_arm' or 'left_arm'
00397     # @param motion vec is in tl frame.
00398     # @param step_size - distance (meters) through which CEP should move
00399     # @param rot_mat - rotation matrix for IK
00400     # @return JEP
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                     #self.segway_command_node.go_xya_pos_local(t[0],t[1],t[2],blocking=False)
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     # sa - segway pose from VO.
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             # don't open the mechanism
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                 #self.z.nadir(1)
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 # maintaining the orientation of the segway.
00502 
00503         eq_mec = mcf.mecanumTglobal(mcf.globalTtorso(self.eq_pt_cartesian))
00504         svel_rot_y = -avel*eq_mec[0,0] # segway vel in y direction due to rotation
00505         svel_rot_x = avel*eq_mec[1,0] # segway vel in x direction due to rotation
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.) # disallowing +ve translation.
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             #dist_boundary<0.01 or dist_bndry_ee < 0.04:
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     ## constantly update the estimate of the kinematics and move the
00546     # equilibrium point along the tangent of the estimated arc, and
00547     # try to keep the radial force constant.
00548     # @param h_force_possible - True (hook side) or False (hook up).
00549     # @param v_force_possible - False (hook side) or True (hook up).
00550     # Is maintaining a radial force possible or not (based on hook
00551     # geometry and orientation)
00552     # @param cep_vel - tangential velocity of the cep in m/s
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 # 0.1 is the time interval between calls to the equi_generator function (see pull)
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         #mechanism kinematics.
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             # this is specifically for the right arm, and lots of
00591             # other assumptions about the hook etc. (Advait, Feb 28, 2010)
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.: # only allowing upward force.
00598                 force_vec_ts = -force_vec_ts
00599             if force_vec_ts[1,0] < 0.: # only allowing force to the left
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                 # trajectory is parallel to the ground.
00628                 # find tangential direction.
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             #        if cy<0.:
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 # axis to the left, want force in
00644                                            # anti-radial direction.
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                 # here the mechanism does not move in a plane parallel
00651                 # to the ground.
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 # radial_motion_mag in cm (depends on eq_motion step size)
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 #        print 'wrist force:', wrist_force.A1
00706 #        print 'tangential_vec:', tangential_vec.A1
00707 #        print 'tangential_vec_ts:', tangential_vec_ts.A1
00708 #        print 'ftan:', ftan
00709 #        print 'force magnitude:', mag
00710         if abs(dist_moved) > 0.09 and self.hooked_location_moved == False:
00711             # change the force threshold once the hook has started pulling.
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 #                print 'ftan threshold exceed.'
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     ## behavior to search around the hook_loc to try and get a good
00747     # hooking grasp
00748     # @param arm - 'right_arm' or 'left_arm'
00749     # @param hook_angle - radians(0,-90,90) side,up,down
00750     # @param hook_loc - 3x1 np matrix
00751     # @param angle - angle between torso x axis and surface normal.
00752     # @return s, jep (stopping string and last commanded JEP)
00753     def search_and_hook(self, arm, hook_angle, hook_loc, angle,
00754                         hooking_force_threshold = 5.):
00755         #rot_mat = tr.Rz(hook_angle) * tr.Rx(angle) * tr.Ry(math.radians(-90))
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 # hook direc in home position
00760         elif arm == 'left_arm':
00761             hook_dir = np.matrix([0.,-1.,0.]).T # hook direc in home position
00762         else:
00763             raise RuntimeError('Unknown arm: %s', arm)
00764         start_loc = hook_loc + rot_mat.T * hook_dir * -0.03 # 3cm direc opposite to hook.
00765 
00766         # vector normal to surface and pointing into the surface.
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 # funny error in meka control code? or is it gravity comp?
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     ## move along a vertical surface while maintaining a small for on it.
00790     # NOTE: stopping conditions assume we are trying to hook onto a
00791     # handle.
00792     # @param arm - 'left_arm' or 'right_arm'
00793     # @param move_dir - direction along which the end effector moves. (3x1 np matrix in tl frame)
00794     # @param rot_mat - matrix that defines the end effector
00795     # orientation. It transforms points in torso frame to end effector
00796     # frame.
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     # assumes: 1) already hooked onto mechanism.
00823     # @param arm - 'left_arm' or 'right_arm'
00824     # @param hook_angle - RADIANS(0, -90, 90) (hor, up, down)
00825     # @param surface_angle - see rot_mat_from_angles
00826     # @param force_threshold - max force at which to stop pulling.
00827     # @param jep - last commanded JEP.
00828     # @param use_utm - to take 3D scans or not.
00829     # @param use_camera - to take pictures from the camera or not.
00830     # @param strategy - 'line_neg_x': move CEP along -x axis.
00831     #                   'control_radial_force': try and keep the radial force constant
00832     # @param info_string - string saved with key 'info' in the pkl.
00833     # @param cep_vel - tangential velocity of the cep in m/s
00834     # @param kinematics_estimation - 'rotation_center' or 'jacobian'
00835     # @param pull_left - UBER ADHOC. trying to specify initial motion direction (Advait, Feb 28. 2:50am)
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         #rot_mat = tr.Rz(hook_angle)*tr.Ry(math.radians(-90))
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 # flag to indicate when the hooking location started moving.
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 # might want to change this to account for the surface_angle.
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             # this might have to change depending on left and right
00918             # arm? or maybe not since the right arm can open both
00919             # doors.
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             #self.bndry = smc.compute_boundary(self.wrkspc_pts)
00933 
00934 #            thread.start_new_thread(self.circle_estimator,())
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     #        q[1] = math.radians(15)
01056     #        q = firenze.IK('right_arm',p0,rot_mat,q_guess = q)
01057         elbow_angle = firenze.elbow_plane_angle('right_arm',q)
01058         print '---------------------------------------'
01059         print 'ee position:', p0.A1
01060     #        print 'joint angles:', q
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         #----------- non-class functions test --------------------
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             #p = np.matrix([0.45,-0.2,-0.23]).T
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 


2010_icra_epc_pull
Author(s): Advait Jain, Charles C. Kemp (Healthcare Robotics Lab, Georgia Tech)
autogenerated on Wed Nov 27 2013 12:14:43