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 }