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