00001 #include <sstream>
00002 #include <iostream>
00003 #include <fstream>
00004 #include <tabletop_pushing/shape_features.h>
00005 #include <ros/ros.h>
00006 #include <pcl16/point_cloud.h>
00007 #include <pcl16/point_types.h>
00008 #include <pcl16/io/pcd_io.h>
00009 #include <pcl16_ros/transforms.h>
00010 #include <pcl16/ros/conversions.h>
00011 #include <pcl16/common/pca.h>
00012 #include <tabletop_pushing/VisFeedbackPushTrackingAction.h>
00013 #include <tabletop_pushing/point_cloud_segmentation.h>
00014 #include <cpl_visual_features/helpers.h>
00015 #include <cpl_visual_features/features/kernels.h>
00016 #include <time.h> 
00017 
00018 
00019 #include <libsvm/svm.h>
00020 
00021 using namespace cpl_visual_features;
00022 using namespace tabletop_pushing;
00023 
00024 typedef tabletop_pushing::VisFeedbackPushTrackingFeedback PushTrackerState;
00025 
00026 #define XY_RES 0.001
00027 
00028 ShapeLocations start_loc_history_;
00029 double start_loc_arc_length_percent_;
00030 int start_loc_push_sample_count_;
00031 XYZPointCloud hull_cloud_;
00032 PushTrackerState cur_state_;
00033 double point_cloud_hist_res_ = 0.01;
00034 inline int objLocToIdx(double val, double min_val, double max_val)
00035 {
00036   return round((val-min_val)/XY_RES);
00037 }
00038 
00039 inline double sqrDistXY(pcl16::PointXYZ a, pcl16::PointXYZ b)
00040 {
00041   const double dx = a.x-b.x;
00042   const double dy = a.y-b.y;
00043   return dx*dx+dy*dy;
00044 }
00045 
00046 pcl16::PointXYZ worldPointInObjectFrame(pcl16::PointXYZ world_pt, PushTrackerState& cur_state)
00047 {
00048   
00049   pcl16::PointXYZ shifted_pt;
00050   shifted_pt.x = world_pt.x - cur_state.x.x;
00051   shifted_pt.y = world_pt.y - cur_state.x.y;
00052   shifted_pt.z = world_pt.z - cur_state.z;
00053   double ct = cos(cur_state.x.theta);
00054   double st = sin(cur_state.x.theta);
00055   
00056   pcl16::PointXYZ obj_pt;
00057   obj_pt.x =  ct*shifted_pt.x + st*shifted_pt.y;
00058   obj_pt.y = -st*shifted_pt.x + ct*shifted_pt.y;
00059   obj_pt.z = shifted_pt.z; 
00060   return obj_pt;
00061 }
00062 
00063 pcl16::PointXYZ objectPointInWorldFrame(pcl16::PointXYZ obj_pt, PushTrackerState& cur_state)
00064 {
00065   
00066   pcl16::PointXYZ rotated_pt;
00067   double ct = cos(cur_state.x.theta);
00068   double st = sin(cur_state.x.theta);
00069   rotated_pt.x = ct*obj_pt.x - st*obj_pt.y;
00070   rotated_pt.y = st*obj_pt.x + ct*obj_pt.y;
00071   rotated_pt.z = obj_pt.z;  
00072   
00073   pcl16::PointXYZ world_pt;
00074   world_pt.x = rotated_pt.x + cur_state.x.x;
00075   world_pt.y = rotated_pt.y + cur_state.x.y;
00076   world_pt.z = rotated_pt.z + cur_state.z;
00077   return world_pt;
00078 }
00079 
00080 static inline double dist(pcl16::PointXYZ a, pcl16::PointXYZ b)
00081 {
00082   const double dx = a.x-b.x;
00083   const double dy = a.y-b.y;
00084   const double dz = a.z-b.z;
00085   return std::sqrt(dx*dx+dy*dy+dz*dz);
00086 }
00087 
00088 static inline double sqrDist(pcl16::PointXYZ a, pcl16::PointXYZ b)
00089 {
00090   const double dx = a.x-b.x;
00091   const double dy = a.y-b.y;
00092   const double dz = a.z-b.z;
00093   return dx*dx+dy*dy+dz*dz;
00094 }
00095 
00096 ShapeLocation chooseFixedGoalPushStartLoc(ProtoObject& cur_obj, PushTrackerState& cur_state, bool new_object,
00097                                           int num_start_loc_pushes_per_sample, int num_start_loc_sample_locs)
00098 {
00099   double hull_alpha = 0.01;
00100   XYZPointCloud hull_cloud = tabletop_pushing::getObjectBoundarySamples(cur_obj, hull_alpha);
00101   hull_cloud_ = hull_cloud;
00102   cur_state_ = cur_state;
00103 
00104   int rot_idx = -1;
00105   if (new_object)
00106   {
00107     
00108     start_loc_arc_length_percent_ = 0.0;
00109     start_loc_push_sample_count_ = 0;
00110     start_loc_history_.clear();
00111 
00112     
00113     
00114     double min_angle_dist = FLT_MAX;
00115     for (int i = 0; i < hull_cloud.size(); ++i)
00116     {
00117       double theta_i = atan2(hull_cloud.at(i).y - cur_state.x.y, hull_cloud.at(i).x - cur_state.x.x);
00118       double angle_dist_i = fabs(subPIAngle(theta_i - cur_state.x.theta));
00119       if (angle_dist_i < min_angle_dist)
00120       {
00121         min_angle_dist = angle_dist_i;
00122         rot_idx = i;
00123       }
00124     }
00125   }
00126   else
00127   {
00128     
00129     if (start_loc_history_.size() % num_start_loc_pushes_per_sample == 0)
00130     {
00131       start_loc_arc_length_percent_ += 1.0/num_start_loc_sample_locs;
00132       
00133     }
00134 
00135     
00136     
00137     pcl16::PointXYZ init_loc_point = objectPointInWorldFrame(start_loc_history_[0].boundary_loc_, cur_state);
00138     
00139 
00140     
00141     double min_dist = FLT_MAX;
00142     for (int i = 0; i < hull_cloud.size(); ++i)
00143     {
00144       double dist_i = sqrDist(init_loc_point, hull_cloud.at(i));
00145       if (dist_i < min_dist)
00146       {
00147         min_dist = dist_i;
00148         rot_idx = i;
00149       }
00150     }
00151   }
00152   
00153   double pt0_theta = atan2(hull_cloud[rot_idx].y - cur_state.x.y, hull_cloud[rot_idx].x - cur_state.x.x);
00154   int pt1_idx = (rot_idx+1) % hull_cloud.size();
00155   double pt1_theta = atan2(hull_cloud[pt1_idx].y - cur_state.x.y, hull_cloud[pt1_idx].x - cur_state.x.x);
00156   bool reverse_data = false;
00157   if (subPIAngle(pt1_theta - pt0_theta) < 0)
00158   {
00159     reverse_data = true;
00160     
00161   }
00162 
00163   
00164   std::vector<double> boundary_dists(hull_cloud.size(), 0.0);
00165   double boundary_length = 0.0;
00166   
00167   for (int i = 1; i <= hull_cloud.size(); ++i)
00168   {
00169     int idx0 = (rot_idx+i-1) % hull_cloud.size();
00170     int idx1 = (rot_idx+i) % hull_cloud.size();
00171     if (reverse_data)
00172     {
00173       idx0 = (hull_cloud.size()+rot_idx-i+1) % hull_cloud.size();
00174       idx1 = (hull_cloud.size()+rot_idx-i) % hull_cloud.size();
00175     }
00176     
00177     boundary_dists[idx0] = boundary_length;
00178     double loc_dist = dist(hull_cloud[idx0], hull_cloud[idx1]);
00179     boundary_length += loc_dist;
00180   }
00181 
00182   
00183   double desired_boundary_dist = start_loc_arc_length_percent_*boundary_length;
00184   
00185   int boundary_loc_idx;
00186   double min_boundary_dist_diff = FLT_MAX;
00187   for (int i = 0; i < hull_cloud.size(); ++i)
00188   {
00189     double boundary_dist_diff_i = fabs(desired_boundary_dist - boundary_dists[i]);
00190     if (boundary_dist_diff_i < min_boundary_dist_diff)
00191     {
00192       min_boundary_dist_diff = boundary_dist_diff_i;
00193       boundary_loc_idx = i;
00194     }
00195   }
00196 
00197   
00198   
00199   double gripper_spread = 0.05;
00200   pcl16::PointXYZ boundary_loc = hull_cloud[boundary_loc_idx];
00201   ShapeDescriptor sd = tabletop_pushing::extractLocalAndGlobalShapeFeatures(hull_cloud, cur_obj,
00202                                                                             boundary_loc, boundary_loc_idx,
00203                                                                             gripper_spread, hull_alpha,
00204                                                                             point_cloud_hist_res_);
00205   
00206   ShapeLocation s_obj(worldPointInObjectFrame(boundary_loc, cur_state), sd);
00207   start_loc_history_.push_back(s_obj);
00208   ShapeLocation s_world(boundary_loc, sd);
00209   return s_world;
00210 }
00211 
00212 ShapeLocation chooseFixedGoalPushStartLoc(ProtoObject& cur_obj, PushTrackerState& cur_state,
00213                                           pcl16::PointXYZ start_pt)
00214 
00215 {
00216   double hull_alpha = 0.01;
00217   XYZPointCloud hull_cloud = tabletop_pushing::getObjectBoundarySamples(cur_obj, hull_alpha);
00218   hull_cloud_ = hull_cloud;
00219   cur_state_ = cur_state;
00220   double min_dist = FLT_MAX;
00221   int min_dist_idx = 0;
00222   for (int i = 0; i < hull_cloud.size(); ++i)
00223   {
00224     double pt_dist = dist(hull_cloud[i], start_pt);
00225     if (pt_dist < min_dist)
00226     {
00227       min_dist = pt_dist;
00228       min_dist_idx = i;
00229     }
00230   }
00231   double gripper_spread = 0.05;
00232   pcl16::PointXYZ boundary_loc = hull_cloud[min_dist_idx];
00233   ShapeDescriptor sd = tabletop_pushing::extractLocalAndGlobalShapeFeatures(hull_cloud, cur_obj,
00234                                                                             boundary_loc, min_dist_idx,
00235                                                                             gripper_spread,
00236                                                                             hull_alpha, point_cloud_hist_res_);
00237   ShapeLocation s_obj(worldPointInObjectFrame(boundary_loc, cur_state), sd);
00238   start_loc_history_.push_back(s_obj);
00239 
00240   ShapeLocation s_world(boundary_loc, sd);
00241   return s_world;
00242 }
00243 
00244 ShapeLocation chooseLearnedPushStartLoc(ProtoObject& cur_obj, PushTrackerState& cur_state, std::string param_path,
00245                                         float& chosen_score)
00246 {
00247   
00248   float hull_alpha = 0.01;
00249   XYZPointCloud hull_cloud = tabletop_pushing::getObjectBoundarySamples(cur_obj, hull_alpha);
00250   float gripper_spread = 0.05;
00251   ShapeDescriptors sds = tabletop_pushing::extractLocalAndGlobalShapeFeatures(hull_cloud, cur_obj,
00252                                                                               gripper_spread, hull_alpha,
00253                                                                               point_cloud_hist_res_);
00254   
00255   
00256   
00257   
00258   
00259   
00260   
00261 
00262   
00263   ROS_INFO_STREAM("reading svm model: " << param_path);
00264   svm_model* push_model;
00265   push_model = svm_load_model(param_path.c_str());
00266   ROS_INFO_STREAM("read svm model: " << param_path);
00267   ROS_INFO_STREAM("svm_parameters.svm_type: " << push_model->param.svm_type);
00268   ROS_INFO_STREAM("svm_parameters.kernel_type: " << push_model->param.kernel_type);
00269   ROS_INFO_STREAM("number SVs: " << push_model->l);
00270 
00271   std::vector<double> pred_push_scores;
00272   chosen_score = FLT_MAX;
00273   int best_idx = -1;
00274   
00275   for (int i = 0; i < sds.size(); ++i)
00276   {
00277     
00278     
00279     svm_node* x = new svm_node[sds[i].size()];
00280     for (int j = 0; j < sds[i].size(); ++j)
00281     {
00282       x[j].index = (j+1); 
00283       x[j].value = sds[i][j];
00284     }
00285     
00286     
00287     double pred_log_score = svm_predict(push_model, x);
00288     double pred_score = exp(pred_log_score);
00289     
00290     
00291     if (pred_score < chosen_score)
00292     {
00293       chosen_score = pred_score;
00294       best_idx = i;
00295     }
00296     pred_push_scores.push_back(pred_score);
00297     delete x;
00298   }
00299   ROS_INFO_STREAM("Chose best push location " << best_idx << " with score " << chosen_score);
00300   ROS_INFO_STREAM("Push location 3D: " << hull_cloud[best_idx]);
00301   
00302   ShapeLocation loc;
00303   if (best_idx >= 0)
00304   {
00305     loc.boundary_loc_ = hull_cloud[best_idx];
00306     loc.descriptor_ = sds[best_idx];
00307   }
00308   return loc;
00309 }
00310 
00311 ShapeDescriptor getTrialDescriptor(std::string cloud_path, pcl16::PointXYZ init_loc, double init_theta, bool new_object)
00312 {
00313   int num_start_loc_pushes_per_sample = 3;
00314   int num_start_loc_sample_locs = 16;
00315 
00316   
00317   ProtoObject cur_obj;
00318   
00319   PushTrackerState cur_state;
00320   cur_state.x.x = init_loc.x;
00321   cur_state.x.y = init_loc.y;
00322   cur_state.x.theta = init_theta;
00323   cur_state.z = init_loc.z;
00324   cur_obj.centroid[0] = cur_state.x.x;
00325   cur_obj.centroid[1] = cur_state.x.y;
00326   cur_obj.centroid[2] = cur_state.z;
00327   ROS_INFO_STREAM("Getting cloud: " << cloud_path);
00328   if (pcl16::io::loadPCDFile<pcl16::PointXYZ> (cloud_path, cur_obj.cloud) == -1) 
00329   {
00330     ROS_ERROR_STREAM("Couldn't read file " << cloud_path);
00331   }
00332   ROS_INFO_STREAM("Got cloud: " << cloud_path);
00333   ShapeLocation sl = chooseFixedGoalPushStartLoc(cur_obj, cur_state, new_object, num_start_loc_pushes_per_sample,
00334                                                  num_start_loc_sample_locs);
00335   return sl.descriptor_;
00336 }
00337 
00338 ShapeDescriptor getTrialDescriptor(std::string cloud_path, pcl16::PointXYZ init_loc, double init_theta,
00339                                    pcl16::PointXYZ start_pt)
00340 {
00341   int num_start_loc_pushes_per_sample = 3;
00342   int num_start_loc_sample_locs = 16;
00343 
00344   
00345   ProtoObject cur_obj;
00346   
00347   PushTrackerState cur_state;
00348   cur_state.x.x = init_loc.x;
00349   cur_state.x.y = init_loc.y;
00350   cur_state.x.theta = init_theta;
00351   cur_state.z = init_loc.z;
00352   cur_obj.centroid[0] = cur_state.x.x;
00353   cur_obj.centroid[1] = cur_state.x.y;
00354   cur_obj.centroid[2] = cur_state.z;
00355   ROS_INFO_STREAM("Getting cloud: " << cloud_path);
00356   if (pcl16::io::loadPCDFile<pcl16::PointXYZ> (cloud_path, cur_obj.cloud) == -1) 
00357   {
00358     ROS_ERROR_STREAM("Couldn't read file " << cloud_path);
00359   }
00360   ROS_INFO_STREAM("Got cloud: " << cloud_path);
00361   ShapeLocation sl = chooseFixedGoalPushStartLoc(cur_obj, cur_state, start_pt);
00362   return sl.descriptor_;
00363 }
00364 
00365 ShapeLocation predictPushLocation(std::string cloud_path, pcl16::PointXYZ init_loc, double init_theta,
00366                                   pcl16::PointXYZ start_pt, std::string param_path)
00367 {
00368   int num_start_loc_pushes_per_sample = 3;
00369   int num_start_loc_sample_locs = 16;
00370 
00371   
00372   ProtoObject cur_obj;
00373   
00374   PushTrackerState cur_state;
00375   cur_state.x.x = init_loc.x;
00376   cur_state.x.y = init_loc.y;
00377   cur_state.x.theta = init_theta;
00378   cur_state.z = init_loc.z;
00379   cur_obj.centroid[0] = cur_state.x.x;
00380   cur_obj.centroid[1] = cur_state.x.y;
00381   cur_obj.centroid[2] = cur_state.z;
00382   ROS_INFO_STREAM("Getting cloud: " << cloud_path);
00383   if (pcl16::io::loadPCDFile<pcl16::PointXYZ> (cloud_path, cur_obj.cloud) == -1) 
00384   {
00385     ROS_ERROR_STREAM("Couldn't read file " << cloud_path);
00386   }
00387   ROS_INFO_STREAM("Got cloud: " << cloud_path);
00388   float chosen_score;
00389   ShapeLocation sl = chooseLearnedPushStartLoc(cur_obj, cur_state, param_path, chosen_score);
00390   return sl;
00391 }
00392 
00393 class TrialStuff
00394 {
00395  public:
00396   TrialStuff(double init_x_, double init_y_, double init_z_, double init_theta_, std::string trial_id_, bool new_object_,
00397              double push_x_, double push_y_, double push_z_) :
00398       init_loc(init_x_, init_y_, init_z_), init_theta(init_theta_), trial_id(trial_id_), new_object(new_object_),
00399       start_pt(push_x_, push_y_, push_z_)
00400   {
00401   }
00402   pcl16::PointXYZ init_loc;
00403   double init_theta;
00404   std::string trial_id;
00405   bool new_object;
00406   pcl16::PointXYZ start_pt;
00407 };
00408 
00409 std::vector<TrialStuff> getTrialsFromFile(std::string aff_file_name)
00410 {
00411   std::vector<TrialStuff> trials;
00412   std::ifstream trials_in(aff_file_name.c_str());
00413 
00414   bool next_line_trial = false;
00415   bool trial_is_start = true;
00416   int line_count = 0;
00417   int object_comment = 0;
00418   int trial_starts = 0;
00419   int bad_stops = 0;
00420   int good_stops = 0;
00421   int control_headers = 0;
00422   bool new_object = true;
00423   while(trials_in.good())
00424   {
00425     char c_line[4096];
00426     trials_in.getline(c_line, 4096);
00427     line_count++;
00428     if (next_line_trial)
00429     {
00430       
00431       next_line_trial = false;
00432 
00433       
00434       std::stringstream trial_line;
00435       trial_line << c_line;
00436       char trial_id_c[4096];
00437       trial_line.getline(trial_id_c, 4096, ' ');
00438       std::stringstream trial_id;
00439       trial_id << trial_id_c;
00440       
00441       double init_x, init_y, init_z, init_theta;
00442       trial_line >> init_x >> init_y >> init_z >> init_theta;
00443       double final_x, final_y, final_z, final_theta;
00444       trial_line >> final_x >> final_y >> final_z >> final_theta;
00445       double goal_x, goal_y, goal_theta;
00446       trial_line >> goal_x >> goal_y >> goal_theta;
00447       double push_start_x, push_start_y, push_start_z, push_start_theta;
00448       trial_line >> push_start_x >> push_start_y >> push_start_z;
00449 
00450       
00451       
00452       new_object = !trials.size();
00453       TrialStuff trial(init_x, init_y, init_z, init_theta, trial_id.str(), new_object,
00454                        push_start_x, push_start_y, push_start_z);
00455       trials.push_back(trial);
00456     }
00457     if (c_line[0] == '#')
00458     {
00459       if (c_line[2] == 'o')
00460       {
00461         object_comment++;
00462         if (trial_is_start)
00463         {
00464           next_line_trial = true;
00465           trial_starts += 1;
00466           
00467         }
00468         else
00469         {
00470           
00471           good_stops++;
00472         }
00473         
00474         trial_is_start = !trial_is_start;
00475       }
00476       else if (c_line[2] == 'x')
00477       {
00478         control_headers += 1;
00479       }
00480       else if (c_line[1] == 'B')
00481       {
00482         
00483         trial_is_start = true;
00484         trials.pop_back();
00485         bad_stops += 1;
00486       }
00487     }
00488   }
00489   trials_in.close();
00490 
00491   ROS_INFO_STREAM("Read in: " << line_count << " lines");
00492   ROS_INFO_STREAM("Read in: " << control_headers << " control headers");
00493   ROS_INFO_STREAM("Read in: " << object_comment << " trial headers");
00494   ROS_INFO_STREAM("Classified: " << trial_starts << " as starts");
00495   ROS_INFO_STREAM("Classified: " << bad_stops << " as bad");
00496   ROS_INFO_STREAM("Classified: " << good_stops << " as good");
00497   ROS_INFO_STREAM("Read in: " << trials.size() << " trials");
00498   return trials;
00499 }
00500 
00501 void writeNewFile(std::string out_file_name, std::vector<TrialStuff> trials, ShapeDescriptors descriptors)
00502 {
00503   std::ofstream out_file(out_file_name.c_str());
00504   for (unsigned int i = 0; i < descriptors.size(); ++i)
00505   {
00506     for (unsigned int j = 0; j < descriptors[i].size(); ++j)
00507     {
00508       out_file << descriptors[i][j] << " ";
00509     }
00510     out_file << "\n";
00511   }
00512   out_file.close();
00513 }
00514 
00515 void writeNewExampleFile(std::string out_file_name, std::vector<TrialStuff> trials, ShapeDescriptors descriptors,
00516                          std::vector<double>& push_scores)
00517 {
00518   ROS_INFO_STREAM("Writing example file: " << out_file_name);
00519   std::ofstream out_file(out_file_name.c_str());
00520   for (unsigned int i = 0; i < descriptors.size(); ++i)
00521   {
00522     out_file << push_scores[i] << " ";
00523     for (unsigned int j = 0; j < descriptors[i].size(); ++j)
00524     {
00525       if (descriptors[i][j] != 0.0)
00526       {
00527         out_file << (j+1) << ":" << descriptors[i][j] << " ";
00528       }
00529     }
00530     out_file << "\n";
00531   }
00532   out_file.close();
00533 }
00534 
00535 std::vector<double> readScoreFile(std::string file_path)
00536 {
00537   std::ifstream data_in(file_path.c_str());
00538   std::vector<double> scores;
00539   while (data_in.good())
00540   {
00541     char c_line[4096];
00542     data_in.getline(c_line, 4096);
00543     std::stringstream line;
00544     line << c_line;
00545     double y;
00546     line >> y;
00547     if (!data_in.eof())
00548     {
00549       scores.push_back(y);
00550     }
00551   }
00552   data_in.close();
00553   return scores;
00554 }
00555 
00556 void drawScores(std::vector<double>& push_scores, std::string out_file_path)
00557 {
00558   double max_y = 0.3;
00559   double min_y = -0.3;
00560   double max_x = 0.3;
00561   double min_x = -0.3;
00562   int rows = ceil((max_y-min_y)/XY_RES);
00563   int cols = ceil((max_x-min_x)/XY_RES);
00564   cv::Mat footprint(rows, cols, CV_8UC3, cv::Scalar(255,255,255));
00565 
00566   for (int i = 0; i < hull_cloud_.size(); ++i)
00567   {
00568     pcl16::PointXYZ obj_pt =  worldPointInObjectFrame(hull_cloud_[i], cur_state_);
00569     int img_x = objLocToIdx(obj_pt.x, min_x, max_x);
00570     int img_y = objLocToIdx(obj_pt.y, min_y, max_y);
00571     cv::Scalar color(128, 0, 0);
00572     cv::circle(footprint, cv::Point(img_x, img_y), 1, color, 3);
00573   }
00574   
00575   double max_score = 0.0602445;
00576   for (int i = 0; i < start_loc_history_.size(); ++i)
00577   {
00578     int x = objLocToIdx(start_loc_history_[i].boundary_loc_.x, min_x, max_x);
00579     int y = objLocToIdx(start_loc_history_[i].boundary_loc_.y, min_y, max_y);
00580     
00581     double score = push_scores[i]/M_PI;
00582     ROS_INFO_STREAM("Score " << score);
00583     cv::Scalar color(0, score*255, (1-score)*255);
00584     
00585     
00586     
00587     
00588     cv::circle(footprint, cv::Point(x,y), 1, color, 3);
00589     cv::circle(footprint, cv::Point(x,y), 2, color, 3);
00590     cv::circle(footprint, cv::Point(x,y), 3, color, 3);
00591   }
00592   
00593   ROS_INFO_STREAM("Writing image: " << out_file_path);
00594   cv::imwrite(out_file_path, footprint);
00595 
00596   cv::imshow("Push score", footprint);
00597   cv::waitKey();
00598 }
00599 
00600 pcl16::PointXYZ pointClosestToAngle(double major_angle, XYZPointCloud& hull_cloud, Eigen::Vector4f centroid)
00601 {
00602   pcl16::PointXYZ closest;
00603   double min_angle_dist = FLT_MAX;
00604   for (int i = 0; i < hull_cloud.size(); ++i)
00605   {
00606     double angle_dist = fabs(major_angle - atan2(hull_cloud[i].y - centroid[1], hull_cloud[i].x - centroid[0]));
00607     if (angle_dist < min_angle_dist)
00608     {
00609       closest = hull_cloud[i];
00610       min_angle_dist = angle_dist;
00611     }
00612   }
00613   ROS_INFO_STREAM("Closest point " << closest << " at angle dist " << min_angle_dist);
00614   return closest;
00615 }
00616 
00617 void getMajorMinorBoundaryDists(std::string cloud_path, pcl16::PointXYZ init_loc, pcl16::PointXYZ start_pt,
00618                                 double& major_dist, double& minor_dist)
00619 {
00620   ProtoObject cur_obj;
00621   cur_obj.centroid[0] = init_loc.x;
00622   cur_obj.centroid[1] = init_loc.y;
00623   cur_obj.centroid[2] = init_loc.z;
00624   ROS_INFO_STREAM("Getting cloud: " << cloud_path);
00625   if (pcl16::io::loadPCDFile<pcl16::PointXYZ> (cloud_path, cur_obj.cloud) == -1) 
00626   {
00627     ROS_ERROR_STREAM("Couldn't read file " << cloud_path);
00628   }
00629   ROS_INFO_STREAM("Got cloud: " << cloud_path);
00630 
00631   float hull_alpha = 0.01;
00632   XYZPointCloud hull_cloud = tabletop_pushing::getObjectBoundarySamples(cur_obj, hull_alpha);
00633   hull_cloud_ = hull_cloud;
00634   double min_dist = FLT_MAX;
00635   int min_dist_idx = 0;
00636   for (int i = 0; i < hull_cloud.size(); ++i)
00637   {
00638     double pt_dist = dist(hull_cloud[i], start_pt);
00639     if (pt_dist < min_dist)
00640     {
00641       min_dist = pt_dist;
00642       min_dist_idx = i;
00643     }
00644   }
00645   float gripper_spread = 0.05;
00646   pcl16::PointXYZ boundary_loc = hull_cloud[min_dist_idx];
00647 
00648   
00649   pcl16::PCA<pcl16::PointXYZ> pca;
00650   pca.setInputCloud(hull_cloud.makeShared());
00651   Eigen::Vector3f eigen_values = pca.getEigenValues();
00652   Eigen::Matrix3f eigen_vectors = pca.getEigenVectors();
00653   Eigen::Vector4f centroid = pca.getMean();
00654   double minor_angle = atan2(eigen_vectors(1,0), eigen_vectors(0,0));
00655   double major_angle = minor_angle-0.5*M_PI;
00656 
00657   
00658   pcl16::PointXYZ a = pointClosestToAngle(major_angle, hull_cloud, centroid);
00659   pcl16::PointXYZ b = pointClosestToAngle(subPIAngle(major_angle+M_PI), hull_cloud, centroid);
00660   major_dist = std::min(sqrDistXY(boundary_loc, a), sqrDistXY(boundary_loc, b));
00661   
00662   pcl16::PointXYZ c  = pointClosestToAngle(minor_angle, hull_cloud, centroid);
00663   pcl16::PointXYZ d = pointClosestToAngle(subPIAngle(minor_angle+M_PI), hull_cloud, centroid);
00664   minor_dist = std::min(sqrDistXY(boundary_loc, c), sqrDistXY(boundary_loc, d));
00665 }
00666 
00667 int main(int argc, char** argv)
00668 {
00669   int seed = time(NULL);
00670   srand(seed);
00671 
00672   std::string aff_file_path(argv[1]);
00673   std::string data_directory_path(argv[2]);
00674   std::string out_file_path(argv[3]);
00675   std::vector<TrialStuff> trials = getTrialsFromFile(aff_file_path);
00676   std::string score_file = "";
00677   bool draw_scores = argc > 4;
00678   ROS_INFO_STREAM("trials.size(): " << trials.size());
00679   std::vector<double> push_scores;
00680   if (draw_scores)
00681   {
00682     score_file = argv[4];
00683     push_scores = readScoreFile(score_file);
00684     ROS_INFO_STREAM("scores.size(): " << push_scores.size());
00685   }
00686 
00687   bool test_straw_man = false;
00688   std::ofstream straw_scores_stream("/home/thermans/Desktop/straw_scores.txt");
00689   double max_score = -100.0;
00690   ShapeDescriptors descriptors;
00691   for (unsigned int i = 0; i < trials.size(); ++i)
00692   {
00693     std::string trial_id = trials[i].trial_id;
00694     pcl16::PointXYZ init_loc = trials[i].init_loc;
00695     double init_theta = trials[i].init_theta;
00696     bool new_object = trials[i].new_object;
00697     ROS_INFO_STREAM("trial_id: " << trial_id);
00698     ROS_INFO_STREAM("init_loc: " << init_loc);
00699     ROS_INFO_STREAM("init_theta: " << init_theta);
00700     ROS_INFO_STREAM("new object: " << new_object);
00701     ROS_INFO_STREAM("start_pt: " << trials[i].start_pt);
00702     std::stringstream cloud_path;
00703     cloud_path << data_directory_path << trial_id << "_obj_cloud.pcd";
00704 
00705     ShapeDescriptor sd = getTrialDescriptor(cloud_path.str(), init_loc, init_theta, trials[i].start_pt);
00706     
00707     
00708 
00709     
00710     
00711     
00712     
00713     
00714     
00715     
00716     
00717     
00718     
00719     
00720     
00721     
00722     
00723     
00724     
00725     
00726     
00727     
00728     
00729     
00730     
00731     
00732     
00733     
00734     
00735     
00736 
00737     
00738     
00739     
00740     
00741     
00742     
00743     
00744     
00745     
00746     
00747     descriptors.push_back(sd);
00748   }
00749   
00750   
00751   
00752   
00753   
00754   
00755   
00756   
00757   
00758   
00759   
00760   
00761   
00762   
00763   
00764   
00765   
00766   
00767   
00768   
00769   
00770   
00771   
00772   
00773   
00774   
00775   
00776   
00777   
00778   
00779   
00780   
00781   
00782   
00783   
00784   
00785   
00786   
00787   
00788   
00789   
00790   
00791   
00792   
00793   
00794   
00795   
00796   
00797   
00798   
00799   
00800   
00801   
00802   
00803   
00804   
00805   
00806   
00807   
00808   
00809   
00810   
00811   
00812 
00813     
00814     
00815     
00816     
00817     
00818     
00819     
00820 
00821   
00822   
00823   if (draw_scores)
00824   {
00825     
00826     drawScores(push_scores, out_file_path);
00827     
00828   }
00829   return 0;
00830 }