push_learning.py
Go to the documentation of this file.
00001 #!/usr/bin/env python
00002 # Software License Agreement (BSD License)
00003 #
00004 #  Copyright (c) 2012, Georgia Institute of Technology
00005 #  All rights reserved.
00006 #
00007 #  Redistribution and use in source and binary forms, with or without
00008 #  modification, are permitted provided that the following conditions
00009 #  are met:
00010 #
00011 #  * Redistributions of source code must retain the above copyright
00012 #     notice, this list of conditions and the following disclaimer.
00013 #  * Redistributions in binary form must reproduce the above
00014 #     copyright notice, this list of conditions and the following
00015 #     disclaimer in the documentation and/or other materials provided
00016 #     with the distribution.
00017 #  * Neither the name of the Georgia Institute of Technology nor the names of
00018 #     its contributors may be used to endorse or promote products derived
00019 #     from this software without specific prior written permission.
00020 #
00021 #  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
00022 #  'AS IS' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
00023 #  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
00024 #  FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
00025 #  COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
00026 #  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
00027 #  BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
00028 #  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
00029 #  CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
00030 #  LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
00031 #  ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
00032 #  POSSIBILITY OF SUCH DAMAGE.
00033 import roslib; roslib.load_manifest('tabletop_pushing')
00034 from geometry_msgs.msg import Point, Pose2D, Twist
00035 import tf.transformations as tr
00036 from push_primitives import *
00037 from tabletop_pushing.srv import *
00038 from tabletop_pushing.msg import *
00039 import rospy
00040 import cv2
00041 import numpy as np
00042 import sys
00043 from math import sin, cos, pi, sqrt, fabs, atan2, hypot, acos, isnan
00044 #from pylab import *
00045 import matplotlib.pyplot as plotter
00046 import random
00047 import os
00048 import subprocess
00049 
00050 _VERSION_LINE = '# v0.6'
00051 _LEARN_TRIAL_HEADER_LINE = '# object_id/trial_id init_x init_y init_z init_theta final_x final_y final_z final_theta goal_x goal_y goal_theta push_start_point.x push_start_point.y push_start_point.z behavior_primitive controller proxy which_arm push_time precondition_method score [shape_descriptors]'
00052 _CONTROL_HEADER_LINE = '# x.x x.y x.theta x_dot.x x_dot.y x_dot.theta x_desired.x x_desired.y x_desired.theta theta0 u.linear.x u.linear.y u.linear.z u.angular.x u.angular.y u.angular.z time hand.x hand.y hand.z'
00053 _BAD_TRIAL_HEADER_LINE='#BAD_TRIAL'
00054 _DEBUG_IO = False
00055 
00056 def subPIAngle(theta):
00057     while theta < -pi:
00058         theta += 2.0*pi
00059     while theta > pi:
00060         theta -= 2.0*pi
00061     return theta
00062 
00063 def point_line_dist(pt, a, b):
00064     '''
00065     Get the perpendicular distance from pt to the line defined through (a,b)
00066     '''
00067     A = np.asarray(a)
00068     B = np.asarray(b)
00069     P = np.asarray(pt)
00070     q = A - P
00071     n = B-A
00072     n_hat = n / np.linalg.norm(n)
00073     return np.linalg.norm(q-np.dot(q,n_hat)*n_hat)
00074 
00075 class PushTrial:
00076     def __init__(self):
00077         self.object_id = ''
00078         self.controller = ''
00079         self.behavior_primitive = ''
00080         self.proxy = ''
00081         self.which_arm = ''
00082         self.precondition_method = ''
00083         self.init_centroid = Point()
00084         self.init_orientation = 0.0
00085         self.final_centroid = Point()
00086         self.final_orientation = 0.0
00087         self.goal_pose = Pose2D()
00088         self.start_point = Point()
00089         self.push_time = 0.0
00090         # NOTE: Everything below not saved to disk, just computed for convenience
00091         self.push_angle = 0.0
00092         self.push_dist = 0.0
00093         self.continuation = False
00094         self.score = -1.0
00095         self.shape_descriptor = []
00096 
00097     def __str__(self):
00098         return (self.object_id +
00099                 ' (' + self.proxy + ', ' + self.controller + ', ' + self.behavior_primitive + ', ' +
00100                 self.which_arm + '_arm'+', ' +self.precondition_method+'):\n' +
00101                 'init_centroid:\n' + str(self.init_centroid) + '\n'+
00102                 'init_orientation: ' + str(self.init_orientation) +'\n'+
00103                 'final_centroid:\n' + str(self.final_centroid) + '\n'+
00104                 'final_orientation: ' + str(self.final_orientation) + '\n'+
00105                 'goal_pose:\n' + str(self.goal_pose) + '\n'+
00106                 'push_time: ' + str(self.push_time))
00107 
00108 class ControlTimeStep:
00109     def __init__(self, x, x_dot, x_desired, theta0, u, t):
00110         self.x = x
00111         self.x_dot = x_dot
00112         self.x_desired = x_desired
00113         self.theta0 = theta0
00114         self.u = u
00115         self.t = t
00116 
00117 class PushCtrlTrial:
00118     def __init__(self):
00119         self.trial_start = None
00120         self.trial_end = None
00121         self.trial_trajectory = []
00122 
00123     def __str__(self):
00124         return (str(self.trial_start) + '\n' + str(self.trial_trajectory) + '\n' + str(self.trial_end))
00125 
00126 class PushLearningIO:
00127     def __init__(self):
00128         self.data_out = None
00129         self.data_in = None
00130 
00131     def write_line(self, init_centroid, init_orientation, final_centroid,
00132                    final_orientation, goal_pose, push_start_point, behavior_primitive,
00133                    controller, proxy, which_arm, push_time, object_id,
00134                    push_point, precondition_method='centroid_push', push_score=-1):
00135         if self.data_out is None:
00136             rospy.logerr('Attempting to write to file that has not been opened.')
00137             return
00138         rospy.logdebug('Writing output line.\n')
00139         data_line = object_id+' '+str(init_centroid.x)+' '+str(init_centroid.y)+' '+str(init_centroid.z)+' '+\
00140             str(init_orientation)+' '+str(final_centroid.x)+' '+str(final_centroid.y)+' '+\
00141             str(final_centroid.z)+' '+str(final_orientation)+' '+\
00142             str(goal_pose.x)+' '+str(goal_pose.y)+' '+str(goal_pose.theta)+' '+\
00143             str(push_start_point.x)+' '+str(push_start_point.y)+' '+str(push_start_point.z)+' '+\
00144             behavior_primitive+' '+controller+' '+proxy+' '+which_arm+' '+str(push_time)+' '+precondition_method+' '+\
00145             str(push_score)+'\n'
00146         self.data_out.write(_LEARN_TRIAL_HEADER_LINE+'\n')
00147         self.data_out.write(data_line)
00148         self.data_out.flush()
00149 
00150     def parse_line(self, line):
00151         if line.startswith('#'):
00152             return None
00153         l  = line.split()
00154         l.reverse()
00155         num_objs = len(l)
00156         push = PushTrial()
00157         push.object_id = l.pop()
00158         push.init_centroid.x = float(l.pop())
00159         push.init_centroid.y = float(l.pop())
00160         push.init_centroid.z = float(l.pop())
00161         push.init_orientation = float(l.pop())
00162         push.final_centroid.x = float(l.pop())
00163         push.final_centroid.y = float(l.pop())
00164         push.final_centroid.z = float(l.pop())
00165         push.final_orientation = float(l.pop())
00166         push.goal_pose.x = float(l.pop())
00167         push.goal_pose.y = float(l.pop())
00168         push.goal_pose.theta = float(l.pop())
00169         push.start_point.x = float(l.pop())
00170         push.start_point.y = float(l.pop())
00171         push.start_point.z = float(l.pop())
00172         push.behavior_primitive = l.pop()
00173         push.controller = l.pop()
00174         push.proxy = l.pop()
00175         push.which_arm = l.pop()
00176         push.push_time = float(l.pop())
00177         if len(l) > 0:
00178             push.precondition_method = l.pop()
00179         else:
00180             push.precondition_method = 'push_centroid'
00181         if len(l) > 0:
00182             push.score = float(l.pop())
00183         else:
00184             push.score = -1.0
00185         push.shape_descriptor = []
00186         while len(l) > 0:
00187             push.shape_descriptor.append(float(l.pop()))
00188 
00189         push.push_angle = atan2(push.goal_pose.y-push.init_centroid.y,
00190                                 push.goal_pose.x-push.init_centroid.x)
00191         push.push_dist = hypot(push.goal_pose.y-push.init_centroid.y,
00192                                push.goal_pose.x-push.init_centroid.x)
00193         if push.init_centroid.x > 1.0:
00194             print 'Greater than 1.0 x: ', str(push)
00195         return push
00196 
00197     def write_pre_push_line(self, init_centroid, init_orientation, goal_pose, push_start_point, behavior_primitive,
00198                             controller, proxy, which_arm, object_id, precondition_method,
00199                             predicted_score=-1.0, shape_descriptor=None):
00200         if self.data_out is None:
00201             rospy.logerr('Attempting to write to file that has not been opened.')
00202             return
00203         rospy.logdebug('Writing pre push output line.\n')
00204         data_line = object_id+' '+str(init_centroid.x)+' '+str(init_centroid.y)+' '+str(init_centroid.z)+' '+\
00205             str(init_orientation)+' '+str(0.0)+' '+str(0.0)+' '+\
00206             str(0.0)+' '+str(0.0)+' '+\
00207             str(goal_pose.x)+' '+str(goal_pose.y)+' '+str(goal_pose.theta)+' '+\
00208             str(push_start_point.x)+' '+str(push_start_point.y)+' '+str(push_start_point.z)+' '+\
00209             behavior_primitive+' '+controller+' '+proxy+' '+which_arm+' '+str(0.0)+' '+precondition_method+ ' ' +\
00210             str(predicted_score)
00211 
00212         if shape_descriptor is not None:
00213             for s in shape_descriptor:
00214                 data_line += ' '+str(s)
00215         data_line+='\n'
00216         self.data_out.write(_LEARN_TRIAL_HEADER_LINE+'\n')
00217         self.data_out.write(data_line)
00218         self.data_out.flush()
00219 
00220     def write_bad_trial_line(self):
00221         self.data_out.write(_BAD_TRIAL_HEADER_LINE+'\n')
00222         self.data_out.flush()
00223 
00224     def read_in_data_file(self, file_name):
00225         data_in = file(file_name, 'r')
00226         x = [self.parse_line(l) for l in data_in.readlines()]
00227         data_in.close()
00228         x = filter(None, x)
00229         return self.link_repeat_trials(x)
00230 
00231     def link_repeat_trials(self, trials):
00232         for i in range(1,len(trials)):
00233             if (trials[i].goal_pose.y == trials[i-1].goal_pose.y and
00234                 trials[i].goal_pose.x == trials[i-1].goal_pose.x and
00235                 trials[i].behavior_primitive == trials[i-1].behavior_primitive and
00236                 trials[i].proxy == trials[i-1].proxy and
00237                 trials[i].controller == trials[i-1].controller):
00238                 if trials[i].which_arm == trials[i-1].which_arm:
00239                     # print 'Continuation with different arm'
00240                     pass
00241                 else:
00242                     trials[i].continuation = True
00243         return trials
00244 
00245     def open_out_file(self, file_name):
00246         self.data_out = file(file_name, 'a')
00247         self.data_out.write(_VERSION_LINE+'\n')
00248         # self.data_out.write(_LEARN_TRIAL_HEADER_LINE+'\n')
00249         self.data_out.flush()
00250 
00251     def close_out_file(self):
00252         self.data_out.close()
00253 
00254 class ControlAnalysisIO:
00255     def __init__(self):
00256         self.data_out = None
00257         self.data_in = None
00258 
00259     def write_line(self, x, x_dot, x_desired, theta0, u, time, hand_pose):
00260         if self.data_out is None:
00261             rospy.logerr('Attempting to write to file that has not been opened.')
00262             return
00263         data_line = str(x.x)+' '+str(x.y)+' '+str(x.theta)+' '+\
00264             str(x_dot.x)+' '+str(x_dot.y)+' '+str(x_dot.theta)+' '+\
00265             str(x_desired.x)+' '+str(x_desired.y)+' '+str(x_desired.theta)+' '+\
00266             str(theta0)+' '+str(u.linear.x)+' '+str(u.linear.y)+' '+str(u.linear.z)+' '+\
00267             str(u.angular.x)+' '+str(u.angular.y)+' '+str(u.angular.z)+' '+str(time)+' '+\
00268             str(hand_pose.position.x)+' '+str(hand_pose.position.y)+' '+str(hand_pose.position.z)+\
00269             '\n'
00270         self.data_out.write(data_line)
00271         self.data_out.flush()
00272 
00273     def parse_line(self, line):
00274         if line.startswith('#'):
00275             return None
00276         data = [float(s) for s in line.split()]
00277         x = Pose2D()
00278         x_dot = Pose2D()
00279         x_desired = Pose2D()
00280         u = Twist()
00281         x.x = data[0]
00282         x.y = data[1]
00283         x.theta = data[2]
00284         x_dot.x = data[3]
00285         x_dot.y = data[4]
00286         x_dot.theta = data[5]
00287         x_desired.x = data[6]
00288         x_desired.y = data[7]
00289         x_desired.theta = data[8]
00290         theta0 = data[9]
00291         u.linear.x = data[10]
00292         u.linear.y = data[11]
00293         u.linear.z = data[12]
00294         u.angular.x = data[13]
00295         u.angular.y = data[14]
00296         u.angular.z = data[15]
00297         t = data[16]
00298         ee_x = data[17]
00299         ee_y = data[18]
00300         ee_z = data[19]
00301         cts = ControlTimeStep(x, x_dot, x_desired, theta0, u, t)
00302         return cts
00303 
00304     def read_in_data_file(self, file_name):
00305         data_in = file(file_name, 'r')
00306         x = [self.parse_line(l) for l in data_in.readlines()[1:]]
00307         data_in.close()
00308         return filter(None, x)
00309 
00310     def open_out_file(self, file_name):
00311         self.data_out = file(file_name, 'a')
00312         self.data_out.write(_CONTROL_HEADER_LINE+'\n')
00313         self.data_out.flush()
00314 
00315     def close_out_file(self):
00316         self.data_out.close()
00317 
00318 class CombinedPushLearnControlIO:
00319     def __init__(self):
00320         self.pl_io = PushLearningIO()
00321         self.ctrl_io = ControlAnalysisIO()
00322         self.push_trials = []
00323 
00324     def read_in_data_file(self, file_name):
00325         data_in = file(file_name, 'r')
00326         read_pl_trial_line = False
00327         read_ctrl_line = False
00328         trial_is_start = True
00329 
00330         trial_starts = 0
00331         bad_stops = 0
00332         object_comments = 0
00333         control_headers = 0
00334 
00335         self.push_trials = []
00336         current_trial = PushCtrlTrial()
00337         for line in  data_in.readlines():
00338             if line.startswith(_VERSION_LINE):
00339                 if _DEBUG_IO:
00340                     print 'Ignoring version line'
00341                 continue
00342             elif line.startswith(_LEARN_TRIAL_HEADER_LINE):
00343                 object_comments += 1
00344 
00345                 if _DEBUG_IO:
00346                     print 'Read learn trial header'
00347                 if trial_is_start:
00348                     trial_starts += 1
00349                 read_pl_trial_line = True
00350                 read_ctrl_line = False
00351             elif line.startswith(_CONTROL_HEADER_LINE):
00352                 if _DEBUG_IO:
00353                     print 'Read control header'
00354                 control_headers += 1
00355                 read_ctrl_line = True
00356             elif line.startswith(_BAD_TRIAL_HEADER_LINE):
00357                 bad_stops += 1
00358                 if _DEBUG_IO:
00359                     print 'BAD TRIAL: not adding current trial to list'
00360                 # Reset trial and switch to read next pl_trial_line as start trial
00361                 current_trial = PushCtrlTrial()
00362                 trial_is_start = True
00363             elif read_pl_trial_line:
00364                 if _DEBUG_IO:
00365                     print 'Reading trial'
00366                 trial = self.pl_io.parse_line(line)
00367                 read_pl_trial_line = False
00368                 if trial_is_start:
00369                     current_trial.trial_start = trial
00370                     if _DEBUG_IO:
00371                         print 'Trial is start trial'
00372                 else:
00373                     if _DEBUG_IO:
00374                         print 'Trial is end trial'
00375                     current_trial.trial_end = trial
00376                     self.push_trials.append(current_trial)
00377                     current_trial = PushCtrlTrial()
00378                 trial_is_start = not trial_is_start
00379             elif read_ctrl_line:
00380                 if _DEBUG_IO:
00381                     print 'Read ctrl pt'
00382                 traj_pt = self.ctrl_io.parse_line(line)
00383                 current_trial.trial_trajectory.append(traj_pt)
00384             else:
00385                 if _DEBUG_IO:
00386                     print 'None of these?'
00387         data_in.close()
00388         # print 'object_comments',object_comments
00389         print 'Read in', file_name
00390         print 'trial_starts',trial_starts
00391         print 'bad_stops',bad_stops
00392         # print 'control_headers',control_headers
00393         print 'num trials', len(self.push_trials), '\n'
00394 
00395     def write_example_file(self, file_name, X, Y, normalize=False, debug=False):
00396         data_out = file(file_name, 'w')
00397         # print 'Normalize:', normalize
00398         k = 0
00399         for x,y in zip(X,Y):
00400             k += 1
00401             if debug:
00402                 print y, x
00403             if isnan(y):
00404                 print 'Skipping writing example: ', k
00405                 continue
00406             data_line = str(y)
00407             if normalize:
00408                 feature_sum = 0.0
00409                 for xi in x:
00410                     feature_sum += xi
00411                 for i, xi in enumerate(x):
00412                     if xi > 0:
00413                         data_line += ' ' + str(i+1)+':'+str(sqrt(xi/float(feature_sum)))
00414             else:
00415                 for i, xi in enumerate(x):
00416                     if xi > 0:
00417                         data_line += ' ' + str(i+1)+':'+str(xi)
00418             data_line +='\n'
00419             data_out.write(data_line)
00420         print 'Wrote', k, 'examples'
00421         data_out.close()
00422 
00423     def read_example_file(self, file_name):
00424         data_in = file(file_name, 'r')
00425         lines = [l.split() for l in data_in.readlines()]
00426         data_in.close()
00427         Y = []
00428         X = []
00429         for line in lines:
00430             y = float(line.pop(0))
00431             Y.append(y)
00432             x = []
00433             for pair in line:
00434                 idx, val = pair.split(':')
00435                 idx = int(idx) - 1
00436                 val = float(val)
00437                 while len(x) < idx:
00438                     x.append(0)
00439                 x.append(val)
00440             X.append(x)
00441         return (X,Y)
00442 
00443     def read_regression_prediction_file(self, file_name):
00444         data_in = file(file_name, 'r')
00445         Y_hat = [float(y.strip()) for y in data_in.readlines()]
00446         data_in.close()
00447         return Y_hat
00448 
00449 class StartLocPerformanceAnalysis:
00450 
00451     def __init__(self):
00452         self.analyze_straight_line_push = self.analyze_straight_line_push_line_dist
00453         self.analyze_spin_push = self.analyze_spin_push_net_spin
00454         # self.analyze_spin_push = self.analyze_spin_push_net_spin_signed
00455 
00456     def compare_predicted_and_observed_push_scores(self, in_file_name, out_file_name=None, use_spin=False):
00457         # Read in data
00458         plio = CombinedPushLearnControlIO()
00459         plio.read_in_data_file(in_file_name)
00460         file_out = None
00461         if out_file_name is not None:
00462             file_out = file(out_file_name, 'w')
00463         for i, p in enumerate(plio.push_trials):
00464             pred_score = p.trial_start.score
00465             # Compute observed push score
00466             if use_spin:
00467                 observed_score = self.analyze_spin_push(p)
00468             else:
00469                 observed_score = self.analyze_straight_line_push(p)
00470             print 'Trial [',i,'] : Pred: ', pred_score, '\tObserved: ', observed_score
00471             if file_out is not None:
00472                 trial_line = str(pred_score) + ' ' + str(observed_score) + '\n'
00473                 file_out.write(trial_line)
00474         if file_out is not None:
00475             file_out.close()
00476 
00477     def compute_observed_push_scores_final_errors(self, in_file_name, out_file_name=None, use_spin=False):
00478         # Read in data
00479         plio = CombinedPushLearnControlIO()
00480         plio.read_in_data_file(in_file_name)
00481         file_out = None
00482         if out_file_name is not None:
00483             file_out = file(out_file_name, 'w')
00484         for i, p in enumerate(plio.push_trials):
00485             final_pose = p.trial_end.final_centroid
00486             final_orientation = p.trial_end.final_orientation
00487             goal_pose = p.trial_start.goal_pose
00488             if use_spin:
00489                 final_error = abs(subPIAngle(goal_pose.theta - final_orientation))
00490             else:
00491                 # Compute observed push score
00492                 err_x = goal_pose.x - final_pose.x
00493                 err_y = goal_pose.y - final_pose.y
00494                 final_error = hypot(err_x, err_y)
00495             if file_out is not None:
00496                 trial_line = str(final_error)+'\n'
00497                 file_out.write(trial_line)
00498         if file_out is not None:
00499             file_out.close()
00500 
00501     def get_trial_features(self, file_name, use_spin=False):
00502         self.plio = CombinedPushLearnControlIO()
00503         self.plio.read_in_data_file(file_name)
00504         Y = []
00505         X = []
00506         for i, p in enumerate(self.plio.push_trials):
00507             if use_spin:
00508                 y = self.analyze_spin_push(p)
00509             else:
00510                 y = self.analyze_straight_line_push(p)
00511             if y < 0:
00512                 continue
00513             x = p.trial_start.shape_descriptor
00514             Y.append(y)
00515             X.append(x)
00516         return (X,Y)
00517 
00518     def generate_example_file(self, file_in_name, file_out_name, normalize=False, set_train=False,
00519                               set_test=False, use_spin=False):
00520         (X, Y) = self.get_trial_features(file_in_name, use_spin)
00521         print 'Read in', len(X), 'sample locations'
00522         self.plio.write_example_file(file_out_name, X, Y, normalize)
00523         if set_train:
00524             self.X_train = X[:]
00525             self.Y_train = Y[:]
00526         if set_test:
00527             self.X_test = X[:]
00528             self.Y_test = Y[:]
00529 
00530     def generate_train_and_test_files(self, file_in, file_out, normalize=False, train_percent=0.6,
00531                                       must_move_epsilon=0.05):
00532         (X,Y) = self.get_trial_features(file_in)
00533         Z = zip(X,Y)
00534         # random.shuffle(Z)
00535         if file_out.endswith('.txt'):
00536             train_file_out = file_out[:-4]+'_train'+'.txt'
00537             test_file_out = file_out[:-4]+'_test'+'.txt'
00538         else:
00539             train_file_out = file_out+'_train'
00540             test_file_out = file_out+'_test'
00541 
00542         # TODO: Make more informed based on object_id
00543         num_train_examples = int(train_percent*len(X))
00544         print 'Read in', len(X), 'examples'
00545         print 'Training file has', num_train_examples, 'examples'
00546         print 'Test file has', len(X)-num_train_examples, 'examples'
00547         self.Y_train = []
00548         self.X_train = []
00549         self.Y_test = []
00550         self.X_test = []
00551 
00552         for i, xy in enumerate(Z):
00553             x = xy[0]
00554             y = xy[1]
00555             if i < num_train_examples:
00556                 self.Y_train.append(y)
00557                 self.X_train.append(x)
00558             else:
00559                 self.Y_test.append(y)
00560                 self.X_test.append(x)
00561         print 'len(Y_train)', len(self.Y_train)
00562         self.plio.write_example_file(train_file_out, self.X_train, self.Y_train, normalize)
00563         print 'len(Y_test)', len(self.Y_test)
00564         self.plio.write_example_file(test_file_out, self.X_test, self.Y_test, normalize)
00565 
00566     def plot_svm_results(self, pred_file):
00567         self.Y_hat = self.plio.read_regression_prediction_file(pred_file)
00568 
00569         max_score = 0.0
00570         Y_test_norm = self.Y_test[:]
00571         Y_hat_norm = self.Y_hat[:]
00572         Y_diffs = []
00573         for i in xrange(len(Y_test_norm)):
00574             # TODO: Get max and normalize
00575             if self.Y_test[i] > max_score:
00576                 max_score = self.Y_test[i]
00577             if self.Y_hat[i] > max_score:
00578                 max_score = self.Y_hat[i]
00579             Y_diffs.append(fabs(self.Y_hat[i]-self.Y_test[i]))
00580         for i in xrange(len(Y_test_norm)):
00581             Y_test_norm[i] = self.Y_test[i]/max_score
00582             Y_hat_norm[i] = self.Y_hat[i]/max_score
00583         print 'Average error is', sum(Y_diffs)/len(Y_diffs)
00584         print 'Max error is', max(Y_diffs)
00585         print 'Min error is', min(Y_diffs)
00586         p1, = plotter.plot(Y_test_norm, Y_hat_norm,'bx')
00587         plotter.xlabel('True Score')
00588         plotter.ylabel('Predicted score')
00589         plotter.title('Push Scoring Evaluation')
00590         plotter.xlim((0.0,1.0))
00591         plotter.ylim((0.0,1.0))
00592         plotter.show()
00593 
00594     def plot_svm_results_old(self, pred_file):
00595         self.Y_hat = self.plio.read_regression_prediction_file(pred_file)
00596 
00597         Ys_ordered = zip(self.Y_test[:], self.Y_hat[:])
00598         Ys_ordered.sort(key=lambda test_value: test_value[0])
00599         Y_test_ordered = []
00600         Y_hat_ordered = []
00601         Y_diffs = []
00602         for Ys in Ys_ordered:
00603             Y_test_ordered.append(Ys[0])
00604             Y_hat_ordered.append(Ys[1])
00605             Y_diffs.append(fabs(Ys[0]-Ys[1]))
00606         print 'Average error is', sum(Y_diffs)/len(Y_diffs)
00607         print 'Max error is', max(Y_diffs)
00608         print 'Min error is', min(Y_diffs)
00609         p1, = plotter.plot(Y_test_ordered,'bx')
00610         p2, = plotter.plot(Y_hat_ordered, 'r+')
00611         plotter.xlabel('Test index')
00612         plotter.ylabel('Straight push score')
00613         plotter.title('Push Scoring Evaluation')
00614         plotter.legend([p1,p2],['True Score', 'Predicted Score'], loc=2)
00615         plotter.show()
00616 
00617     def lookup_push_trial_by_shape_descriptor(self, trials, descriptor):
00618         for t in trials:
00619             match = True
00620             for a,b in zip(t.trial_start.shape_descriptor, descriptor):
00621                 if a != b:
00622                     match = False
00623             if match:
00624                 print t
00625                 return t
00626         return None
00627 
00628     def analyze_straight_line_push_delta_theta(self, push_trial):
00629         '''
00630         Compute the average frame to frame change in orientation while pushing
00631         '''
00632         init_theta = push_trial.trial_start.init_orientation
00633         angle_errs = []
00634         for i, pt in enumerate(push_trial.trial_trajectory):
00635             if i == 0:
00636                 theta_prev = init_theta
00637             else:
00638                 theta_prev = push_trial.trial_trajectory[i-1].x.theta
00639             angle_errs.append(abs(subPIAngle(pt.x.theta - theta_prev)))
00640 
00641         if len(angle_errs) < 1:
00642             return -1
00643         mean_angle_errs = sum(angle_errs)/len(angle_errs)
00644         # print mean_angle_errs, 'rad'
00645 
00646         return mean_angle_errs
00647 
00648     def analyze_straight_line_push_line_dist(self, push_trial):
00649         '''
00650         Get the average distance of the current point to the desired straight line path
00651         '''
00652         init_pose = push_trial.trial_start.init_centroid
00653         goal_pose = push_trial.trial_start.goal_pose
00654         init_loc = (init_pose.x, init_pose.y)
00655         goal_loc = (goal_pose.x, goal_pose.y)
00656 
00657         line_dists = []
00658         for i, pt in enumerate(push_trial.trial_trajectory):
00659             cur_pt = (pt.x.x, pt.x.y)
00660             line_dist = point_line_dist(cur_pt, init_loc, goal_loc)
00661             line_dists.append(line_dist)
00662 
00663         if len(line_dists) < 1:
00664             return -1
00665         mean_line_dist = sum(line_dists)/len(line_dists)
00666         return mean_line_dist
00667 
00668     def analyze_straight_line_push_goal_vector_diff(self, push_trial, normalize_score=False):
00669         '''
00670         Get the average angler error between the instantaneous velocity direction of the object and the
00671         direction towards the goal
00672         '''
00673         init_pose = push_trial.trial_start.init_centroid
00674         goal_pose = push_trial.trial_start.goal_pose
00675         final_pose = push_trial.trial_end.final_centroid
00676         push_trial.trial_trajectory
00677         err_x = goal_pose.x - final_pose.x
00678         err_y = goal_pose.y - final_pose.y
00679         final_error =  hypot(err_x, err_y)
00680         total_change = hypot(final_pose.x - init_pose.x, final_pose.y - init_pose.y)
00681         angle_errs = []
00682         init_goal_vector = np.asarray([goal_pose.x - init_pose.x, goal_pose.y - init_pose.y])
00683         init_final_vector = np.asarray([final_pose.x - init_pose.x, final_pose.y - init_pose.y])
00684         final_angle_diff = self.angle_between_vectors(init_goal_vector, init_final_vector)
00685         final_angle_area = 0.5*fabs(init_goal_vector[0]*init_final_vector[1]-
00686                                     init_goal_vector[1]*init_final_vector[0])
00687         for i, pt in enumerate(push_trial.trial_trajectory):
00688             if i == 0:
00689                 continue
00690             prev_pt = push_trial.trial_trajectory[i-1]
00691             goal_vector = np.asarray([goal_pose.x - prev_pt.x.x, goal_pose.y - prev_pt.x.y])
00692             push_vector = np.asarray([pt.x.x - prev_pt.x.x, pt.x.y - prev_pt.x.y])
00693             if hypot(push_vector[0], push_vector[1]) == 0:
00694                 continue
00695             else:
00696                 angle_errs.append(self.angle_between_vectors(goal_vector, push_vector))
00697         mean_angle_errs = sum(angle_errs)/len(angle_errs)
00698         # print mean_angle_errs, 'rad'
00699         # print final_error, 'cm'
00700         if normalize_score:
00701             score = 1.0-mean_angle_errs/pi
00702         else:
00703             score = mean_angle_errs
00704 
00705         return (score, final_error, total_change, final_angle_diff, final_angle_area)
00706 
00707     def analyze_spin_push_total_spin(self, push_trial):
00708         '''
00709         Get the average change in heading aggregated over the entire trial
00710         '''
00711         init_theta = push_trial.trial_start.init_orientation
00712         goal_theta = push_trial.trial_start.goal_pose.theta
00713 
00714         delta_thetas = []
00715         prev_theta = init_theta
00716         for i, pt in enumerate(push_trial.trial_trajectory):
00717             cur_theta = pt.x.theta
00718             delta_thetas.append(abs(cur_theta-prev_theta))
00719             prev_theta = cur_theta
00720 
00721         if len(delta_thetas) < 1:
00722             return -1
00723         mean_delta_theta = sum(delta_thetas)/len(line_dists)
00724         return mean_delta_theta
00725 
00726     def analyze_spin_push_net_spin(self, push_trial):
00727         init_theta = push_trial.trial_start.init_orientation
00728         final_theta = push_trial.trial_end.final_orientation
00729         return abs(subPIAngle(final_theta - init_theta))
00730 
00731     def analyze_spin_push_net_spin_signed(self, push_trial):
00732         init_theta = push_trial.trial_start.init_orientation
00733         final_theta = push_trial.trial_end.final_orientation
00734         return subPIAngle(final_theta - init_theta)
00735 
00736     def angle_between_vectors(self, a, b):
00737         a_dot_b = sum(a*b)
00738         norm_a = hypot(a[0], a[1])
00739         norm_b = hypot(b[0], b[1])
00740         if norm_a == 0 or norm_b == 0:
00741             # print 'Bad angle, returning max value'
00742             return pi
00743         return acos(a_dot_b/(norm_a*norm_b))
00744 
00745     def show_data_affinity(self):
00746         X = self.X_train[:]
00747         X.extend(self.X_test[:])
00748         Y = self.Y_train[:]
00749         Y.extend(self.Y_test[:])
00750         X_aff = np.zeros((len(X),len(X)))
00751         Y_aff = np.zeros((len(Y),len(Y)))
00752         for r in xrange(len(X)):
00753             for c in range(r, len(X)):
00754                 X_aff[r,c] = sum(np.fabs(np.asarray(X[r]) - np.asarray(X[c])))
00755                 Y_aff[r,c] = fabs(Y[r] - Y[c])
00756                 print '(',r,',',c,'): ', X_aff[r,c], '\t', Y_aff[r,c]
00757         plotter.imshow(X_aff, plotter.cm.gray,interpolation='nearest')
00758         plotter.title('Xaff')
00759         plotter.figure()
00760         plotter.imshow(Y_aff, plotter.cm.gray, interpolation='nearest')
00761         plotter.title('Yaff')
00762         plotter.show()
00763         return X_aff,Y_aff
00764 
00765 class BruteForceKNN:
00766     def __init__(self, data):
00767         self.data = data
00768 
00769     def find_k_neighbors(self, element, k=3, comp_func=None):
00770         if comp_func is None:
00771             comp_func = self.xy_dist
00772         k_closest = []
00773         k_dists = []
00774         for d in self.data:
00775             comp_dist = comp_func(element, d)
00776             inserted = False
00777             for i, close in enumerate(k_closest):
00778                 if comp_dist < close:
00779                     k_closest.insert(d, i)
00780                     k_dists.insert(comp_dist,i)
00781                     inserted = True
00782             if not inserted and len(k_closest) < k:
00783                 k_closest.append(d)
00784                 k_dists.append(comp_dist)
00785             elif len(k_closest) > k:
00786                 k_closest = k_closest[:k]
00787                 k_dists = k_dists[:k]
00788         return (k_closest, k_dists)
00789 
00790     def xy_dist(self, a, b):
00791         return hypot(a.init_centroid.x - b.init_centroid.x,
00792                      a.init_centroid.y - b.init_centroid.y)
00793 
00794 class PushLearningAnalysis:
00795 
00796     def __init__(self):
00797         self.raw_data = None
00798         self.io = PushLearningIO()
00799         self.xy_hash_precision = 20.0 # bins/meter
00800         self.num_angle_bins = 8
00801 
00802     def workspace_span(self, push):
00803         # score_fnc=self.compute_normalized_push_time
00804         score_fnc = self.compute_push_error_xy
00805         # score_fnc = self.compute_change_in_push_error_xy
00806         # Evaluate all push trials
00807         for t in self.all_trials:
00808             t.score = score_fnc(t)
00809         knn = BruteForceKNN(self.all_trials)
00810         neighbors, dists = knn.find_k_neighbors(push)
00811         # TODO: What are the best performing neighbors?
00812 
00813     #
00814     # Methods for computing marginals
00815     #
00816     def workspace_ranking(self):
00817         # likelihood_arg=['behavior_primitive','proxy','controller','which_arm']
00818         # likelihood_arg=['which_arm']
00819         likelihood_arg=['behavior_primitive','proxy','controller']
00820         score_fnc=self.compute_change_in_push_error_xy
00821         score_fnc=self.compute_push_error_xy
00822         workspace_ranks = self.rank_avg_pushes(trial_hash_fnc=self.hash_push_xy_angle,
00823                                                likelihood_arg=likelihood_arg,
00824                                                mean_push_fnc=self.get_mean_workspace_push,
00825                                                score_fnc=score_fnc)
00826         # print "Workspace push rankings:"
00827         for ranks in workspace_ranks:
00828             self.output_push_ranks(ranks,
00829                                    ['init_centroid.x','init_centroid.y','push_angle'],
00830                                    likelihood_arg, n=3)
00831         return workspace_ranks
00832 
00833     def object_ranking(self, use_raw=False, count_successes=True):
00834         '''
00835         Method to find the best performing (on average) behavior_primitive as a function of object_id
00836         '''
00837         cond_arg='object_id'
00838         likelihood_arg=['behavior_primitive','proxy','controller']
00839         # score_fnc=self.compute_normalized_push_time
00840         score_fnc=self.compute_push_error_xy
00841         # score_fnc=self.compute_change_in_push_error_xy
00842         if use_raw:
00843             rankings = self.rank_raw_pushes(trial_grouping_arg=cond_arg,
00844                                             score_fnc=score_fnc)
00845             print "\Raw object behavior rankings:"
00846             for ranks in rankings:
00847                 self.output_push_ranks(ranks, cond_arg, likelihood_arg, n=5)
00848         elif count_successes:
00849             rankings = self.count_successful_pushes(trial_grouping_arg=cond_arg,
00850                                                     likelihood_arg=likelihood_arg,
00851                                                     score_fnc=score_fnc)
00852             print "\Successful counts for affordance-behaviors on different objects:"
00853             total_good = 0
00854             total_attempts = 0
00855             for ranks in rankings:
00856                 num_good, num_attempts = self.output_push_counts(ranks, cond_arg, likelihood_arg, n=50)
00857                 total_good += num_good
00858                 total_attempts += num_attempts
00859             print 'Total good', total_good
00860             print 'Total attempts', total_attempts
00861         else:
00862             rankings = self.rank_avg_pushes(trial_grouping_arg=cond_arg,
00863                                             likelihood_arg=likelihood_arg,
00864                                             score_fnc=score_fnc)
00865             print "\nObject behavior rankings:"
00866             for ranks in rankings:
00867                 self.output_push_ranks(ranks, cond_arg, likelihood_arg, n=1)
00868         return rankings
00869 
00870     def object_proxy_ranking(self):
00871         '''
00872         Method to find the best performing (on average) behavior_primitive as a function of object_id
00873         '''
00874         cond_arg='object_id'
00875         likelihood_arg='proxy'
00876         # score_fnc=self.compute_normalized_push_time
00877         # score_fnc=self.compute_push_error_xy
00878         score_fnc=self.compute_change_in_push_error_xy
00879         rankings = self.rank_avg_pushes(trial_grouping_arg=cond_arg,
00880                                         likelihood_arg=likelihood_arg,
00881                                         score_fnc=score_fnc)
00882         print "\nObject proxy rankings:"
00883         for ranks in rankings:
00884             self.output_push_ranks(ranks, cond_arg, likelihood_arg, n=3)
00885         return rankings
00886 
00887     def angle_ranking(self):
00888         '''
00889         Method to find the best performing (on average) behavior_primitive as a function of push_angle
00890         '''
00891         likelihood_arg=['behavior_primitive','proxy','controller']
00892         angle_ranks = self.rank_avg_pushes(
00893             trial_hash_fnc=self.hash_push_angle, likelihood_arg=likelihood_arg,
00894             mean_push_fnc=self.get_mean_angle_push)
00895         print "Angle push rankings:"
00896         for rank in angle_ranks:
00897             self.output_push_ranks(rank, 'push_angle', likelihood_arg, n=3)
00898         return angle_ranks
00899 
00900     def rank_avg_pushes(self, trial_hash_fnc=None, trial_grouping_arg=None,
00901                         likelihood_arg=None, mean_push_fnc=None,score_fnc=None):
00902         '''
00903         '''
00904         # Compute scores
00905         if score_fnc is None:
00906             score_fnc = self.compute_push_error_xy
00907         for t in self.all_trials:
00908             t.score = score_fnc(t)
00909         # Group objects based on conditional variables
00910         if trial_hash_fnc is not None:
00911             trial_groups = self.group_trials(self.all_trials, hash_function=trial_hash_fnc)
00912         else:
00913             trial_groups = self.group_trials(self.all_trials, trial_grouping_arg)
00914 
00915         # Group multiple trials of same type
00916         mean_groups = []
00917         for i, group_key in enumerate(trial_groups):
00918             trial_group = trial_groups[group_key]
00919             likelihood_arg_dict = self.group_trials(trial_group, likelihood_arg)
00920             # Average errors for each push key
00921             mean_group = []
00922             for arg_key in likelihood_arg_dict:
00923                 if trial_grouping_arg is not None:
00924                     mean_push = self.get_mean_push(likelihood_arg_dict[arg_key],
00925                                                    trial_grouping_arg, likelihood_arg)
00926                 else:
00927                     mean_push = mean_push_fnc(likelihood_arg_dict[arg_key])
00928                 mean_group.append(mean_push)
00929             mean_groups.append(mean_group)
00930 
00931         # Choose best push for each conditional group
00932         ranked_pushes = []
00933         for i, group in enumerate(mean_groups):
00934             group.sort(compare_pushes)
00935             ranked_pushes.append(group)
00936         return ranked_pushes
00937 
00938     def count_successful_pushes(self, trial_hash_fnc=None, trial_grouping_arg=None,
00939                                 likelihood_arg=None, mean_push_fnc=None,score_fnc=None, score_thresh=0.02):
00940         '''
00941         '''
00942         # Compute scores
00943         if score_fnc is None:
00944             score_fnc = self.compute_push_error_xy
00945         for t in self.all_trials:
00946             t.score = score_fnc(t)
00947         # Group objects based on conditional variables
00948         if trial_hash_fnc is not None:
00949             trial_groups = self.group_trials(self.all_trials, hash_function=trial_hash_fnc)
00950         else:
00951             trial_groups = self.group_trials(self.all_trials, trial_grouping_arg)
00952 
00953         # Group multiple trials of same type
00954         count_groups = []
00955         for i, group_key in enumerate(trial_groups):
00956             trial_group = trial_groups[group_key]
00957             likelihood_arg_dict = self.group_trials(trial_group, likelihood_arg)
00958             # Average errors for each push key
00959             count_group = []
00960             for arg_key in likelihood_arg_dict:
00961                 push_count = self.get_count_push(likelihood_arg_dict[arg_key],
00962                                                  trial_grouping_arg, likelihood_arg, score_thresh)
00963                 count_group.append(push_count)
00964             count_groups.append(count_group)
00965 
00966         # Choose best push for each conditional group
00967         ranked_pushes = []
00968         for i, group in enumerate(count_groups):
00969             group.sort(compare_counts)
00970             ranked_pushes.append(group)
00971         return ranked_pushes
00972 
00973     def get_successful_pushes(self, trial_hash_fnc=None, trial_grouping_arg=None,
00974                               likelihood_arg=None, mean_push_fnc=None,score_fnc=None, score_thresh=0.02):
00975         '''
00976         '''
00977         # Compute scores
00978         if score_fnc is None:
00979             score_fnc = self.compute_push_error_xy
00980         for t in self.all_trials:
00981             t.score = score_fnc(t)
00982         # Group objects based on conditional variables
00983         if trial_hash_fnc is not None:
00984             trial_groups = self.group_trials(self.all_trials, hash_function=trial_hash_fnc)
00985         else:
00986             trial_groups = self.group_trials(self.all_trials, trial_grouping_arg)
00987 
00988         # Group multiple trials of same type
00989         count_groups = []
00990         for i, group_key in enumerate(trial_groups):
00991             trial_group = trial_groups[group_key]
00992             likelihood_arg_dict = self.group_trials(trial_group, likelihood_arg)
00993             # Average errors for each push key
00994             count_group = []
00995             for arg_key in likelihood_arg_dict:
00996                 for push in likelihood_arg_dict[arg_key]:
00997                     if push.score < score_thresh:
00998                         count_group.append(push)
00999             count_groups.append(count_group)
01000         return count_groups
01001 
01002     def rank_raw_pushes(self, trial_hash_fnc=None, trial_grouping_arg=None, score_fnc=None):
01003         '''
01004         '''
01005         # Compute scores
01006         if score_fnc is None:
01007             score_fnc = self.compute_push_error_xy
01008         for t in self.all_trials:
01009             t.score = score_fnc(t)
01010         # Group objects based on conditional variables
01011         if trial_hash_fnc is not None:
01012             trial_groups = self.group_trials(self.all_trials, hash_function=trial_hash_fnc)
01013         else:
01014             trial_groups = self.group_trials(self.all_trials, trial_grouping_arg)
01015 
01016         # Group multiple trials of same type
01017         ranked_pushes = []
01018         for i, group_key in enumerate(trial_groups):
01019             trial_group = trial_groups[group_key]
01020             trial_group.sort(compare_pushes)
01021             ranked_pushes.append(trial_group)
01022         return ranked_pushes
01023 
01024     def get_mean_push(self, arg_list, trial_grouping_arg, likelihood_arg):
01025         mean_push = PushTrial()
01026         mean_score, score_var = self.mean_and_variance(arg_list)
01027         mean_push.score = mean_score
01028         mean_push.var = score_var
01029         if type(trial_grouping_arg) is not list:
01030             trial_grouping_arg = [trial_grouping_arg]
01031         if type(likelihood_arg) is not list:
01032             likelihood_arg = [likelihood_arg]
01033         for arg in trial_grouping_arg:
01034             setattr(mean_push,arg, get_attr(arg_list[0],arg))
01035         for arg in likelihood_arg:
01036             setattr(mean_push,arg, get_attr(arg_list[0],arg))
01037         return mean_push
01038 
01039 
01040     def get_count_push(self, pushes, trial_grouping_arg, likelihood_arg, score_thresh):
01041         count_push = PushTrial()
01042         successful_count = 0
01043         for push in pushes:
01044             if push.score < score_thresh:
01045                 successful_count += 1
01046         count_push.successful_count = successful_count
01047         count_push.total_count = len(pushes)
01048         if type(trial_grouping_arg) is not list:
01049             trial_grouping_arg = [trial_grouping_arg]
01050         if type(likelihood_arg) is not list:
01051             likelihood_arg = [likelihood_arg]
01052         for arg in trial_grouping_arg:
01053             setattr(count_push,arg, get_attr(pushes[0],arg))
01054         for arg in likelihood_arg:
01055             setattr(count_push,arg, get_attr(pushes[0],arg))
01056         return count_push
01057 
01058     def get_mean_angle_push(self, arg_list):
01059         mean_push = PushTrial()
01060         mean_score, score_var = self.mean_and_variance(arg_list)
01061         mean_push.score = mean_score
01062         mean_push.var = score_var
01063         mean_push.push_angle = self.hash_angle(arg_list[0].push_angle)
01064         mean_push.behavior_primitive = arg_list[0].behavior_primitive
01065         mean_push.controller = arg_list[0].controller
01066         mean_push.proxy = arg_list[0].proxy
01067         return mean_push
01068 
01069     def get_mean_workspace_push(self, arg_list):
01070         mean_push = PushTrial()
01071         mean_score, score_var = self.mean_and_variance(arg_list)
01072         mean_push.score = mean_score
01073         mean_push.var = score_var
01074         mean_push.init_centroid.x, mean_push.init_centroid.y = self.hash_xy(
01075             arg_list[0].init_centroid.x, arg_list[0].init_centroid.y)
01076         mean_push.push_angle = self.hash_angle(arg_list[0].push_angle)
01077         mean_push.behavior_primitive = arg_list[0].behavior_primitive
01078         mean_push.controller = arg_list[0].controller
01079         mean_push.proxy = arg_list[0].proxy
01080         mean_push.which_arm = arg_list[0].which_arm
01081         return mean_push
01082 
01083     def mean_and_variance(self, pushes):
01084         n = len(pushes)
01085         mean_score = 0
01086         for push in pushes:
01087             mean_score += push.score
01088         mean_score = mean_score / n
01089 
01090         if n <= 1:
01091             return (mean_score, 0)
01092 
01093         var_sum = 0
01094         for push in pushes:
01095             var_sum += push.score**2
01096         score_var = (var_sum-n*mean_score**2)/(n-1)
01097 
01098         return (mean_score, score_var)
01099     #
01100     # Grouping methods
01101     #
01102     def group_trials(self, all_trials, hash_attribute=None, hash_function=None):
01103         group_dict = {}
01104         # Group scored pushes by push angle
01105         for t in all_trials:
01106             if hash_function is not None:
01107                 group_key = hash_function(t)
01108             elif type(hash_attribute) == list and len(hash_attribute) > 1:
01109                 group_key = []
01110                 for attr in hash_attribute:
01111                     group_key.append(get_attr(t,attr))
01112                 group_key = tuple(group_key)
01113             elif type(hash_attribute) == list:
01114                 group_key = get_attr(t, hash_attribute[0])
01115             else:
01116                 group_key = get_attr(t, hash_attribute)
01117             try:
01118                 group_dict[group_key].append(t)
01119             except KeyError:
01120                 group_dict[group_key] = [t]
01121         return group_dict
01122 
01123     def group_trials_by_xy_and_push_angle(self, all_trials):
01124         '''
01125         Method to group all trials by initial table location and push angle
01126         '''
01127         groups = {}
01128         # Group scored pushes by push angle
01129         for t in all_trials:
01130             angle_key = self.hash_angle(t.push_angle)
01131             x_key, y_key = self.hash_xy(t.init_centroid.x, t.init_centroid.y)
01132             group_key = (x_key, y_key, angle_key)
01133             try:
01134                 groups[group_key].append(t)
01135             except KeyError:
01136                 groups[group_key] = [t]
01137         return groups
01138 
01139     def group_trials_by_push_angle(self, all_trials):
01140         '''
01141         Method to group all trials by initial table location and push angle
01142         '''
01143         return self.group_trials(all_trials, hash_function=self.hash_push_angle)
01144 
01145     def group_trials_by_xy(self, all_trials):
01146         '''
01147         Method to group all trials by initial table location and push angle
01148         '''
01149         xy_dict = {}
01150         for t in all_trials:
01151             xy_key = self.hash_xy(t.init_centroid.x, t.init_centroid.y)
01152             # Check if x_key exists
01153             try:
01154                 xy_dict[xy_key].append(t)
01155             except KeyError:
01156                 xy_dict[xy_key] = [t]
01157         return xy_dict
01158     #
01159     # Visualization functions
01160     #
01161     def visualize_push_choices(self, ranks, score_threshold=None, object_id=None):
01162         choices = []
01163         for rank in ranks:
01164             choices.append(rank[0])
01165         # load in image from dropbox folder
01166         disp_img = cv2.imread('/u/thermans/Dropbox/Data/choose_push/use_for_display.png')
01167 
01168         xy_groups = self.group_trials_by_xy(choices)
01169 
01170         for group_key in xy_groups:
01171             disp_img = self.draw_push_choices_on_image(xy_groups[group_key], disp_img,
01172                                                        score_threshold=score_threshold)
01173         cv2.imshow('Chosen pushes', disp_img)
01174         file_name = '/u/thermans/Desktop/push_learn_out'
01175         if object_id is not None:
01176             file_name += '_'+object_id
01177         if score_threshold is not None:
01178             file_name += '_'+str(score_threshold)
01179 
01180         file_name += '.png'
01181         cv2.imwrite(file_name, disp_img)
01182         cv2.waitKey()
01183 
01184     def draw_push_choices_on_image(self, choices, img, score_threshold=None):
01185         # TODO: Double check that this is all correct
01186         # TODO: load in transform and camera parameters from saved info file
01187         K = np.matrix([[525, 0, 319.5, 0.0],
01188                        [0, 525, 239.5, 0.0],
01189                        [0, 0, 1, 0.0]])
01190         tl = np.asarray([-0.0115423, 0.441939, 0.263569])
01191         q = np.asarray([0.693274, -0.685285, 0.157732, 0.157719])
01192         num_downsamples = 0
01193         table_height = -0.3
01194         P_w = np.matrix([[choices[0].init_centroid.x], [choices[0].init_centroid.y],
01195                          [table_height], [1.0]])
01196         # Transform choice location into camera frame
01197         T = (np.matrix(tr.translation_matrix(tl)) *
01198              np.matrix(tr.quaternion_matrix(q)))
01199         P_c = T*P_w
01200         # Transform camera point into image frame
01201         P_i = K*P_c
01202         P_i = P_i / P_i[2]
01203         u = P_i[0]/pow(2,num_downsamples)
01204         v = P_i[1]/pow(2,num_downsamples)
01205 
01206         valid_choices = 0
01207         for c in choices:
01208             if score_threshold is None:
01209                 valid_choices += 1
01210             elif c.score < score_threshold:
01211                 valid_choices += 1
01212         if valid_choices == 0:
01213             return img
01214         # Draw circle for the location
01215         radius = 13
01216         cv2.circle(img, (u,v), 3, [0.0,0.0,0.0],3)
01217         cv2.circle(img, (u,v), 3, [255.0,255.0,255.0], 1)
01218         # Draw Shadows for all angles
01219         for c in choices:
01220             if score_threshold is None:
01221                 pass
01222             elif c.score > score_threshold:
01223                 continue
01224             end_point = (u-sin(c.push_angle)*(radius), v-cos(c.push_angle)*(radius))
01225             color = [0.0, 0.0, 0.0] # Black
01226             #cv2.line(img, (u,v), end_point, color,3)
01227         for c in choices:
01228             if score_threshold is None:
01229                 pass
01230             elif c.score > score_threshold:
01231                 continue
01232             # Choose color by push type
01233             if True or c.which_arm == 'l':
01234                 if c.behavior_primitive == GRIPPER_PUSH:
01235                     color = [255.0, 0.0, 0.0] # Blue
01236                 elif c.behavior_primitive == GRIPPER_SWEEP:
01237                     color = [0.0, 255.0, 0.0] # Green
01238                 elif c.behavior_primitive == OVERHEAD_PUSH:
01239                     color = [0.0, 0.0, 255.0] # Red
01240                 elif c.behavior_primitive == GRIPPER_PULL:
01241                     color = [0.0, 255.0, 255.0] # Yellow
01242                 # color = [0.0, 255.0, 0.0] # Green
01243             else:
01244                 if c.behavior_primitive == GRIPPER_PUSH:
01245                     color = [128.0, 0.0, 128.0] # Magenta
01246                 elif c.behavior_primitive == GRIPPER_SWEEP:
01247                     color = [0.0, 64.0, 129.0] # Brown
01248                 elif c.behavior_primitive == OVERHEAD_PUSH:
01249                     color = [128.0, 128.0, 0.0] # Cyan
01250                 elif c.behavior_primitive == GRIPPER_PULL:
01251                     color = [200.0, 200.0, 200.0] # White
01252                 # color = [0.0, 0.0, 255.0] # Red
01253             # Draw line depicting the angle
01254             end_point = (u-sin(c.push_angle)*(radius), v-cos(c.push_angle)*(radius))
01255             cv2.line(img, (u,v), end_point, color, 2)
01256         return img
01257 
01258     def visualize_angle_push_choices(self, ranks, score_threshold=None):
01259         choices = []
01260         for rank in ranks:
01261             choices.append(rank[0])
01262         # load in image from dropbox folder
01263         disp_img = cv2.imread('/u/thermans/Dropbox/Data/choose_push/use_for_display.png')
01264 
01265         # TODO: Create a single group and display for all (x,y) locs
01266 
01267         for x in x_locs:
01268             for y in y_locs:
01269                 for c in choices:
01270                     c.init_centroid.x = x
01271                     c.init_centroid.y = y
01272                     disp_img = self.draw_push_choices_on_image(choices,
01273                                                                disp_img,
01274                                                                score_threshold=score_threshold)
01275         cv2.imshow('Chosen pushes', disp_img)
01276         cv2.imwrite('/u/thermans/Desktop/push_learn_angle_out.png', disp_img)
01277         cv2.waitKey()
01278 
01279     #
01280     # IO Functions
01281     #
01282     def read_in_push_trials(self, file_name, object_id=None):
01283         self.all_trials = []
01284         object_ids = {}
01285         if object_id is not None:
01286             all_trials = self.io.read_in_data_file(file_name)
01287             for t in all_trials:
01288                 if t.object_id in object_ids:
01289                     pass
01290                 else:
01291                     object_ids[t.object_id] = t.object_id
01292                     print "object_id is:", t.object_id
01293                 if object_id == t.object_id:
01294                     self.all_trials.append(t)
01295         else:
01296             self.all_trials = self.io.read_in_data_file(file_name)
01297 
01298 
01299 
01300     def output_push_choice(self, c, conditional_value, arg_value):
01301         '''
01302         Method takes strings [or lists of strings] of what attributes of PushTrail instance c to display
01303         '''
01304         if type(conditional_value) == list:
01305             conditional_str = ''
01306             for val in conditional_value:
01307                 conditional_str += str(get_attr(c,val))+', '
01308             conditional_str = conditional_str[:-2]
01309         else:
01310             conditional_str = str(get_attr(c,conditional_value))
01311         if type(arg_value) == list:
01312             arg_str = ''
01313             for val in arg_value:
01314                 arg_str += str(get_attr(c,val))+', '
01315             arg_str = arg_str[:-2]
01316         else:
01317             arg_str = str(get_attr(c,arg_value))
01318         print 'Choice for (' +  conditional_str + '): ('+ arg_str+ ') : ' + str(c.score) + ', ' + str(c.var)
01319 
01320     def output_push_ranks(self, ranks, conditional_value, arg_value, n=3):
01321         '''
01322         Method takes strings [or lists of strings] of what attributes of PushTrail instance c to display
01323         '''
01324         if len(ranks) == 0:
01325             return
01326         if type(conditional_value) == list:
01327             conditional_str = ''
01328             for val in conditional_value:
01329                 conditional_str += str(get_attr(ranks[0], val))+', '
01330             conditional_str = conditional_str[:-2]
01331         else:
01332             conditional_str = str(get_attr(ranks[0], conditional_value))
01333         # print 'Ranks for (' +  conditional_str + '):'
01334         for i, c in enumerate(ranks):
01335             if i >= n:
01336                 break
01337             if type(arg_value) == list:
01338                 arg_str = ''
01339                 for val in arg_value:
01340                     arg_str += str(get_attr(c,val))+', '
01341                 arg_str = arg_str[:-2]
01342             else:
01343                 arg_str = str(get_attr(c,arg_value))
01344             # print '\t ('+ arg_str+ ') : ' + str(c.score) + ', ' + str(c.var)
01345 
01346     def output_push_counts(self, ranks, conditional_value, arg_value, n=3):
01347         '''
01348         Method takes strings [or lists of strings] of what attributes of PushTrail instance c to display
01349         '''
01350         total_good = 0
01351         total_attempts = 0
01352         if len(ranks) == 0:
01353             return
01354         if type(conditional_value) == list:
01355             conditional_str = ''
01356             for val in conditional_value:
01357                 conditional_str += str(get_attr(ranks[0], val))+', '
01358             conditional_str = conditional_str[:-2]
01359         else:
01360             conditional_str = str(get_attr(ranks[0], conditional_value))
01361         print conditional_str + ''
01362         for i, c in enumerate(ranks):
01363             if i >= n:
01364                 break
01365             if type(arg_value) == list:
01366                 arg_str = ''
01367                 for val in arg_value:
01368                     arg_str += str(get_attr(c,val))+' & '
01369                 arg_str = arg_str[:-3]
01370             else:
01371                 arg_str = str(get_attr(c,arg_value))
01372             if c.successful_count > 0:
01373                 total_good += c.successful_count
01374                 total_attempts += c.total_count
01375             #     print ' & '+ arg_str+ ' & & ' + str(c.successful_count) + ' & ' + str(c.total_count) + ' \\\\'
01376         # print 'Total good: ', total_good
01377         # print 'Total attempts: ', total_attempts
01378         return total_good, total_attempts
01379     def output_loc_push_choices(self, choices):
01380         print "Loc push choices:"
01381         for c in choices:
01382             self.output_push_choice(c, ['init_centroid.x','init_centroid.y','push_angle'],
01383                                     ['behavior_primitive','controller','proxy'])
01384 
01385     #
01386     # Hashing Functions
01387     #
01388 
01389     def hash_push_angle(self, push):
01390         return self.hash_angle(push.push_angle)
01391 
01392     def hash_push_xy_angle(self, push):
01393         x_prime, y_prime = self.hash_xy(push.init_centroid.x, push.init_centroid.y)
01394         return (x_prime, y_prime, self.hash_angle(push.push_angle))
01395 
01396     def hash_angle(self, theta):
01397         # Group different pushes by push_angle
01398         bin = int((theta + pi)/(2.0*pi)*self.num_angle_bins)
01399         bin = max(min(bin, self.num_angle_bins-1), 0)
01400         return -pi+(2.0*pi)*float(bin)/self.num_angle_bins
01401 
01402     def hash_xy(self, x,y):
01403         # Group different pushes by push_angle
01404         x_prime = (round(x*self.xy_hash_precision)-1)/self.xy_hash_precision
01405         y_prime = (round(y*self.xy_hash_precision)-1)/self.xy_hash_precision
01406         return (x_prime, y_prime)
01407 
01408     #
01409     # Scoring Functions
01410     #
01411 
01412     def compute_push_error_xy(self, push):
01413         err_x = push.goal_pose.x - push.final_centroid.x
01414         err_y = push.goal_pose.y - push.final_centroid.y
01415         return hypot(err_x,err_y)
01416 
01417     def compute_change_in_push_error_xy(self, push):
01418         init_x_error = push.goal_pose.x - push.init_centroid.x
01419         init_y_error = push.goal_pose.y - push.init_centroid.y
01420         final_x_error = push.goal_pose.x - push.final_centroid.x
01421         final_y_error = push.goal_pose.y - push.final_centroid.y
01422 
01423         if push.final_centroid == 0.0 and push.final_centroid.y == 0.0:
01424             print 'Knocked off object'
01425             return 100.0
01426         init_error = hypot(init_x_error, init_y_error)
01427         final_error = hypot(final_x_error, final_y_error)
01428         return final_error / init_error
01429 
01430     def compute_push_error_push_dist_diff(self, push):
01431         desired_x = push.init_centroid.x + cos(push.push_angle)*push.push_dist
01432         desired_y = push.init_centroid.y + sin(push.push_angle)*push.push_dist
01433         d_x = push.final_centroid.x - push.init_centroid.x
01434         d_y = push.final_centroid.y - push.init_centroid.y
01435         actual_dist = sqrt(d_x*d_x + d_y*d_y)
01436         return fabs(actual_dist - push.push_dist)
01437 
01438     def compute_normalized_push_time(self, push):
01439         return push.push_time / push.push_dist
01440 
01441 # Helper functions
01442 def get_attr(instance, attribute):
01443     '''
01444     A wrapper for the builtin python getattr which handles recursive attributes of attributes
01445     '''
01446     attr_list = attribute.split('.')
01447     def get_nested_attr(instance, attr_list):
01448         if len(attr_list) == 1:
01449             return getattr(instance, attr_list[0])
01450         return get_nested_attr(getattr(instance, attr_list[0]), attr_list[1:])
01451     return get_nested_attr(instance, attr_list)
01452 
01453 def compare_pushes(a, b):
01454     if a.score < b.score:
01455         return -1
01456     elif a.score > b.score:
01457         return 1
01458     else:
01459         return 0
01460 
01461 def compare_counts(a, b):
01462     if a.successful_count > b.successful_count:
01463         return -1
01464     elif a.successful_count < b.successful_count:
01465         return 1
01466     else:
01467         return 0
01468 
01469 def plot_controller_results(file_name, spin=False):
01470     # TODO: Plot with dashes and dots for no color distinction
01471     io = ControlAnalysisIO()
01472     controls = io.read_in_data_file(file_name)
01473     XS = [c.x.x for c in controls]
01474     YS = [c.x.y for c in controls]
01475     Thetas = [c.x.y for c in controls]
01476     init_x = XS[0]
01477     init_y = YS[0]
01478     goal_x = controls[0].x_desired.x
01479     goal_y = controls[0].x_desired.y
01480     goal_theta = controls[0].x_desired.theta
01481     plotter.figure()
01482     plotter.plot(XS,YS)
01483     plotter.scatter(XS,YS)
01484     ax = plotter.gca()
01485     print ylim()
01486     print ax.set_xlim(xlim()[1]-(ylim()[1]-ylim()[0]), xlim()[1])
01487     headings = [plotter.Arrow(c.x.x, c.x.y, cos(c.x.theta)*0.01, sin(c.x.theta)*0.01, 0.05, axes=ax) for c in controls]
01488     arrows = [ax.add_patch(h) for h in headings]
01489     init_arrow = plotter.Arrow(controls[0].x.x, controls[0].x.y,
01490                                cos(controls[0].x.theta)*0.01,
01491                                sin(controls[0].x.theta)*0.01, 0.05,
01492                                axes=ax, facecolor='red')
01493     goal_arrow = plotter.Arrow(controls[0].x_desired.x, controls[0].x_desired.y,
01494                                cos(controls[0].x_desired.theta)*0.01,
01495                                sin(controls[0].x_desired.theta)*0.01, 0.05,
01496                                axes=ax, facecolor='green')
01497     ax.add_patch(goal_arrow)
01498     ax.add_patch(init_arrow)
01499     plotter.scatter(init_x, init_y, c='r')
01500     plotter.scatter(goal_x, goal_y, c='g')
01501     plotter.xlabel('x (meters)')
01502     plotter.ylabel('y (meters)')
01503     plotter.title('Tracker Ouput')
01504     plotter.savefig('/home/thermans/sandbox/tracker-output.png')
01505     plotter.figure()
01506     ux = [c.u.linear.x for c in controls]
01507     uy = [c.u.linear.y for c in controls]
01508     if spin:
01509         uy = [c.u.linear.z for c in controls]
01510     plotter.plot(ux)
01511     plotter.plot(uy)
01512     plotter.xlabel('Time')
01513     plotter.ylabel('Velocity (m/s)')
01514     plotter.legend(['u_x', 'u_y'])
01515     plotter.title('Feedback Controller - Input Velocities')
01516     plotter.savefig('/home/thermans/sandbox/feedback-input.png')
01517     plotter.figure()
01518     xdots = [c.x_dot.x for c in controls]
01519     ydots = [c.x_dot.y for c in controls]
01520     plotter.plot(xdots)
01521     plotter.plot(ydots)
01522     plotter.xlabel('Time')
01523     plotter.ylabel('Velocity (m/s)')
01524     plotter.title('Tracker Velocities')
01525     plotter.legend(['x_dot', 'y_dot'])
01526     plotter.savefig('/home/thermans/sandbox/tracker-velocities.png')
01527     plotter.figure()
01528     thetadots = [c.x_dot.theta for c in controls]
01529     plotter.plot(thetadots,c='r')
01530     plotter.xlabel('Time')
01531     plotter.ylabel('Velocity (rad/s)')
01532     plotter.title('Tracker Velocities')
01533     plotter.legend(['theta_dot'])
01534     plotter.savefig('/home/thermans/sandbox/tracker-theta-vel.png')
01535     plotter.figure()
01536     x_err = [c.x_desired.x - c.x.x for c in controls]
01537     y_err = [c.x_desired.y - c.x.y for c in controls]
01538     plotter.plot(x_err)
01539     plotter.plot(y_err)
01540     plotter.xlabel('Time')
01541     plotter.ylabel('Error (meters)')
01542     plotter.title('Position Error')
01543     plotter.legend(['x_err', 'y_err'])
01544     plotter.savefig('/home/thermans/sandbox/pos-err.png')
01545     plotter.figure()
01546     if spin:
01547         theta_err = [c.x_desired.theta - c.x.theta for c in controls]
01548     else:
01549         theta_err = [c.theta0 - c.x.theta for c in controls]
01550     plotter.plot(theta_err, c='r')
01551     plotter.xlabel('Time')
01552     plotter.ylabel('Error (radians)')
01553     if spin:
01554         plotter.title('Error in Orientation')
01555     else:
01556         plotter.title('Heading Deviation from Initial')
01557     plotter.savefig('/home/thermans/sandbox/theta-err.png')
01558     plotter.show()
01559 
01560 def plot_junk():
01561     # plot_controller_results(sys.argv[1])
01562     req_object_id = None
01563     thresh = 1.0
01564     # TODO: Add more options to command line
01565     if len(sys.argv) > 1:
01566         data_path = str(sys.argv[1])
01567     else:
01568         print 'Usage:',sys.argv[0],'input_file [object_id] [distance_thresh]'
01569         quit()
01570     if len(sys.argv) > 2:
01571         req_object_id = str(sys.argv[2])
01572         if req_object_id == "None":
01573             req_object_id = None
01574     if len(sys.argv) > 3:
01575         thresh = float(sys.argv[3])
01576         print "thresh:", thresh
01577 
01578     pla = PushLearningAnalysis()
01579     pla.read_in_push_trials(data_path, req_object_id)
01580 
01581     # TODO: Use command line arguments to choose these
01582     workspace_ranks = pla.workspace_ranking()
01583     pla.visualize_push_choices(workspace_ranks, thresh, object_id=req_object_id)
01584     # angle_ranks = pla.angle_ranking()
01585     # pla.object_ranking()
01586     # pla.object_proxy_ranking()
01587     print 'Num trials: ' + str(len(pla.all_trials))
01588 
01589 def read_example_file(file_name):
01590     data_in = file(file_name, 'r')
01591     lines = [l.split() for l in data_in.readlines()]
01592     data_in.close()
01593     Y = []
01594     X = []
01595     for line in lines:
01596         y = float(line.pop(0))
01597         Y.append(y)
01598         x = []
01599         for pair in line:
01600             idx, val = pair.split(':')
01601             idx = int(idx) - 1
01602             val = float(val)
01603             while len(x) < idx:
01604                 x.append(0)
01605             x.append(val)
01606         X.append(x)
01607     return (X,Y)
01608 
01609 def read_feature_file(file_name):
01610     data_in = file(file_name, 'r')
01611     lines = [l.split() for l in data_in.readlines()]
01612     data_in.close()
01613     X = []
01614     for line in lines:
01615         x = []
01616         for val in line:
01617             x.append(float(val))
01618         X.append(x)
01619     return X
01620 
01621 def write_example_file(file_name, X, Y, normalize=False, debug=False):
01622     data_out = file(file_name, 'w')
01623     # print 'Normalize:', normalize
01624     i = 0
01625     for x,y in zip(X,Y):
01626         i += 1
01627         if debug:
01628             print y, x
01629         if isnan(y):
01630             print 'Skipping writing example: ', i
01631             continue
01632         data_line = str(y)
01633         if normalize:
01634             feature_sum = 0.0
01635             for xi in x:
01636                 feature_sum += xi
01637             for i, xi in enumerate(x):
01638                 if xi > 0:
01639                     data_line += ' ' + str(i+1)+':'+str(sqrt(xi/float(feature_sum)))
01640         else:
01641             for i, xi in enumerate(x):
01642                 if xi > 0:
01643                     data_line += ' ' + str(i+1)+':'+str(xi)
01644         data_line +='\n'
01645         data_out.write(data_line)
01646     data_out.close()
01647     return (X,Y)
01648 
01649 def rewrite_example_file_features(original_file_name, feat_file_name, out_file_name, normalize=False, debug=False):
01650     old_X, Y = read_example_file(original_file_name)
01651     X = read_feature_file(feat_file_name)
01652     write_example_file(out_file_name, X, Y, normalize, debug)
01653 
01654 def extract_shape_features_batch():
01655   base_dir = '/home/thermans/Dropbox/Data/ichr2013-results/icdl_data/'
01656   class_dirs = ['camcorder3', 'food_box3', 'large_brush3', 'small_brush3','soap_box3', 'toothpaste3']
01657   # class_dirs = ['toothpaste3']
01658   # subprocess.Popen(['mkdir', '-p', out_dir], shell=False)
01659   base_dir = '/home/thermans/Dropbox/Data/ichr2013-results/rotate_to_heading_train_and_validate/'
01660   class_dirs = ['camcorder0', 'food_box0', 'large_brush0', 'small_brush0','soap_box0', 'toothpaste0']
01661 
01662   out_dir = base_dir+'examples_line_dist/'
01663   feat_dir = base_dir+'examples_line_dist/'
01664 
01665   for c in class_dirs:
01666       print 'Class:', c
01667       class_dir = base_dir+c+'/'
01668       files = os.listdir(class_dir)
01669       data_file = None
01670       for f in files:
01671           if f.startswith('aff_learn_out'):
01672               data_file = f
01673       if data_file is None:
01674           print 'ERROR: No data file in directory:', c
01675           continue
01676       aff_file = class_dir+data_file
01677       score_file = base_dir+'example_files/'+c+'.txt'
01678       # file_out = out_dir+c[:-1]+'_new_feats_cpp.txt'
01679       file_out = base_dir+'analysis/'+c+'_gt_scores.png'
01680       print '/home/thermans/src/gt-ros-pkg/cpl/tabletop_pushing/bin/extract_shape_features', aff_file, \
01681           class_dir, file_out, score_file
01682       p = subprocess.Popen(['/home/thermans/src/gt-ros-pkg/cpl/tabletop_pushing/bin/extract_shape_features',
01683                             aff_file, class_dir, file_out, score_file], shell=False)
01684       p.wait()
01685 
01686 def read_and_score_raw_files():
01687   # base_dir = '/home/thermans/Dropbox/Data/ichr2013-results/point_push/'
01688   # class_dirs = ['camcorder3', 'food_box3', 'large_brush3', 'small_brush3','soap_box3', 'toothpaste3']
01689   # out_dir = base_dir+'examples_line_dist/'
01690   base_dir = '/home/thermans/Dropbox/Data/ichr2013-results/rotate_to_heading_train_and_validate/'
01691   class_dirs = ['camcorder0', 'food_box0', 'large_brush0', 'small_brush0','soap_box0', 'toothpaste0']
01692   out_dir = base_dir+'example_files/'
01693   use_spin = True
01694   for i, c in enumerate(class_dirs):
01695       in_dir = base_dir+c+'/'
01696       files = os.listdir(in_dir)
01697       file_name = None
01698       for f in files:
01699           if f.startswith('aff_learn_out'):
01700               file_name = f
01701       if file_name is None:
01702           continue
01703       file_in = in_dir+file_name
01704       file_out = out_dir+c+'.txt'
01705       print 'Out file:', file_out
01706       slp = StartLocPerformanceAnalysis()
01707       slp.generate_example_file(file_in, file_out, use_spin=use_spin)
01708 
01709 def compare_predicted_and_observed_push_scores(in_file_name, out_file_name=None, use_spin=False):
01710     slp = StartLocPerformanceAnalysis()
01711     slp.compare_predicted_and_observed_push_scores(in_file_name, out_file_name, use_spin)
01712 
01713 def compute_predicted_and_observed_push_scores(in_file_name, out_file_name=None, use_spin=False):
01714     slp = StartLocPerformanceAnalysis()
01715     slp.compute_observed_push_scores_final_errors(in_file_name, out_file_name, use_spin)
01716 
01717 def analyze_predicted_and_observed_batch():
01718   # base_dir = '/home/thermans/Dropbox/Data/ichr2013-results/hold_out_straight_line_results/'
01719   # class_dirs = ['camcorder1', 'food_box1', 'large_brush1', 'small_brush1','soap_box1', 'toothpaste1']
01720   # base_dir = '/home/thermans/Dropbox/Data/ichr2013-results/rand_straight_line_results/'
01721   base_dir = '/home/thermans/Dropbox/Data/ichr2013-results/rotate_to_heading_rand_results/'
01722   # base_dir = '/home/thermans/Dropbox/Data/ichr2013-results/rotate_to_heading_test_results/'
01723   class_dirs = ['camcorder0', 'food_box0', 'large_brush0', 'small_brush0','soap_box0', 'toothpaste0']
01724   out_dir = base_dir+'analysis/'
01725   use_spin = True
01726 
01727   for c in class_dirs:
01728       in_dir = base_dir+c+'/'
01729       files = os.listdir(in_dir)
01730       file_name = None
01731       for f in files:
01732           if f.startswith('aff_learn_out'):
01733               file_name = f
01734       if file_name is None:
01735           continue
01736       file_in = in_dir+file_name
01737       file_out = out_dir+c+'.txt'
01738       file_out_final_error = out_dir+c+'-final-error.txt'
01739       compare_predicted_and_observed_push_scores(file_in, file_out, use_spin)
01740       compute_predicted_and_observed_push_scores(file_in, file_out_final_error, use_spin)
01741 
01742 def rank_straw_scores(file_path):
01743     straw_file = file(file_path, 'r')
01744     lines = [l.split() for l in straw_file.readlines()]
01745     scores = [float(l[0])*100 for l in lines]
01746     major_dists = [float(l[1]) for l in lines]
01747     minor_dists = [float(l[2]) for l in lines]
01748     min_major_dist = 10000
01749     major_dist_idx = 0
01750     min_minor_dist = 10000
01751     minor_dist_idx = 0
01752     for i in xrange(len(major_dists)):
01753         if major_dists[i] < min_major_dist:
01754             min_major_dist = major_dists[i]
01755             major_dist_idx = i
01756         if minor_dists[i] < min_minor_dist:
01757             min_minor_dist = minor_dists[i]
01758             minor_dist_idx = i
01759     major_score = scores[major_dist_idx]
01760     minor_score = scores[minor_dist_idx]
01761     scores.sort()
01762     print 'Major idx score: ' + str(major_score) + ' is ranked ' + str(scores.index(major_score)+1)
01763     print 'Minor idx score: ' + str(minor_score) + ' is ranked ' + str(scores.index(minor_score)+1)
01764     print 'Scores are: ' + str(scores)
01765 
01766 def rank_straw_scores_batch():
01767   base_dir = '/home/thermans/Dropbox/Data/start_loc_learning/point_push/major_minor_axis_point_data/'
01768   classes = ['camcorder3', 'food_box3', 'large_brush3', 'small_brush3','soap_box3', 'toothpaste3']
01769   for c in classes:
01770       file_path = base_dir + 'straw_scores_' + c + '.txt'
01771       print 'Ranks for: ', c
01772       rank_straw_scores(file_path)
01773       print '\n'
01774 
01775 def convert_robot_attempts_to_example_file(in_file_name, out_file_name):
01776     scores = []
01777     feats = []
01778     loc = []
01779     in_file = file(in_file_name,'r')
01780     raw_lines = in_file.readlines()
01781     in_file.close()
01782     for i, l in enumerate(raw_lines):
01783         line = l.split()
01784         loc.append((float(line[0]), float(line[1])))
01785         scores.append(float(line[2]))
01786         feats.append([float(f) for f in line[3:]])
01787         print i, len(feats[i])
01788     normalize = False
01789     debug = False
01790     return write_example_file(out_file_name, feats, scores, normalize, debug)
01791 
01792 def convert_robot_attempts_file_batch():
01793     pass
01794 
01795 def rank_straw_scores(file_path):
01796     straw_file = file(file_path, 'r')
01797     lines = [l.split() for l in straw_file.readlines()]
01798     scores = [float(l[0])*100 for l in lines]
01799     major_dists = [float(l[1]) for l in lines]
01800     minor_dists = [float(l[2]) for l in lines]
01801     min_major_dist = 10000
01802     major_dist_idx = 0
01803     min_minor_dist = 10000
01804     minor_dist_idx = 0
01805     for i in xrange(len(major_dists)):
01806         if major_dists[i] < min_major_dist:
01807             min_major_dist = major_dists[i]
01808             major_dist_idx = i
01809         if minor_dists[i] < min_minor_dist:
01810             min_minor_dist = minor_dists[i]
01811             minor_dist_idx = i
01812     major_score = scores[major_dist_idx]
01813     minor_score = scores[minor_dist_idx]
01814     scores.sort()
01815     print 'Major idx score: ' + str(major_score) + ' is ranked ' + str(scores.index(major_score)+1)
01816     print 'Minor idx score: ' + str(minor_score) + ' is ranked ' + str(scores.index(minor_score)+1)
01817     print 'Scores are: ' + str(scores)
01818 
01819 def rank_straw_scores_batch():
01820   base_dir = '/home/thermans/Dropbox/Data/start_loc_learning/point_push/major_minor_axis_point_data/'
01821   classes = ['camcorder3', 'food_box3', 'large_brush3', 'small_brush3','soap_box3', 'toothpaste3']
01822   for c in classes:
01823       file_path = base_dir + 'straw_scores_' + c + '.txt'
01824       print 'Ranks for: ', c
01825       rank_straw_scores(file_path)
01826       print '\n'
01827 
01828 if __name__ == '__main__':
01829     analyze_predicted_and_observed_batch()
01830     # read_and_score_raw_files()
01831     # extract_shape_features_batch()
01832     # rank_straw_scores_batch()


tabletop_pushing
Author(s): Tucker Hermans
autogenerated on Wed Nov 27 2013 11:59:44