Go to the documentation of this file.00001 
00002 
00003 
00004 
00005 
00006 
00007 
00008 
00009 
00010 
00011 
00012 
00013 
00014 
00015 
00016 
00017 
00018 
00019 
00020 
00021 
00022 
00023 
00024 
00025 
00026 
00027 
00028 
00029 
00030 
00031 
00032 
00033 
00034 
00035 
00036 
00037 
00038 #include <rosmpi/rosmpi.h>
00039 #include <rosmpi/node_handle.h>
00040 #include <rosmpi/publisher.h>
00041 #include <rosmpi/subscriber.h>
00042 
00043 #include <pcl/point_types.h>
00044 #include <pcl/io/pcd_io.h>
00045 #include <pcl/ros/conversions.h>
00046 #include <pcl/features/normal_3d.h>
00047 #include <pcl/kdtree/kdtree_flann.h>
00048 
00049 typedef sensor_msgs::PointCloud2 Msg;
00050 typedef sensor_msgs::PointCloud2::ConstPtr MsgConstPtr;
00051 
00052 std::string processor_name;
00053 int rank;
00054 
00055 void 
00056   computeIndices (const int rank, const int max_rank, const int nr_points, pcl::PointIndices &indices)
00057 {
00058   int pts_per_worker = lrint (round (nr_points / max_rank));
00059   int s_idx = rank * pts_per_worker;
00060   
00061   indices.indices.resize (pts_per_worker);
00062   for (size_t i = 0; i < indices.indices.size (); i++)
00063     indices.indices[i] = i + s_idx;
00064 }
00065 
00066 class Worker
00067 {
00068   public:
00069     Worker (int rank, int max_rank) : rank_ (rank), max_rank_ (max_rank)
00070     {
00071       sub_ = nh_.subscribe (&Worker::cloud_cb, this);
00072     }
00073 
00074 
00075     void 
00076       cloud_cb (const MsgConstPtr &msg)
00077     {
00078       ROS_INFO_STREAM ("[" << processor_name << "/" << rank << "] received message with " << msg->data.size () << " size, with " << msg->width << "x" << msg->height);
00079 
00080       pcl::PointCloud<pcl::PointXYZ> cloud;
00081       pcl::fromROSMsg (*msg, cloud);
00082       cloud_.reset (new pcl::PointCloud<pcl::PointXYZ> (cloud));
00083      
00084       pcl::PointIndices indices;
00085       computeIndices (rank_, max_rank_, cloud.points.size (), indices);
00086 
00087       tree_ = boost::make_shared<pcl::KdTreeFLANN<pcl::PointXYZ> > ();
00088       tree_->setInputCloud (cloud_);
00089       
00090       ROS_INFO ("Estimating features for indices: %d -> %d", indices.indices[0], indices.indices[indices.indices.size () - 1]);
00091       ne_.setInputCloud (cloud_);
00092       ne_.setIndices (boost::make_shared<pcl::PointIndices> (indices));
00093       ne_.setSearchMethod (tree_);
00094       ne_.setRadiusSearch (0.03);
00095       ne_.compute (normals_);
00096     }
00097 
00098   private:
00099     rosmpi::NodeHandle nh_;
00100     rosmpi::Subscriber sub_;
00101     pcl::KdTreeFLANN<pcl::PointXYZ>::Ptr tree_;
00102     int rank_, max_rank_;
00103 
00104     pcl::NormalEstimation<pcl::PointXYZ, pcl::Normal> ne_;
00105     pcl::PointCloud<pcl::PointXYZ>::Ptr cloud_;
00106     pcl::PointCloud<pcl::Normal> normals_;
00107 };
00108 
00109 
00110 int
00111   main (int argc, char** argv)
00112 {
00113   if (argc < 2)
00114   {
00115     ROS_ERROR ("Need a valid PCD file as input. Example: $ %s `rospack find pcl`/test/bun0.pcd", argv[0]);
00116     return (-1);
00117   }
00118   rosmpi::init (argc, argv, rosmpi::init_options::ThreadSingle);      
00119 
00120   
00121   int nr_procs = rosmpi::communicator::getSize ();
00122   rank     = rosmpi::communicator::getRank ();
00123 
00124   processor_name = rosmpi::this_processor::getName ();
00125  
00126   
00127   if (rank == 0)
00128   {
00129     
00130     Msg msg;
00131     pcl::io::loadPCDFile (argv[1], msg);
00132     ROS_INFO_STREAM ("[" << processor_name << "] Loaded a file with " << msg.width * msg.height << " points (" << msg.data.size () << " data bytes).");
00133 
00134     
00135     rosmpi::Publisher pub; 
00136     ROS_INFO_STREAM ("[" << processor_name << "] Sending data to " << nr_procs << " nodes.") ;
00137     pub.publish<Msg> (msg);
00138 
00139       pcl::PointCloud<pcl::PointXYZ> cloud;
00140       pcl::fromROSMsg (msg, cloud);
00141      
00142       pcl::PointIndices indices;
00143       computeIndices (rank, nr_procs, cloud.points.size (), indices);
00144 
00145       pcl::KdTreeFLANN<pcl::PointXYZ>::Ptr tree_ = boost::make_shared<pcl::KdTreeFLANN<pcl::PointXYZ> > ();
00146       tree_->setInputCloud (boost::make_shared<pcl::PointCloud<pcl::PointXYZ> >(cloud));
00147       
00148       ROS_INFO ("Estimating features for indices: %d -> %d", indices.indices[0], indices.indices[indices.indices.size () - 1]);
00149       pcl::NormalEstimation<pcl::PointXYZ, pcl::Normal> ne_;
00150       ne_.setInputCloud (boost::make_shared<pcl::PointCloud<pcl::PointXYZ> >(cloud));
00151       ne_.setIndices (boost::make_shared<pcl::PointIndices> (indices));
00152       ne_.setSearchMethod (tree_);
00153       ne_.setRadiusSearch (0.03);
00154       pcl::PointCloud<pcl::Normal> normals_;
00155       ne_.compute (normals_);
00156   }
00157   else
00158   {
00159     Worker w (rank, nr_procs);
00160   }
00161 
00162   rosmpi::shutdown ();
00163 
00164   return (0);
00165 }
00166