triangulate_pcl.cpp
Go to the documentation of this file.
00001 
00031 #include <algorithm>
00032 
00033 #include <boost/foreach.hpp>
00034 
00035 #include <ros/ros.h>
00036 #include <pcl_conversions/pcl_conversions.h>
00037 #include <pcl/io/vtk_io.h>
00038 #include <pcl/point_types.h>
00039 #include <pcl/kdtree/kdtree_flann.h>
00040 #include <pcl/surface/mls.h>
00041 #include <pcl/surface/impl/mls.hpp>
00042 #include <pcl/surface/convex_hull.h>
00043 
00044 #include <sensor_msgs/point_cloud_conversion.h>
00045 #include <triangulate_point_cloud/TriangulatePCL.h>
00046 #include <shape_msgs/Mesh.h>
00047 #include <shape_msgs/MeshTriangle.h>
00048 #include <geometry_msgs/Point.h>
00049 
00050 
00051 using namespace pcl;
00052 using namespace triangulate_point_cloud;
00053 
00054 void reconstructMesh(const PointCloud<PointXYZ>::ConstPtr &cloud,
00055   PointCloud<PointXYZ> &output_cloud, std::vector<Vertices> &triangles)
00056 {
00057   boost::shared_ptr<std::vector<int> > indices(new std::vector<int>);
00058   indices->resize(cloud->points.size ());
00059   for (size_t i = 0; i < indices->size (); ++i) { (*indices)[i] = i; }
00060 
00061   pcl::search::KdTree<PointXYZ>::Ptr tree(new pcl::search::KdTree<PointXYZ>);
00062   tree->setInputCloud(cloud);
00063 
00064   PointCloud<PointXYZ>::Ptr mls_points(new PointCloud<PointXYZ>);
00065   PointCloud<PointNormal>::Ptr mls_normals(new PointCloud<PointNormal>);
00066   MovingLeastSquares<PointXYZ, PointNormal> mls;
00067 
00068   mls.setInputCloud(cloud);
00069   mls.setIndices(indices);
00070   mls.setPolynomialFit(true);
00071   mls.setSearchMethod(tree);
00072   mls.setSearchRadius(0.03);
00073   
00074   mls.process(*mls_normals);
00075   
00076   ConvexHull<PointXYZ> ch;
00077   
00078   ch.setInputCloud(mls_points);
00079   ch.reconstruct(output_cloud, triangles);
00080 }
00081 
00082 template<typename T>
00083 void toPoint(const T &in, geometry_msgs::Point &out)
00084 {
00085   out.x = in.x;
00086   out.y = in.y;
00087   out.z = in.z;
00088 }
00089 
00090 template<typename T>
00091 void polygonMeshToShapeMsg(const PointCloud<T> &points,
00092   const std::vector<Vertices> &triangles,
00093   shape_msgs::Mesh &mesh)
00094 {
00095   mesh.vertices.resize(points.points.size());
00096   for(size_t i=0; i<points.points.size(); i++)
00097     toPoint(points.points[i], mesh.vertices[i]);
00098 
00099   ROS_INFO("Found %ld polygons", triangles.size());
00100   BOOST_FOREACH(const Vertices polygon, triangles)
00101   {
00102     if(polygon.vertices.size() < 3)
00103     {
00104       ROS_WARN("Not enough points in polygon. Ignoring it.");
00105       continue;
00106     }
00107 
00108     shape_msgs::MeshTriangle triangle = shape_msgs::MeshTriangle();
00109     boost::array<uint32_t, 3> xyz = {{polygon.vertices[0], polygon.vertices[1], polygon.vertices[2]}};
00110     triangle.vertex_indices = xyz;
00111 
00112     mesh.triangles.push_back(shape_msgs::MeshTriangle());
00113   }
00114 }
00115 
00116 bool onTriangulatePcl(TriangulatePCL::Request &req, TriangulatePCL::Response &res)
00117 {
00118   ROS_INFO("Service request received");
00119 
00120   sensor_msgs::PointCloud2 cloud_raw;
00121   sensor_msgs::convertPointCloudToPointCloud2(req.points, cloud_raw);
00122   PointCloud<PointXYZ>::Ptr cloud(new PointCloud<PointXYZ>);
00123   pcl::fromROSMsg(cloud_raw, *cloud);
00124 
00125   PointCloud<PointXYZ> out_cloud;
00126   std::vector<Vertices> triangles;
00127 
00128   ROS_INFO("Triangulating");
00129   reconstructMesh(cloud, out_cloud, triangles);
00130   ROS_INFO("Triangulation done");
00131 
00132   ROS_INFO("Converting to shape message");
00133   polygonMeshToShapeMsg(out_cloud, triangles, res.mesh);
00134 
00135   ROS_INFO("Service processing done");
00136 
00137   return true;
00138 }
00139 
00140 void test()
00141 {
00142   pcl::PointCloud<pcl::PointXYZ> pcl_cloud;
00143   pcl::PCDReader reader;
00144 
00145   if (reader.read("test_data/ism_test_cat.pcd", pcl_cloud) < 0)
00146   {
00147         PCL_ERROR ("Couldn't read file test_data/ism_test_cat.pcd \n");
00148         return;
00149   }
00150 
00151   sensor_msgs::PointCloud2 sensor_cloud2;
00152   pcl::toROSMsg(pcl_cloud, sensor_cloud2);
00153   sensor_msgs::PointCloud sensor_cloud1;
00154   sensor_msgs::convertPointCloud2ToPointCloud(sensor_cloud2, sensor_cloud1);
00155 
00156   TriangulatePCL::Request req;
00157   req.points = sensor_cloud1;
00158   TriangulatePCL::Response res;
00159   onTriangulatePcl(req, res);
00160 }
00161 
00162 int main(int argc, char *argv[])
00163 {
00164   ros::init(argc, argv, "triangulate_point_cloud");
00165   ros::NodeHandle nh("~");
00166   
00167 //  test();
00168 
00169   ros::ServiceServer service = nh.advertiseService("triangulate", &onTriangulatePcl);
00170   ROS_INFO("Triangulation service running");
00171   ros::spin();
00172   return 0;
00173 }


triangulate_point_cloud
Author(s): Lorenz Moesenlechner
autogenerated on Sat Apr 26 2014 10:07:58