CloudPtr get () { //lock while we swap our cloud and reset it. boost::mutex::scoped_lock lock (mtx_); CloudPtr temp_cloud (new Cloud); CloudPtr temp_cloud2 (new Cloud); CloudPtr temp_cloud3 (new Cloud); CloudPtr temp_cloud4 (new Cloud); CloudPtr temp_cloud5 (new Cloud); CloudConstPtr empty_cloud; cout << "===============================\n" "======Start of frame===========\n" "===============================\n"; //cerr << "cloud size orig: " << cloud_->size() << endl; voxel_grid.setInputCloud (cloud_); voxel_grid.filter (*temp_cloud); // filter cloud for z depth //cerr << "cloud size postzfilter: " << temp_cloud->size() << endl; pcl::ModelCoefficients::Ptr planecoefficients (new pcl::ModelCoefficients ()); pcl::PointIndices::Ptr plane_inliers (new pcl::PointIndices ()); std::vector<pcl::ModelCoefficients> linecoefficients1; pcl::ModelCoefficients model; model.values.resize (6); pcl::PointIndices::Ptr line_inliers (new pcl::PointIndices ()); std::vector<Eigen::Vector3f> corners; if(temp_cloud->size() > MIN_CLOUD_POINTS) { plane_seg.setInputCloud (temp_cloud); plane_seg.segment (*plane_inliers, *planecoefficients); // find plane } //cerr << "plane inliers size: " << plane_inliers->indices.size() << endl; cout << "planecoeffs: " << planecoefficients->values[0] << " " << planecoefficients->values[1] << " " << planecoefficients->values[2] << " " << planecoefficients->values[3] << " " << endl; Eigen::Vector3f pn = Eigen::Vector3f( planecoefficients->values[0], planecoefficients->values[1], planecoefficients->values[2]); float planedeg = pcl::rad2deg(acos(pn.dot(Eigen::Vector3f::UnitZ()))); cout << "angle of camera to floor normal: " << planedeg << " degrees" << endl; cout << "distance of camera to floor: " << planecoefficients->values[3] << " meters" << endl; plane_extract.setNegative (true); plane_extract.setInputCloud (temp_cloud); plane_extract.setIndices (plane_inliers); plane_extract.filter (*temp_cloud2); // remove plane plane_extract.setNegative (false); plane_extract.filter (*temp_cloud5); // only plane for(size_t i = 0; i < temp_cloud5->size (); ++i) { temp_cloud5->points[i].r = 0; temp_cloud5->points[i].g = 255; temp_cloud5->points[i].b = 0; // tint found plane green for ground } for(size_t j = 0 ; j < MAX_LINES && temp_cloud2->size() > MIN_CLOUD_POINTS; j++) // look for x lines until cloud gets too small { // cerr << "cloud size: " << temp_cloud2->size() << endl; line_seg.setInputCloud (temp_cloud2); line_seg.segment (*line_inliers, model); // find line // cerr << "line inliears size: " << line_inliers->indices.size() << endl; if(line_inliers->indices.size() < MIN_CLOUD_POINTS) break; linecoefficients1.push_back (model); // store line coeffs line_extract.setNegative (true); line_extract.setInputCloud (temp_cloud2); line_extract.setIndices (line_inliers); line_extract.filter (*temp_cloud3); // remove plane line_extract.setNegative (false); line_extract.filter (*temp_cloud4); // only plane for(size_t i = 0; i < temp_cloud4->size (); ++i) { temp_cloud4->points[i].g = 0; if(j%2) { temp_cloud4->points[i].r = 255-j*int(255/MAX_LINES); temp_cloud4->points[i].b = 0+j*int(255/MAX_LINES); } else { temp_cloud4->points[i].b = 255-j*int(255/MAX_LINES); temp_cloud4->points[i].r = 0+j*int(255/MAX_LINES); } } *temp_cloud5 += *temp_cloud4; // add line to ground temp_cloud2.swap ( temp_cloud3); // remove line } cout << "found " << linecoefficients1.size() << " lines." << endl; for(size_t i = 0; i < linecoefficients1.size(); i++) { //cerr << "linecoeffs: " << i << " " // << linecoefficients1[i].values[0] << " " // << linecoefficients1[i].values[1] << " " // << linecoefficients1[i].values[2] << " " // << linecoefficients1[i].values[3] << " " // << linecoefficients1[i].values[4] << " " // << linecoefficients1[i].values[5] << " " // << endl; Eigen::Vector3f lv = Eigen::Vector3f( linecoefficients1[i].values[3], linecoefficients1[i].values[4], linecoefficients1[i].values[5]); Eigen::Vector3f lp = Eigen::Vector3f( linecoefficients1[i].values[0], linecoefficients1[i].values[1], linecoefficients1[i].values[2]); float r = pn.dot(lv); float deg = pcl::rad2deg(acos(r)); cout << "angle of line to floor normal: " << deg << " degrees" << endl; if(abs(deg-30) < 5 || abs(deg-150) < 5) { cout << "found corner line" << endl; float t = -(lp.dot(pn) + planecoefficients->values[3])/ r; Eigen::Vector3f intersect = lp + lv*t; cout << "corner intersects floor at: " << endl << intersect << endl; cout << "straight line distance from camera to corner: " << intersect.norm() << " meters" << endl; corners.push_back(intersect); Eigen::Vector3f floor_distance = intersect + pn; // should be - ??? cout << "distance along floor to corner: " << floor_distance.norm() << " meters" << endl; } else if(abs(deg-90) < 5) { cout << "found horizontal line" << endl; } } switch(corners.size()) { case 2: cout << "distance between corners " << (corners[0] - corners[1]).norm() << endl; cout << "angle of pyramid to camera " << pcl::rad2deg(acos(((corners[0] - corners[1]).normalized()).dot(Eigen::Vector3f::UnitX()))) << endl; break; case 3: cout << "distance between corners " << (corners[0] - corners[1]).norm() << endl; cout << "distance between corners " << (corners[0] - corners[2]).norm() << endl; cout << "distance between corners " << (corners[1] - corners[2]).norm() << endl; cout << "angle of corner on floor (should be 90) " << pcl::rad2deg(acos((corners[0] - corners[1]).dot(corners[0] - corners [2]))) << endl; cout << "angle of pyramid to camera " << pcl::rad2deg(acos(((corners[0] - corners[1]).normalized()).dot(Eigen::Vector3f::UnitX()))) << endl; break; } if (saveCloud) { std::stringstream stream, stream1; std::string filename; stream << "inputCloud" << filesSaved << ".pcd"; filename = stream.str(); if (pcl::io::savePCDFile(filename, *cloud_, true) == 0) { filesSaved++; cout << "Saved " << filename << "." << endl; } else PCL_ERROR("Problem saving %s.\n", filename.c_str()); stream1 << "inputCloud" << filesSaved << ".pcd"; filename = stream1.str(); if (pcl::io::savePCDFile(filename, *temp_cloud5, true) == 0) { filesSaved++; cout << "Saved " << filename << "." << endl; } else PCL_ERROR("Problem saving %s.\n", filename.c_str()); saveCloud = false; } empty_cloud.swap(cloud_); // set cloud_ to null if(toggleView == 1) return (temp_cloud); // return orig cloud else return (temp_cloud5); // return colored cloud }
bool PrimitiveShapeClassifier::estimate(const pcl::PointCloud<PointT>::Ptr& cloud, const pcl::PointCloud<pcl::Normal>::Ptr& normal, const pcl::ModelCoefficients::Ptr& plane, pcl::PointIndices::Ptr& boundary_indices, pcl::PointCloud<PointT>::Ptr& projected_cloud, float& circle_likelihood, float& box_likelihood) { // estimate boundaries pcl::PointCloud<pcl::Boundary>::Ptr boundaries(new pcl::PointCloud<pcl::Boundary>); pcl::BoundaryEstimation<PointT, pcl::Normal, pcl::Boundary> b; b.setInputCloud(cloud); b.setInputNormals(normal); b.setSearchMethod(typename pcl::search::KdTree<PointT>::Ptr(new pcl::search::KdTree<PointT>)); b.setAngleThreshold(DEG2RAD(70)); b.setRadiusSearch(0.03); b.compute(*boundaries); // set boundaries as indices for (size_t i = 0; i < boundaries->points.size(); ++i) if ((int)boundaries->points[i].boundary_point) boundary_indices->indices.push_back(i); // extract boundaries pcl::PointCloud<PointT>::Ptr boundary_cloud(new pcl::PointCloud<PointT>); pcl::ExtractIndices<PointT> ext; ext.setInputCloud(cloud); ext.setIndices(boundary_indices); ext.filter(*boundary_cloud); // thresholding with min points num if (boundary_indices->indices.size() < min_points_num_) return false; // project to supporting plane pcl::ProjectInliers<PointT> proj; proj.setModelType(pcl::SACMODEL_PLANE); proj.setInputCloud(boundary_cloud); proj.setModelCoefficients(plane); proj.filter(*projected_cloud); // estimate circles pcl::PointIndices::Ptr circle_inliers(new pcl::PointIndices); pcl::ModelCoefficients::Ptr circle_coeffs(new pcl::ModelCoefficients); pcl::PointIndices::Ptr line_inliers(new pcl::PointIndices); pcl::ModelCoefficients::Ptr line_coeffs(new pcl::ModelCoefficients); pcl::SACSegmentation<PointT> seg; seg.setInputCloud(projected_cloud); seg.setOptimizeCoefficients(true); seg.setMethodType(pcl::SAC_RANSAC); seg.setMaxIterations(sac_max_iterations_); seg.setModelType(pcl::SACMODEL_CIRCLE3D); seg.setDistanceThreshold(sac_distance_threshold_); seg.setRadiusLimits(sac_radius_limit_min_, sac_radius_limit_max_); seg.segment(*circle_inliers, *circle_coeffs); seg.setOptimizeCoefficients(true); seg.setMethodType(pcl::SAC_RANSAC); seg.setMaxIterations(sac_max_iterations_); seg.setModelType(pcl::SACMODEL_LINE); seg.setDistanceThreshold(sac_distance_threshold_); seg.segment(*line_inliers, *line_coeffs); // compute likelihood circle_likelihood = 1.0f * circle_inliers->indices.size() / projected_cloud->points.size(); box_likelihood = 1.0f * line_inliers->indices.size() / projected_cloud->points.size(); NODELET_DEBUG_STREAM("Projected cloud has " << projected_cloud->points.size() << " points"); NODELET_DEBUG_STREAM(circle_inliers->indices.size() << " circle inliers found"); NODELET_DEBUG_STREAM("circle confidence: " << circle_likelihood); NODELET_DEBUG_STREAM(line_inliers->indices.size() << " line inliers found"); NODELET_DEBUG_STREAM("box confidence: " << box_likelihood); return true; }