Go to the documentation of this file.00001 #include <string>
00002 #include <sstream>
00003 #include <iostream>
00004 #include <fstream>
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/surface/concave_hull.h>
00010 #include <tabletop_pushing/shape_features.h>
00011 #include <tabletop_pushing/point_cloud_segmentation.h>
00012 #include <tabletop_pushing/VisFeedbackPushTrackingAction.h>
00013
00014 #include <pcl16/common/pca.h>
00015
00016
00017 #include <cpl_visual_features/helpers.h>
00018
00019 typedef tabletop_pushing::VisFeedbackPushTrackingFeedback PushTrackerState;
00020 using cpl_visual_features::subPIAngle;
00021 using namespace tabletop_pushing;
00022
00023
00024 double getThetaFromEllipse(cv::RotatedRect& obj_ellipse)
00025 {
00026 return subPIAngle(DEG2RAD(obj_ellipse.angle)+0.5*M_PI);
00027 }
00028
00029 void fitHullEllipse(XYZPointCloud& hull_cloud, cv::RotatedRect& obj_ellipse)
00030 {
00031 Eigen::Vector3f eigen_values;
00032 Eigen::Matrix3f eigen_vectors;
00033 Eigen::Vector4f centroid;
00034
00035
00036
00037 centroid = Eigen::Vector4f::Zero();
00038
00039 pcl16::compute3DCentroid(hull_cloud, centroid);
00040
00041 Eigen::MatrixXf cloud_demean;
00042
00043 pcl16::demeanPointCloud(hull_cloud, centroid, cloud_demean);
00044
00045
00046
00047 Eigen::Matrix3f alpha = static_cast<Eigen::Matrix3f> (cloud_demean.topRows<3> () * cloud_demean.topRows<3> ().transpose ());
00048
00049
00050
00051 Eigen::SelfAdjointEigenSolver<Eigen::Matrix3f> evd (alpha);
00052
00053 for (int i = 0; i < 3; ++i)
00054 {
00055 eigen_values[i] = evd.eigenvalues()[2-i];
00056 eigen_vectors.col(i) = evd.eigenvectors().col(2-i);
00057 }
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067
00068
00069
00070
00071
00072
00073 obj_ellipse.center.x = centroid[0];
00074 obj_ellipse.center.y = centroid[1];
00075 obj_ellipse.angle = RAD2DEG(atan2(eigen_vectors(1,0), eigen_vectors(0,0))-0.5*M_PI);
00076
00077 obj_ellipse.size.height = std::max(eigen_values(0)*0.1, 0.07);
00078 obj_ellipse.size.width = std::max(eigen_values(1)*0.1, 0.03);
00079
00080 }
00081
00082 XYZPointCloud getHullFromPCDFile(std::string cloud_path)
00083 {
00084 XYZPointCloud cloud;
00085 if (pcl16::io::loadPCDFile<pcl16::PointXYZ>(cloud_path, cloud) == -1)
00086 {
00087 ROS_ERROR_STREAM("Couldn't read file " << cloud_path);
00088 }
00089
00090 XYZPointCloud hull_cloud;
00091 float hull_alpha = 0.01;
00092 pcl16::ConcaveHull<pcl16::PointXYZ> hull;
00093 hull.setDimension(2);
00094 hull.setInputCloud(cloud.makeShared());
00095 hull.setAlpha(hull_alpha);
00096 hull.reconstruct(hull_cloud);
00097
00098 return hull_cloud;
00099 }
00100
00101 float compareObjectHullShapes(XYZPointCloud& hull_cloud_a,XYZPointCloud& hull_cloud_b)
00102 {
00103
00104 double match_cost;
00105 cpl_visual_features::Path matches = compareBoundaryShapes(hull_cloud_a, hull_cloud_b, match_cost);
00106
00107
00108 PushTrackerState state;
00109 cv::RotatedRect obj_ellipse;
00110 fitHullEllipse(hull_cloud_a, obj_ellipse);
00111 state.x.theta = getThetaFromEllipse(obj_ellipse);
00112
00113 state.x.x = obj_ellipse.center.x;
00114 state.x.y = obj_ellipse.center.y;
00115 cv::Mat match_img = visualizeObjectBoundaryMatches(hull_cloud_a, hull_cloud_b, state, matches);
00116 cv::imshow("Object boundary matches", match_img);
00117 cv::waitKey(3);
00118 return match_cost;
00119 }
00120
00121 int main(int argc, char** argv)
00122 {
00123
00124 if (argc != 5)
00125 {
00126 ROS_INFO_STREAM("usage: " << argv[0] << " cloud_a_path cloud_b_path");
00127 return -1;
00128 }
00129
00130 std::string cloud_a_base_path(argv[1]);
00131 std::string cloud_b_base_path(argv[2]);
00132 int num_a = atoi(argv[3]);
00133 int num_b = atoi(argv[4]);
00134 std::vector<std::vector<float> > match_scores;
00135 float score_sum = 0;
00136 for (int a = 0; a < num_a; ++a)
00137 {
00138 std::stringstream cloud_a_path;
00139 cloud_a_path << cloud_a_base_path << a << ".pcd";
00140
00141 XYZPointCloud hull_cloud_a = getHullFromPCDFile(cloud_a_path.str());
00142 std::vector<float> scores_b;
00143 float score_sum_b = 0;
00144 for (int b = 0; b < num_b; ++b)
00145 {
00146 std::stringstream cloud_b_path;
00147 cloud_b_path << cloud_b_base_path << b << ".pcd";
00148 XYZPointCloud hull_cloud_b = getHullFromPCDFile(cloud_b_path.str());
00149 float match_score = compareObjectHullShapes(hull_cloud_a, hull_cloud_b);
00150 scores_b.push_back(match_score);
00151 score_sum += match_score;
00152 score_sum_b += match_score;
00153 }
00154 match_scores.push_back(scores_b);
00155 ROS_INFO_STREAM("Mean score: " << score_sum_b/num_b);
00156 }
00157 ROS_INFO_STREAM("Overall mean score: " << score_sum/(num_b*num_a));
00158
00159 return 0;
00160 }