bounding_volume_calculator.cpp
Go to the documentation of this file.
00001 #include <rail_segmentation/bounding_volume_calculator.h>
00002 
00003 rail_manipulation_msgs::BoundingVolume BoundingVolumeCalculator::computeBoundingVolume(sensor_msgs::PointCloud2 cloud)
00004 {
00005   //convert point cloud to pcl point cloud
00006   pcl::PointCloud<pcl::PointXYZ>::Ptr object_cloud(new pcl::PointCloud<pcl::PointXYZ>);
00007   pcl::PCLPointCloud2 converter;
00008   pcl_conversions::toPCL(cloud, converter);
00009   pcl::fromPCLPointCloud2(converter, *object_cloud);
00010 
00011   return BoundingVolumeCalculator::computeBoundingVolume(object_cloud);
00012 }
00013 
00014 rail_manipulation_msgs::BoundingVolume
00015 BoundingVolumeCalculator::computeBoundingVolume(pcl::PointCloud<pcl::PointXYZRGB>::Ptr cloud)
00016 {
00017   pcl::PointCloud<pcl::PointXYZ>::Ptr xyz_cloud(new pcl::PointCloud<pcl::PointXYZ>);
00018   pcl::copyPointCloud(*cloud, *xyz_cloud);
00019 
00020   return BoundingVolumeCalculator::computeBoundingVolume(xyz_cloud);
00021 }
00022 
00023 rail_manipulation_msgs::BoundingVolume
00024 BoundingVolumeCalculator::computeBoundingVolume(pcl::PointCloud<pcl::PointXYZ>::Ptr cloud)
00025 {
00026   //calculate original point cloud bounds
00027   pcl::PointXYZ min_original, max_original;
00028   pcl::getMinMax3D(*cloud, min_original, max_original);
00029 
00030   // project point cloud to x-y plane (this will create a bounding box that aligns with gravity; not always accurate,
00031   // but a useful assumption for tabletop, shelf, and floor pick-and-place applications)
00032   pcl::PointCloud<pcl::PointXYZ>::Ptr projected_cloud(new pcl::PointCloud<pcl::PointXYZ>);
00033   pcl::ModelCoefficients::Ptr coefficients (new pcl::ModelCoefficients());
00034   coefficients->values.resize(4);
00035   coefficients->values[0] = coefficients->values[1] = 0;
00036   coefficients->values[2] = 1;
00037   coefficients->values[3] = 0;
00038   pcl::ProjectInliers<pcl::PointXYZ> projector;
00039   projector.setModelType(pcl::SACMODEL_PLANE);
00040   projector.setInputCloud(cloud);
00041   projector.setModelCoefficients(coefficients);
00042   projector.filter(*projected_cloud);
00043 
00044   // compute principal direction
00045   Eigen::Matrix3f covariance;
00046   Eigen::Vector4f centroid;
00047   //use center instead of centroid so as not to strongly weight parts of the point cloud closer to the sensor
00048   centroid[0] = static_cast<float>((min_original.x + max_original.x)/2.0);
00049   centroid[1] = static_cast<float>((min_original.y + max_original.y)/2.0);
00050   centroid[2] = 0;  //because point cloud is projected to x-y plane
00051   pcl::computeCovarianceMatrixNormalized(*projected_cloud, centroid, covariance);
00052   Eigen::SelfAdjointEigenSolver<Eigen::Matrix3f> eigen_solver(covariance, Eigen::ComputeEigenvectors);
00053   Eigen::Matrix3f eig_dx = eigen_solver.eigenvectors();
00054   eig_dx.col(2) = eig_dx.col(0).cross(eig_dx.col(1));
00055 
00056   //move the points to that reference frame
00057   Eigen::Matrix4f p2w(Eigen::Matrix4f::Identity());
00058   p2w.block(0, 0, 3, 3) = eig_dx.transpose();
00059   p2w.block(0, 3, 3, 1) = -1.f * (p2w.block(0, 0, 3, 3) * centroid.head(3));
00060   pcl::PointCloud<pcl::PointXYZ> c_points;
00061   pcl::transformPointCloud(*projected_cloud, c_points, p2w);
00062 
00063   pcl::PointXYZ min_pt, max_pt;
00064   pcl::getMinMax3D(c_points, min_pt, max_pt);
00065   const Eigen::Vector3f mean_diag = 0.5f * (max_pt.getVector3fMap() + min_pt.getVector3fMap());
00066 
00067   //final transform
00068   const Eigen::Quaternionf qfinal(eig_dx);
00069   const Eigen::Vector3f tfinal = eig_dx * mean_diag + centroid.head(3);
00070 
00071   //set object shape
00072   rail_manipulation_msgs::BoundingVolume bounding_box;
00073   bounding_box.dimensions.x = max_original.z - min_original.z;
00074   bounding_box.dimensions.y = max_pt.y - min_pt.y;
00075   bounding_box.dimensions.z = max_pt.z - min_pt.z;
00076   bounding_box.pose.header.frame_id = cloud->header.frame_id;
00077   bounding_box.pose.pose.position.x = tfinal[0];
00078   bounding_box.pose.pose.position.y = tfinal[1];
00079   bounding_box.pose.pose.position.z = (min_original.z + max_original.z)/2.0;
00080   bounding_box.pose.pose.orientation.w = qfinal.w();
00081   bounding_box.pose.pose.orientation.x = qfinal.x();
00082   bounding_box.pose.pose.orientation.y = qfinal.y();
00083   bounding_box.pose.pose.orientation.z = qfinal.z();
00084 
00085   return bounding_box;
00086 }


rail_segmentation
Author(s): Russell Toris , David Kent
autogenerated on Sat Jun 8 2019 19:54:19