00001 #include <agile_grasp/handle_search.h>
00002
00003
00004 std::vector<Handle> HandleSearch::findHandles(const std::vector<GraspHypothesis>& hand_list, int min_inliers,
00005 double min_length)
00006 {
00007 double t0 = omp_get_wtime();
00008 std::vector<Handle> handle_list;
00009 std::vector<GraspHypothesis> reduced_hand_list(hand_list);
00010
00011 for (int i = 0; i < hand_list.size(); i++)
00012 {
00013 if (reduced_hand_list[i].getGraspWidth() == -1)
00014 continue;
00015
00016 Eigen::Vector3d iaxis = reduced_hand_list[i].getAxis();
00017 Eigen::Vector3d ipt = reduced_hand_list[i].getGraspBottom();
00018 Eigen::Vector3d inormal = reduced_hand_list[i].getApproach();
00019 std::vector<Eigen::Vector2d> inliers;
00020
00021 for (int j = 0; j < hand_list.size(); j++)
00022 {
00023 if (reduced_hand_list[j].getGraspWidth() == -1)
00024 continue;
00025
00026 Eigen::Vector3d jaxis = reduced_hand_list[j].getAxis();
00027 Eigen::Vector3d jpt = reduced_hand_list[j].getGraspBottom();
00028 Eigen::Vector3d jnormal = reduced_hand_list[j].getApproach();
00029
00030
00031 double dist_from_line = ((Eigen::Matrix3d::Identity(3, 3) - iaxis * iaxis.transpose()) * (jpt - ipt)).norm();
00032 double dist_along_line = iaxis.transpose() * (jpt - ipt);
00033 Eigen::Vector2d angle_axis;
00034 angle_axis << safeAcos(iaxis.transpose() * jaxis), M_PI - safeAcos(iaxis.transpose() * jaxis);
00035 double dist_angle_axis = angle_axis.minCoeff();
00036 double dist_from_normal = safeAcos(inormal.transpose() * jnormal);
00037 if (dist_from_line < 0.01 && dist_angle_axis < 0.34 && dist_from_normal < 0.34)
00038 {
00039 Eigen::Vector2d inlier;
00040 inlier << j, dist_along_line;
00041 inliers.push_back(inlier);
00042 }
00043 }
00044
00045 if (inliers.size() < min_inliers)
00046 continue;
00047
00048
00049 double handle_gap_threshold = 0.02;
00050 std::vector<Eigen::Vector2d> inliers_list(inliers.begin(), inliers.end());
00051 while (!shortenHandle(inliers_list, handle_gap_threshold))
00052 { };
00053
00054 if (inliers_list.size() < min_inliers)
00055 continue;
00056
00057
00058 double min_dist = 10000000;
00059 double max_dist = -10000000;
00060 std::vector<int> in(inliers_list.size());
00061 for (int k = 0; k < inliers_list.size(); k++)
00062 {
00063 in[k] = inliers_list[k](0);
00064
00065 if (inliers_list[k](1) < min_dist)
00066 min_dist = inliers_list[k](1);
00067 if (inliers_list[k](1) > max_dist)
00068 max_dist = inliers_list[k](1);
00069 }
00070
00071
00072 if (max_dist - min_dist > min_length)
00073 {
00074 handle_list.push_back(Handle(hand_list, in));
00075 std::cout << "handle found with " << in.size() << " inliers\n";
00076
00077
00078 for (int k = 0; k < in.size(); k++)
00079 {
00080 reduced_hand_list[in[k]].setGraspWidth(-1);
00081 }
00082 }
00083 }
00084
00085 std::cout << "Handle Search\n";
00086 std::cout << " runtime: " << omp_get_wtime() - t0 << " sec\n";
00087 std::cout << " " << handle_list.size() << " handles found\n";
00088 return handle_list;
00089 }
00090
00091
00092 bool HandleSearch::shortenHandle(std::vector<Eigen::Vector2d> &inliers, double gap_threshold)
00093 {
00094 std::sort(inliers.begin(), inliers.end(), HandleSearch::LastElementComparator());
00095 bool is_done = true;
00096
00097 for (int i = 0; i < inliers.size() - 1; i++)
00098 {
00099 double diff = inliers[i + 1](1) - inliers[i](1);
00100 if (diff > gap_threshold)
00101 {
00102 std::vector<Eigen::Vector2d> out;
00103 if (inliers[i](2) < 0)
00104 {
00105 out.assign(inliers.begin() + i + 1, inliers.end());
00106 is_done = false;
00107 }
00108 else
00109 {
00110 out.assign(inliers.begin(), inliers.begin() + i);
00111 }
00112 inliers = out;
00113 break;
00114 }
00115 }
00116
00117 return is_done;
00118 }
00119
00120 void HandleSearch::plotHandles(const std::vector<Handle>& handle_list, const PointCloud::Ptr& cloud,
00121 std::string str)
00122 {
00123 std::cout << "Drawing " << handle_list.size() << " handles.\n";
00124
00125 double colors[9][3] = { { 0, 0.4470, 0.7410 }, { 0.8500, 0.3250, 0.0980 }, { 0.9290, 0.6940, 0.1250 }, {
00126 0.4940, 0.1840, 0.5560 }, { 0.4660, 0.6740, 0.1880 }, { 0.3010, 0.7450, 0.9330 }, { 0.6350, 0.0780,
00127 0.1840 }, { 0, 0.4470, 0.7410 }, { 0.8500, 0.3250, 0.0980 } };
00128
00129
00130
00131
00132
00133
00134
00135
00136
00137
00138
00139
00140
00141
00142 std::vector<pcl::PointCloud<pcl::PointNormal>::Ptr> clouds;
00143 pcl::PointCloud<pcl::PointNormal>::Ptr handle_cloud(new pcl::PointCloud<pcl::PointNormal>());
00144
00145 for (int i = 0; i < handle_list.size(); i++)
00146 {
00147 pcl::PointNormal p;
00148 p.x = handle_list[i].getHandsCenter()(0);
00149 p.y = handle_list[i].getHandsCenter()(1);
00150 p.z = handle_list[i].getHandsCenter()(2);
00151 p.normal[0] = -handle_list[i].getApproach()(0);
00152 p.normal[1] = -handle_list[i].getApproach()(1);
00153 p.normal[2] = -handle_list[i].getApproach()(2);
00154 handle_cloud->points.push_back(p);
00155
00156 const std::vector<int>& inliers = handle_list[i].getInliers();
00157 const std::vector<GraspHypothesis>& hand_list = handle_list[i].getHandList();
00158 pcl::PointCloud<pcl::PointNormal>::Ptr axis_cloud(new pcl::PointCloud<pcl::PointNormal>);
00159
00160 for (int j = 0; j < inliers.size(); j++)
00161 {
00162 pcl::PointNormal p;
00163 p.x = hand_list[inliers[j]].getGraspSurface()(0);
00164 p.y = hand_list[inliers[j]].getGraspSurface()(1);
00165 p.z = hand_list[inliers[j]].getGraspSurface()(2);
00166 p.normal[0] = -hand_list[inliers[j]].getApproach()(0);
00167 p.normal[1] = -hand_list[inliers[j]].getApproach()(1);
00168 p.normal[2] = -hand_list[inliers[j]].getApproach()(2);
00169 axis_cloud->points.push_back(p);
00170 }
00171 clouds.push_back(axis_cloud);
00172 }
00173
00174 std::string title = "Handles: " + str;
00175 boost::shared_ptr<pcl::visualization::PCLVisualizer> viewer(new pcl::visualization::PCLVisualizer(title));
00176 viewer->setBackgroundColor(1, 1, 1);
00177
00178
00179 viewer->addPointCloud<pcl::PointXYZ>(cloud, "registered point cloud");
00180 viewer->setPointCloudRenderingProperties(pcl::visualization::PCL_VISUALIZER_POINT_SIZE, 1,
00181 "registered point cloud");
00182 viewer->setPointCloudRenderingProperties(pcl::visualization::PCL_VISUALIZER_COLOR, 0.0, 1.0, 0.0,
00183 "registered point cloud");
00184
00185 for (int i = 0; i < clouds.size(); i++)
00186 {
00187 std::string name = "handle_" + boost::lexical_cast<std::string>(i);
00188 int ci = i % 6;
00189
00190 viewer->addPointCloud<pcl::PointNormal>(clouds[i], name);
00191 viewer->setPointCloudRenderingProperties(pcl::visualization::PCL_VISUALIZER_COLOR, colors[ci][0],
00192 colors[ci][1], colors[ci][2], name);
00193 std::string name2 = "approach_" + boost::lexical_cast<std::string>(i);
00194 viewer->addPointCloudNormals<pcl::PointNormal>(clouds[i], 1, 0.04, name2);
00195 viewer->setPointCloudRenderingProperties(pcl::visualization::PCL_VISUALIZER_LINE_WIDTH, 2, name2);
00196 viewer->setPointCloudRenderingProperties(pcl::visualization::PCL_VISUALIZER_COLOR, colors[ci][0],
00197 colors[ci][1], colors[ci][2], name2);
00198 }
00199
00200 viewer->addPointCloud<pcl::PointNormal>(handle_cloud, "handles");
00201 viewer->setPointCloudRenderingProperties(pcl::visualization::PCL_VISUALIZER_COLOR, 0, 0, 0, "handles");
00202 viewer->addPointCloudNormals<pcl::PointNormal>(handle_cloud, 1, 0.08, "approach");
00203 viewer->setPointCloudRenderingProperties(pcl::visualization::PCL_VISUALIZER_LINE_WIDTH, 4, "approach");
00204 viewer->setPointCloudRenderingProperties(pcl::visualization::PCL_VISUALIZER_COLOR, 0, 0, 0, "approach");
00205
00206
00207 viewer->initCameraParameters();
00208 viewer->setPosition(0, 0);
00209 viewer->setSize(640, 480);
00210
00211 while (!viewer->wasStopped())
00212 {
00213 viewer->spinOnce(100);
00214 boost::this_thread::sleep(boost::posix_time::microseconds(100000));
00215 }
00216
00217 viewer->close();
00218
00219
00220
00221
00222
00223
00224
00225
00226
00227 }
00228
00229 double HandleSearch::safeAcos(double x)
00230 {
00231 if (x < -1.0)
00232 x = -1.0;
00233 else if (x > 1.0)
00234 x = 1.0;
00235 return acos(x);
00236 }