00001
00002 import scipy.optimize as so
00003 import matplotlib.pyplot as pp
00004 import matplotlib_util.util as mpu
00005 import numpy as np, math
00006 import sys, os, time
00007 sys.path.append(os.environ['HRLBASEPATH']+'/src/projects/modeling_forces/handheld_hook')
00008 import ram_db as rd
00009 import mechanism_analyse_RAM as mar
00010 import mechanism_analyse_advait as maa
00011
00012 import arm_trajectories as at
00013 import tangential_force_monitor as tfm
00014
00015 import roslib; roslib.load_manifest('equilibrium_point_control')
00016 import hrl_lib.util as ut, hrl_lib.transforms as tr
00017
00018
00019
00020 def estimate_mechanism_kinematics(pull_dict, pr2_log):
00021 if not pr2_log:
00022 act_tl = at.joint_to_cartesian(pull_dict['actual'], pull_dict['arm'])
00023 force_tl = pull_dict['force']
00024 actual_cartesian, force_ts = at.account_segway_motion(act_tl,
00025 force_tl, pull_dict['segway'])
00026 cartesian_force_clean, _ = at.filter_trajectory_force(actual_cartesian,
00027 pull_dict['force'])
00028 pts_list = actual_cartesian.p_list
00029 pts_2d, reject_idx = at.filter_cartesian_trajectory(cartesian_force_clean)
00030 else:
00031
00032
00033 p_list, f_list = pull_dict['ee_list'], pull_dict['f_list']
00034 p_list = p_list[::2]
00035 f_list = f_list[::2]
00036 pts = np.matrix(p_list).T
00037 px = pts[0,:].A1
00038 py = pts[1,:].A1
00039 pts_2d = np.matrix(np.row_stack((px, py)))
00040
00041
00042 rad = 1.1
00043 x_guess = pts_2d[0,0]
00044 y_guess = pts_2d[1,0] - rad
00045 rad_guess = rad
00046 rad, cx, cy = at.fit_circle(rad_guess,x_guess,y_guess,pts_2d,
00047 method='fmin_bfgs',verbose=False,
00048 rad_fix=False)
00049
00050 return rad, cx, cy
00051
00052 def force_trajectory_in_hindsight(pull_dict, mechanism_type, pr2_log):
00053 print '_________________________________________________'
00054 print 'starting force_trajectory_in_hindsight'
00055 print '_________________________________________________'
00056
00057 if not pr2_log:
00058 arm = pull_dict['arm']
00059 act_tl = at.joint_to_cartesian(pull_dict['actual'], arm)
00060 force_tl = pull_dict['force']
00061 actual_cartesian, force_ts = at.account_segway_motion(act_tl,
00062 force_tl, pull_dict['segway'])
00063 p_list = actual_cartesian.p_list
00064 f_list = force_ts.f_list
00065 else:
00066 p_list, f_list = pull_dict['ee_list'], pull_dict['f_list']
00067 p_list = p_list[::2]
00068 f_list = f_list[::2]
00069
00070 if mechanism_type == 'rotary':
00071 r, cx, cy = estimate_mechanism_kinematics(pull_dict, pr2_log)
00072 print 'rad, cx, cy:', r, cx, cy
00073 frad_list,ftan_list,_ = at.compute_radial_tangential_forces(f_list,
00074 p_list,cx,cy)
00075 p0 = p_list[0]
00076 rad_vec_init = np.matrix((p0[0]-cx, p0[1]-cy)).T
00077 rad_vec_init = rad_vec_init / np.linalg.norm(rad_vec_init)
00078 config_list = []
00079 for p in p_list:
00080 rvec = np.matrix((p[0]-cx, p[1]-cy)).T
00081 rvec = rvec / np.linalg.norm(rvec)
00082 ang = np.arccos((rvec.T*rad_vec_init)[0,0])
00083 if np.isnan(ang):
00084 ang = 0
00085 config_list.append(ang)
00086 else:
00087 p0 = p_list[0]
00088 ftan_list, config_list = [], []
00089 for f, p in zip(f_list, p_list):
00090 config_list.append(p0[0] - p[0])
00091 ftan_list.append(abs(f[0]))
00092
00093 return config_list, ftan_list
00094
00095 def online_force_with_radius(pull_dict, pr2_log, radius_err = 0.,
00096 with_prior = True):
00097 if not pr2_log:
00098 act_tl = at.joint_to_cartesian(pull_dict['actual'], pull_dict['arm'])
00099 force_tl = pull_dict['force']
00100 actual_cartesian, force_ts = at.account_segway_motion(act_tl,
00101 force_tl, pull_dict['segway'])
00102 p_list = actual_cartesian.p_list
00103 f_list = force_ts.f_list
00104 else:
00105 p_list, f_list = pull_dict['ee_list'], pull_dict['f_list']
00106 p_list = p_list[::2]
00107 f_list = f_list[::2]
00108
00109 radius, _, _ = estimate_mechanism_kinematics(pull_dict, pr2_log)
00110 radius += radius_err
00111 print '_________________________________________________'
00112 print 'using radius:', radius
00113 print '_________________________________________________'
00114
00115 pts_list = []
00116 ftan_list = []
00117 config_list = []
00118 for f,p in zip(f_list, p_list):
00119 pts_list.append(p)
00120 pts_2d = (np.matrix(pts_list).T)[0:2,:]
00121
00122 x_guess = pts_list[0][0]
00123 y_guess = pts_list[0][1] - radius
00124 rad_guess = radius
00125 if with_prior:
00126 rad, cx, cy = at.fit_circle_priors(rad_guess, x_guess,
00127 y_guess, pts_2d, sigma_r = 0.2, sigma_xy = 0.2,
00128 sigma_pts = 0.01, verbose=False)
00129 else:
00130 rad, cx, cy = at.fit_circle(rad_guess,x_guess,y_guess,pts_2d,
00131 method='fmin_bfgs',verbose=False,
00132 rad_fix=True)
00133 print 'rad, cx, cy:', rad, cx, cy
00134
00135 p0 = p_list[0]
00136 rad_vec_init = np.matrix((p0[0]-cx, p0[1]-cy)).T
00137 rad_vec_init = rad_vec_init / np.linalg.norm(rad_vec_init)
00138
00139 rad_vec = np.array([p[0]-cx,p[1]-cy])
00140 rad_vec = rad_vec/np.linalg.norm(rad_vec)
00141
00142 ang = np.arccos((rad_vec.T*rad_vec_init)[0,0])
00143 config_list.append(ang)
00144
00145 tan_vec = (np.matrix([[0,-1],[1,0]]) * np.matrix(rad_vec).T).A1
00146 f_vec = np.array([f[0],f[1]])
00147
00148 f_tan_mag = abs(np.dot(f_vec, tan_vec))
00149 ftan_list.append(f_tan_mag)
00150
00151 return config_list, ftan_list
00152
00153 def load_ref_traj(nm):
00154 if 'kitchen_cabinet' in nm:
00155
00156 has_tags = ['HSI_kitchen_cabinet_right']
00157 elif 'lab_cabinet_recessed_left' in nm:
00158 has_tags = ['HSI_lab_cabinet_recessed_left']
00159 elif 'lab_cabinet_recessed_right' in nm:
00160 has_tags = ['HRL_lab_cabinet_recessed_right']
00161 elif 'spring_loaded_door' in nm:
00162 has_tags = ['HSI_Glass_Door']
00163 elif 'hrl_toolchest' in nm:
00164 has_tags = ['HRL_toolchest_drawer_empty']
00165 elif 'ikea_cabinet' in nm:
00166 has_tags = ['HSI_kitchen_cabinet_right']
00167
00168 elif 'refrigerator' in nm:
00169 has_tags = ['naveen_refrigerator']
00170
00171 else:
00172
00173 return None
00174 mn, std, config, typ = rd.get_mean_std_config(has_tags)
00175 return mn, std, config, typ
00176
00177 def error_lists(ftan_l, config_l, ref_dict):
00178
00179 ref_force_dict = {}
00180 ref_force_dict['tangential'] = ref_dict['mean']
00181 ref_force_dict['configuration'] = ref_dict['config']
00182 ref_force_dict['type'] = ref_dict['typ']
00183 ref_force_dict['name'] = ref_dict['name']
00184
00185 rel_err_list = []
00186 abs_err_list = []
00187 for f,c in zip(ftan_l, config_l):
00188 hi, lo, ref_hi, ref_lo = tfm.error_from_reference(ref_force_dict, f, c)
00189
00190
00191
00192 if lo > hi:
00193 err = -lo
00194 ref = ref_lo
00195 else:
00196 err = hi
00197 ref = ref_hi
00198 if ref == 0:
00199 continue
00200
00201
00202 rel_err_list.append(err/ref)
00203 abs_err_list.append(err)
00204
00205 return rel_err_list, abs_err_list
00206
00207 def plot_err_histogram(rel_list, abs_list, title):
00208
00209 max_err = 1.0
00210 bin_width = 0.05
00211 bins = np.arange(0.-bin_width/2.-max_err, max_err+2*bin_width, bin_width)
00212 hist, bin_edges = np.histogram(np.array(rel_list), bins)
00213 mpu.figure()
00214 mpu.plot_histogram(bin_edges[:-1]+bin_width/2., hist,
00215 width=bin_width*0.8, xlabel='Relative Error',
00216 plot_title=title)
00217
00218 max_err = 20
00219 bin_width = 2
00220 bins = np.arange(0.-bin_width/2.-max_err, max_err+2*bin_width, bin_width)
00221 hist, bin_edges = np.histogram(np.array(abs_list), bins)
00222 mpu.figure()
00223 mpu.plot_histogram(bin_edges[:-1]+bin_width/2., hist,
00224 width=bin_width*0.8, xlabel='Absolute Error',
00225 plot_title=title)
00226
00227 def truncate_to_config(ftan_l, config_l, config):
00228 idxs = np.where(np.array(config_l)<config)[0]
00229 idx = idxs[-1]
00230 return ftan_l[:idx+1], config_l[:idx+1]
00231
00232 def plot_pkl(pkl_nm):
00233 pull_dict = ut.load_pickle(pkl_nm)
00234
00235 if 'pr2' in pkl_nm:
00236 pr2_log = True
00237 h_color = 'y'
00238 else:
00239 pr2_log = False
00240 h_color = 'r'
00241
00242 t = load_ref_traj(pkl_nm)
00243 if t !=None:
00244 ref_mean, ref_std, ref_config, typ = t
00245 mar.plot_reference_trajectory(ref_config, ref_mean, ref_std, typ, 'Hello')
00246 ref_config = np.degrees(ref_config)
00247 max_config = np.max(ref_config)
00248 else:
00249 typ = 'rotary'
00250 max_config = 60.
00251
00252 if pr2_log:
00253 o_ftan = pull_dict['ftan_list']
00254 o_config = pull_dict['config_list']
00255 else:
00256 o_ftan = pull_dict['online_ftan']
00257 o_config = pull_dict['online_ang']
00258
00259 h_config, h_ftan = force_trajectory_in_hindsight(pull_dict,
00260 typ, pr2_log)
00261 if typ == 'rotary':
00262 if opt.prior:
00263 r_config, r_ftan = online_force_with_radius(pull_dict,
00264 pr2_log)
00265 r_config = np.degrees(r_config)
00266 o_config = np.degrees(o_config)
00267 h_config = np.degrees(h_config)
00268
00269 o_ftan, o_config = truncate_to_config(o_ftan, o_config, max_config)
00270 h_ftan, h_config = truncate_to_config(h_ftan, h_config, max_config)
00271
00272 if typ == 'rotary':
00273 if opt.prior:
00274 r_ftan, r_config = truncate_to_config(r_ftan, r_config, max_config)
00275 bin_size = 1.
00276 else:
00277 bin_size = 0.01
00278
00279
00280
00281
00282
00283
00284
00285
00286
00287
00288
00289
00290
00291
00292
00293 if not pr2_log:
00294 m,c = get_cody_calibration()
00295 o_ftan = (np.array(o_ftan) - c) / m
00296 h_ftan = (np.array(h_ftan) - c) / m
00297
00298 pp.plot(o_config, o_ftan, 'bo-', ms=5, label='online')
00299 pp.plot(h_config, h_ftan, h_color+'o-', ms=5, label='hindsight')
00300 if typ == 'rotary':
00301 if opt.prior:
00302 r_config, r_ftan = maa.bin(r_config, r_ftan, bin_size, max, True)
00303 pp.plot(r_config, r_ftan, 'go-', ms=5, label='online with priors')
00304 pp.xlabel('Configuration')
00305 pp.ylabel('Tangential Force')
00306
00307 if pr2_log:
00308 pp.figure()
00309 p_list, f_list = pull_dict['ee_list'], pull_dict['f_list']
00310 p_list = p_list[::2]
00311 f_list = f_list[::2]
00312 x_l, y_l, z_l = zip(*p_list)
00313 pp.plot(x_l, y_l)
00314 r, cx, cy = estimate_mechanism_kinematics(pull_dict, pr2_log)
00315 mpu.plot_circle(cx, cy, r, 0., math.pi/2,
00316 label='Actual\_opt', color='r')
00317 pp.axis('equal')
00318
00319
00320 def compute_mean_std(pkls, bin_size):
00321 c_list = []
00322 f_list = []
00323 max_config = math.radians(100.)
00324 typ = 'rotary'
00325 for pkl_nm in pkls:
00326 pull_dict = ut.load_pickle(pkl_nm)
00327 pr2_log = 'pr2' in pkl_nm
00328 h_config, h_ftan = force_trajectory_in_hindsight(pull_dict,
00329 typ, pr2_log)
00330
00331 c_list.append(h_config)
00332 f_list.append(h_ftan)
00333 max_config = min(max_config, np.max(h_config))
00334
00335 leng = int (max_config / bin_size) - 1
00336 ff = []
00337 for c, f in zip(c_list, f_list):
00338
00339 c, f = maa.bin(c, f, bin_size, np.mean, False, empty_value = np.nan)
00340 f, c = truncate_to_config(f, c, max_config)
00341 f = np.ma.masked_array(f, np.isnan(f))
00342 f = f[:leng]
00343 c = c[:leng]
00344 ff.append(f)
00345 arr = np.array(ff)
00346 mean = arr.mean(0)
00347 std = arr.std(0)
00348 return mean, std, c, arr
00349
00350 def calibrate_least_squares(ref_mean, sensor_mean):
00351 ref_mean = np.array(ref_mean)
00352 length = min(ref_mean.shape[0], sensor_mean.shape[0])
00353 ref_mean = ref_mean[:length]
00354 sensor_mean = sensor_mean[:length]
00355 def error_function(params):
00356 m, c = params[0], params[1]
00357 sensor_predict = m * ref_mean + c
00358 err = (sensor_predict - sensor_mean)
00359 return np.sum((err * err) * np.abs(ref_mean))
00360
00361
00362 params = [1., 0.]
00363 r = so.fmin_bfgs(error_function, params, full_output=1,
00364 disp = False, gtol=1e-5)
00365 print 'Optimization result:', r[0]
00366
00367 def get_cody_calibration():
00368 m = 1.13769405
00369 c = 2.22946475
00370
00371 m, c = 1., 0.
00372 return m, c
00373
00374 def convert_to_ram_db(pkls, name):
00375 if pkls == []:
00376 return
00377 bin_size = math.radians(1.)
00378 mean, std, c, arr = compute_mean_std(pkls, bin_size)
00379
00380 d = {}
00381 d['std'] = std
00382 d['mean'] = mean
00383 d['rad'] = -3.141592
00384 d['name'] = name
00385 d['config'] = c
00386 d['vec_list'] = arr.tolist()
00387 d['typ'] = 'rotary'
00388 ut.save_pickle(d, name+'.pkl')
00389
00390
00391 def simulate_perception(pkls, percep_std, name):
00392 c_list = []
00393 f_list = []
00394 trials_per_pkl = 5
00395 bin_size = math.radians(1.)
00396 max_config = math.radians(100.)
00397 for pkl_nm in pkls:
00398 pull_dict = ut.load_pickle(pkl_nm)
00399 pr2_log = 'pr2' in pkl_nm
00400
00401 for t in range(trials_per_pkl):
00402 radius_err = np.random.normal(scale=percep_std)
00403
00404 h_config, h_ftan = online_force_with_radius(pull_dict, pr2_log, radius_err)
00405 c_list.append(h_config)
00406 f_list.append(h_ftan)
00407 max_config = min(max_config, np.max(h_config))
00408
00409 leng = int (max_config / bin_size) - 1
00410 ff = []
00411 for c, f in zip(c_list, f_list):
00412 c, f = maa.bin(c, f, bin_size, np.mean, False, empty_value = np.nan)
00413 f, c = truncate_to_config(f, c, max_config)
00414 f = np.ma.masked_array(f, np.isnan(f))
00415 f = f[:leng]
00416 c = c[:leng]
00417 ff.append(f)
00418 arr = np.array(ff)
00419 mean = arr.mean(0)
00420 std = arr.std(0)
00421
00422 d = {}
00423 d['std'] = std
00424 d['mean'] = mean
00425 d['rad'] = -3.141592
00426 d['name'] = name
00427 d['config'] = c
00428 d['vec_list'] = arr.tolist()
00429 d['typ'] = 'rotary'
00430 ut.save_pickle(d, name+'.pkl')
00431
00432 def known_radius(pkls, name):
00433 c_list = []
00434 f_list = []
00435 trials_per_pkl = 1
00436 bin_size = math.radians(1.)
00437 max_config = math.radians(100.)
00438 for pkl_nm in pkls:
00439 pull_dict = ut.load_pickle(pkl_nm)
00440 pr2_log = 'pr2' in pkl_nm
00441
00442 for t in range(trials_per_pkl):
00443 h_config, h_ftan = online_force_with_radius(pull_dict,
00444 pr2_log, with_prior = False)
00445 c_list.append(h_config)
00446 f_list.append(h_ftan)
00447 max_config = min(max_config, np.max(h_config))
00448
00449 leng = int (max_config / bin_size) - 1
00450 ff = []
00451 for c, f in zip(c_list, f_list):
00452 c, f = maa.bin(c, f, bin_size, np.mean, False, empty_value = np.nan)
00453 f, c = truncate_to_config(f, c, max_config)
00454 f = np.ma.masked_array(f, np.isnan(f))
00455 f = f[:leng]
00456 c = c[:leng]
00457 ff.append(f)
00458 arr = np.array(ff)
00459 mean = arr.mean(0)
00460 std = arr.std(0)
00461
00462 d = {}
00463 d['std'] = std
00464 d['mean'] = mean
00465 d['rad'] = -3.141592
00466 d['name'] = name
00467 d['config'] = c
00468 d['vec_list'] = arr.tolist()
00469 d['typ'] = 'rotary'
00470 ut.save_pickle(d, name+'.pkl')
00471
00472
00473 if __name__ == '__main__':
00474 import optparse
00475 import glob
00476 p = optparse.OptionParser()
00477 p.add_option('-d', action='store', type='string', dest='dir_nm',
00478 help='plot all the pkls in the directory.', default='')
00479 p.add_option('-f', action='store', type='string', dest='fname',
00480 help='pkl file to use.', default='')
00481 p.add_option('--prior', action='store_true', dest='prior',
00482 help='estimate tangential force using prior.')
00483 p.add_option('--calibrate', action='store_true', dest='calibrate',
00484 help='calibrate the sensor using the ref trajectory.')
00485 p.add_option('--ram_db', action='store_true', dest='ram_db',
00486 help='convert trials to ram_db format.')
00487 p.add_option('--nm', action='store', dest='name', default='',
00488 help='name for the ram_db dict.')
00489 p.add_option('--simulate_percep', action='store_true', dest='simulate_percep',
00490 help='simulate perception.')
00491
00492 opt, args = p.parse_args()
00493
00494 if opt.calibrate:
00495 pkls_nm = glob.glob(opt.dir_nm+'/*pull*.pkl')
00496 ref_mean, ref_std, ref_config, typ = load_ref_traj(pkls_nm[0])
00497 cody_pkls = glob.glob(opt.dir_nm+'/*trajector*.pkl')
00498 cody_mn, cody_std, cody_config, _ = compute_mean_std(cody_pkls, math.radians(1.))
00499 calibrate_least_squares(ref_mean, cody_mn)
00500 sys.exit()
00501
00502
00503 if opt.simulate_percep:
00504 percep_std = 0.1
00505 if opt.name == '':
00506 name = opt.dir_nm.split('/')[0]
00507 else:
00508 name = opt.name
00509 cody_pkls = glob.glob(opt.dir_nm+'/*trajector*.pkl')
00510 if cody_pkls != []:
00511 simulate_perception(cody_pkls, percep_std, name+'_noisy_cody')
00512 known_radius(cody_pkls, name+'_known_rad_cody')
00513 pr2_pkls = glob.glob(opt.dir_nm+'/pr2*.pkl')
00514 if pr2_pkls != []:
00515 simulate_perception(pr2_pkls, percep_std, name+'_noisy_pr2')
00516 known_radius(pr2_pkls, name+'_known_rad_pr2')
00517
00518 sys.exit()
00519
00520
00521 if opt.ram_db:
00522 if opt.name == '':
00523 name = opt.dir_nm.split('/')[0]
00524 else:
00525 name = opt.name
00526 cody_pkls = glob.glob(opt.dir_nm+'/*trajector*.pkl')
00527 convert_to_ram_db(cody_pkls, name+'_cody')
00528 pr2_pkls = glob.glob(opt.dir_nm+'/pr2*.pkl')
00529 convert_to_ram_db(pr2_pkls, name+'_pr2')
00530 sys.exit()
00531
00532 if opt.dir_nm != '':
00533 pkls_nm = glob.glob(opt.dir_nm+'/*pull*.pkl')
00534
00535 pp.figure()
00536 ref_mean, ref_std, ref_config, typ = load_ref_traj(pkls_nm[0])
00537 mar.plot_reference_trajectory(ref_config, ref_mean, ref_std, typ, 'Hello')
00538
00539 pr2_pkls = glob.glob(opt.dir_nm+'/pr2*.pkl')
00540 if pr2_pkls != []:
00541 pr2_mn, pr2_std, pr2_config, _ = compute_mean_std(pr2_pkls, math.radians(1.))
00542
00543 c1 = 'b'
00544 pr2_config = np.degrees(pr2_config)
00545 pp.plot(pr2_config, pr2_mn, color=c1, label='PR2')
00546 pp.fill_between(pr2_config, np.array(pr2_mn)+np.array(pr2_std),
00547 np.array(pr2_mn)-np.array(pr2_std), color=c1, alpha=0.5)
00548
00549 cody_pkls = glob.glob(opt.dir_nm+'/*trajector*.pkl')
00550 if cody_pkls != []:
00551 cody_mn, cody_std, cody_config, _ = compute_mean_std(cody_pkls, math.radians(1.))
00552 m,c = get_cody_calibration()
00553 cody_mn = (cody_mn - c) / m
00554
00555 cody_mn = cody_mn[1:]
00556 cody_std = cody_std[1:]
00557 cody_config = cody_config[:-1]
00558 c1 = 'r'
00559 cody_config = np.degrees(cody_config)
00560 pp.plot(cody_config, cody_mn, color=c1, label='Cody')
00561 pp.fill_between(cody_config, np.array(cody_mn)+np.array(cody_std),
00562 np.array(cody_mn)-np.array(cody_std), color=c1, alpha=0.5)
00563 pp.legend()
00564 pp.show()
00565
00566 if opt.fname:
00567 plot_pkl(opt.fname)
00568 pp.legend()
00569 pp.show()
00570
00571