feature.cpp
Go to the documentation of this file.
00001 /*
00002  * Software License Agreement (BSD License)
00003  *
00004  *  Copyright (c) 2009, Willow Garage, Inc.
00005  *  All rights reserved.
00006  *
00007  *  Redistribution and use in source and binary forms, with or without
00008  *  modification, are permitted provided that the following conditions
00009  *  are met:
00010  *
00011  *   * Redistributions of source code must retain the above copyright
00012  *     notice, this list of conditions and the following disclaimer.
00013  *   * Redistributions in binary form must reproduce the above
00014  *     copyright notice, this list of conditions and the following
00015  *     disclaimer in the documentation and/or other materials provided
00016  *     with the distribution.
00017  *   * Neither the name of Willow Garage, Inc. nor the names of its
00018  *     contributors may be used to endorse or promote products derived
00019  *     from this software without specific prior written permission.
00020  *
00021  *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
00022  *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
00023  *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
00024  *  FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
00025  *  COPYRIGHT OWNERff OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
00026  *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
00027  *  BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
00028  *  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
00029  *  CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
00030  *  LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
00031  *  ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
00032  *  POSSIBILITY OF SUCH DAMAGE.
00033  *
00034  * $Id: feature.cpp 35422 2011-01-24 20:04:44Z rusu $
00035  *
00036  */
00037 
00038 //#include <pluginlib/class_list_macros.h>
00039 // Include the implementations here instead of compiling them separately to speed up compile time
00040 //#include "normal_3d.cpp"
00041 //#include "boundary.cpp"
00042 //#include "fpfh.cpp"
00043 //#include "fpfh_omp.cpp"
00044 //#include "moment_invariants.cpp"
00045 //#include "normal_3d_omp.cpp"
00046 //#include "normal_3d_tbb.cpp"
00047 //#include "pfh.cpp"
00048 //#include "principal_curvatures.cpp"
00049 //#include "vfh.cpp"
00050 #include <pcl/io/io.h>
00051 #include "pcl_ros/features/feature.h"
00052 #include <message_filters/null_types.h>
00053 
00055 void
00056 pcl_ros::Feature::onInit ()
00057 {
00058   // Call the super onInit ()
00059   PCLNodelet::onInit ();
00060 
00061   // Call the child init
00062   childInit (*pnh_);
00063 
00064   // Allow each individual class that inherits from us to declare their own Publisher
00065   // This is useful for Publisher<pcl::PointCloud<T> >, as NormalEstimation can publish PointCloud<Normal>, etc
00066   //pub_output_ = pnh_->template advertise<PointCloud2> ("output", max_queue_size_);
00067 
00068   // ---[ Mandatory parameters
00069   if (!pnh_->getParam ("k_search", k_) && !pnh_->getParam ("radius_search", search_radius_))
00070   {
00071     NODELET_ERROR ("[%s::onInit] Neither 'k_search' nor 'radius_search' set! Need to set at least one of these parameters before continuing.", getName ().c_str ());
00072     return;
00073   }
00074   if (!pnh_->getParam ("spatial_locator", spatial_locator_type_))
00075   {
00076     NODELET_ERROR ("[%s::onInit] Need a 'spatial_locator' parameter to be set before continuing!", getName ().c_str ());
00077     return;
00078   }
00079 
00080   // ---[ Optional parameters
00081   pnh_->getParam ("use_surface", use_surface_);
00082 
00083   // Enable the dynamic reconfigure service
00084   srv_ = boost::make_shared<dynamic_reconfigure::Server<FeatureConfig> > (*pnh_);
00085   dynamic_reconfigure::Server<FeatureConfig>::CallbackType f = boost::bind (&Feature::config_callback, this, _1, _2);
00086   srv_->setCallback (f);
00087 
00088   // If we're supposed to look for PointIndices (indices) or PointCloud (surface) messages
00089   if (use_indices_ || use_surface_)
00090   {
00091     // Create the objects here
00092     if (approximate_sync_)
00093       sync_input_surface_indices_a_ = boost::make_shared<message_filters::Synchronizer<sync_policies::ApproximateTime<PointCloudIn, PointCloudIn, PointIndices> > >(max_queue_size_);
00094     else
00095       sync_input_surface_indices_e_ = boost::make_shared<message_filters::Synchronizer<sync_policies::ExactTime<PointCloudIn, PointCloudIn, PointIndices> > >(max_queue_size_);
00096 
00097     // Subscribe to the input using a filter
00098     sub_input_filter_.subscribe (*pnh_, "input", max_queue_size_);
00099     if (use_indices_)
00100     {
00101       // If indices are enabled, subscribe to the indices
00102       sub_indices_filter_.subscribe (*pnh_, "indices", max_queue_size_);
00103       if (use_surface_)     // Use both indices and surface
00104       {
00105         // If surface is enabled, subscribe to the surface, connect the input-indices-surface trio and register
00106         sub_surface_filter_.subscribe (*pnh_, "surface", max_queue_size_);
00107         if (approximate_sync_)
00108           sync_input_surface_indices_a_->connectInput (sub_input_filter_, sub_surface_filter_, sub_indices_filter_);
00109         else
00110           sync_input_surface_indices_e_->connectInput (sub_input_filter_, sub_surface_filter_, sub_indices_filter_);
00111       }
00112       else                  // Use only indices
00113       {
00114         sub_input_filter_.registerCallback (bind (&Feature::input_callback, this, _1));
00115         // surface not enabled, connect the input-indices duo and register
00116         if (approximate_sync_)
00117           sync_input_surface_indices_a_->connectInput (sub_input_filter_, nf_pc_, sub_indices_filter_);
00118         else
00119           sync_input_surface_indices_e_->connectInput (sub_input_filter_, nf_pc_, sub_indices_filter_);
00120       }
00121     }
00122     else                    // Use only surface
00123     {
00124       sub_input_filter_.registerCallback (bind (&Feature::input_callback, this, _1));
00125       // indices not enabled, connect the input-surface duo and register
00126       sub_surface_filter_.subscribe (*pnh_, "surface", max_queue_size_);
00127       if (approximate_sync_)
00128         sync_input_surface_indices_a_->connectInput (sub_input_filter_, sub_surface_filter_, nf_pi_);
00129       else
00130         sync_input_surface_indices_e_->connectInput (sub_input_filter_, sub_surface_filter_, nf_pi_);
00131     }
00132     // Register callbacks
00133     if (approximate_sync_)
00134       sync_input_surface_indices_a_->registerCallback (bind (&Feature::input_surface_indices_callback, this, _1, _2, _3));
00135     else
00136       sync_input_surface_indices_e_->registerCallback (bind (&Feature::input_surface_indices_callback, this, _1, _2, _3));
00137   }
00138   else
00139     // Subscribe in an old fashion to input only (no filters)
00140     sub_input_ = pnh_->subscribe<PointCloudIn> ("input", max_queue_size_,  bind (&Feature::input_surface_indices_callback, this, _1, PointCloudInConstPtr (), PointIndicesConstPtr ()));
00141 
00142   NODELET_DEBUG ("[%s::onInit] Nodelet successfully created with the following parameters:\n"
00143                  " - use_surface    : %s\n"
00144                  " - k_search       : %d\n"
00145                  " - radius_search  : %f\n"
00146                  " - spatial_locator: %d",
00147                 getName ().c_str (),
00148                 (use_surface_) ? "true" : "false", k_, search_radius_, spatial_locator_type_);
00149 }
00150 
00152 void
00153 pcl_ros::Feature::config_callback (FeatureConfig &config, uint32_t level)
00154 {
00155   if (k_ != config.k_search)
00156   {
00157     k_ = config.k_search;
00158     NODELET_DEBUG ("[config_callback] Setting the number of K nearest neighbors to use for each point: %d.", k_);
00159   }
00160   if (search_radius_ != config.radius_search)
00161   {
00162     search_radius_ = config.radius_search;
00163     NODELET_DEBUG ("[config_callback] Setting the nearest neighbors search radius for each point: %f.", search_radius_);
00164   }
00165 }
00166 
00168 void
00169 pcl_ros::Feature::input_surface_indices_callback (const PointCloudInConstPtr &cloud, 
00170     const PointCloudInConstPtr &cloud_surface, const PointIndicesConstPtr &indices)
00171 {
00172   // No subscribers, no work
00173   if (pub_output_.getNumSubscribers () <= 0)
00174     return;
00175 
00176   // If cloud is given, check if it's valid
00177   if (!isValid (cloud))
00178   {
00179     NODELET_ERROR ("[%s::input_surface_indices_callback] Invalid input!", getName ().c_str ());
00180     emptyPublish (cloud);
00181     return;
00182   }
00183 
00184   // If surface is given, check if it's valid
00185   if (cloud_surface && !isValid (cloud_surface, "surface"))
00186   {
00187     NODELET_ERROR ("[%s::input_surface_indices_callback] Invalid input surface!", getName ().c_str ());
00188     emptyPublish (cloud);
00189     return;
00190   }
00191     
00192   // If indices are given, check if they are valid
00193   if (indices && !isValid (indices))
00194   {
00195     NODELET_ERROR ("[%s::input_surface_indices_callback] Invalid input indices!", getName ().c_str ());
00196     emptyPublish (cloud);
00197     return;
00198   }
00199 
00201   if (cloud_surface)
00202     if (indices)
00203       NODELET_DEBUG ("[input_surface_indices_callback]\n"
00204                      "                                         - PointCloud with %d data points (%s), stamp %f, and frame %s on topic %s received.\n"
00205                      "                                         - PointCloud with %d data points (%s), stamp %f, and frame %s on topic %s received.\n"
00206                      "                                         - PointIndices with %zu values, stamp %f, and frame %s on topic %s received.",
00207                  cloud->width * cloud->height, pcl::getFieldsList (*cloud).c_str (), cloud->header.stamp.toSec (), cloud->header.frame_id.c_str (), pnh_->resolveName ("input").c_str (),
00208                  cloud_surface->width * cloud_surface->height, pcl::getFieldsList (*cloud_surface).c_str (), cloud_surface->header.stamp.toSec (), cloud_surface->header.frame_id.c_str (), pnh_->resolveName ("surface").c_str (),
00209                  indices->indices.size (), indices->header.stamp.toSec (), indices->header.frame_id.c_str (), pnh_->resolveName ("indices").c_str ());
00210     else
00211       NODELET_DEBUG ("[input_surface_indices_callback]\n"
00212                      "                                 - PointCloud with %d data points (%s), stamp %f, and frame %s on topic %s received.\n"
00213                      "                                 - PointCloud with %d data points (%s), stamp %f, and frame %s on topic %s received.",
00214                      cloud->width * cloud->height, pcl::getFieldsList (*cloud).c_str (), cloud->header.stamp.toSec (), cloud->header.frame_id.c_str (), pnh_->resolveName ("input").c_str (),
00215                      cloud_surface->width * cloud_surface->height, pcl::getFieldsList (*cloud_surface).c_str (), cloud_surface->header.stamp.toSec (), cloud_surface->header.frame_id.c_str (), pnh_->resolveName ("surface").c_str ());
00216 
00217   else
00218     if (indices)
00219       NODELET_DEBUG ("[input_surface_indices_callback]\n"
00220                      "                                 - PointCloud with %d data points (%s), stamp %f, and frame %s on topic %s received.\n"
00221                      "                                 - PointIndices with %zu values, stamp %f, and frame %s on topic %s received.",
00222                      cloud->width * cloud->height, pcl::getFieldsList (*cloud).c_str (), cloud->header.stamp.toSec (), cloud->header.frame_id.c_str (), pnh_->resolveName ("input").c_str (),
00223                      indices->indices.size (), indices->header.stamp.toSec (), indices->header.frame_id.c_str (), pnh_->resolveName ("indices").c_str ());
00224     else
00225       NODELET_DEBUG ("[input_surface_indices_callback] PointCloud with %d data points, stamp %f, and frame %s on topic %s received.", cloud->width * cloud->height, cloud->header.stamp.toSec (), cloud->header.frame_id.c_str (), pnh_->resolveName ("input").c_str ());
00227 
00228 
00229   if ((int)(cloud->width * cloud->height) < k_)
00230   {
00231     NODELET_ERROR ("[input_surface_indices_callback] Requested number of k-nearest neighbors (%d) is larger than the PointCloud size (%d)!", k_, (int)(cloud->width * cloud->height));
00232     emptyPublish (cloud);
00233     return;
00234   }
00235 
00236   // If indices given...
00237   IndicesPtr vindices;
00238   if (indices && !indices->header.frame_id.empty ())
00239     vindices.reset (new std::vector<int> (indices->indices));
00240 
00241   computePublish (cloud, cloud_surface, vindices);
00242 }
00243 
00247 
00249 void
00250 pcl_ros::FeatureFromNormals::onInit ()
00251 {
00252   // Call the super onInit ()
00253   PCLNodelet::onInit ();
00254 
00255   // Call the child init
00256   childInit (*pnh_);
00257 
00258   // Allow each individual class that inherits from us to declare their own Publisher
00259   // This is useful for Publisher<pcl::PointCloud<T> >, as NormalEstimation can publish PointCloud<Normal>, etc
00260   //pub_output_ = pnh_->template advertise<PointCloud2> ("output", max_queue_size_);
00261 
00262   // ---[ Mandatory parameters
00263   if (!pnh_->getParam ("k_search", k_) && !pnh_->getParam ("radius_search", search_radius_))
00264   {
00265     NODELET_ERROR ("[%s::onInit] Neither 'k_search' nor 'radius_search' set! Need to set at least one of these parameters before continuing.", getName ().c_str ());
00266     return;
00267   }
00268   if (!pnh_->getParam ("spatial_locator", spatial_locator_type_))
00269   {
00270     NODELET_ERROR ("[%s::onInit] Need a 'spatial_locator' parameter to be set before continuing!", getName ().c_str ());
00271     return;
00272   }
00273   // ---[ Optional parameters
00274   pnh_->getParam ("use_surface", use_surface_);
00275 
00276   sub_input_filter_.subscribe (*pnh_, "input", max_queue_size_);
00277   sub_normals_filter_.subscribe (*pnh_, "normals", max_queue_size_);
00278 
00279   // Enable the dynamic reconfigure service
00280   srv_ = boost::make_shared<dynamic_reconfigure::Server<FeatureConfig> > (*pnh_);
00281   dynamic_reconfigure::Server<FeatureConfig>::CallbackType f = boost::bind (&FeatureFromNormals::config_callback, this, _1, _2);
00282   srv_->setCallback (f);
00283 
00284   // Create the objects here
00285   if (approximate_sync_)
00286     sync_input_normals_surface_indices_a_ = boost::make_shared <message_filters::Synchronizer<sync_policies::ApproximateTime<PointCloudIn, PointCloudN, PointCloudIn, PointIndices> > > (max_queue_size_);
00287   else
00288     sync_input_normals_surface_indices_e_ = boost::make_shared <message_filters::Synchronizer<sync_policies::ExactTime<PointCloudIn, PointCloudN, PointCloudIn, PointIndices> > > (max_queue_size_);
00289 
00290   // If we're supposed to look for PointIndices (indices) or PointCloud (surface) messages
00291   if (use_indices_ || use_surface_)
00292   {
00293     if (use_indices_)
00294     {
00295       // If indices are enabled, subscribe to the indices
00296       sub_indices_filter_.subscribe (*pnh_, "indices", max_queue_size_);
00297       if (use_surface_)     // Use both indices and surface
00298       {
00299         // If surface is enabled, subscribe to the surface, connect the input-indices-surface trio and register
00300         sub_surface_filter_.subscribe (*pnh_, "surface", max_queue_size_);
00301         if (approximate_sync_)
00302           sync_input_normals_surface_indices_a_->connectInput (sub_input_filter_, sub_normals_filter_, sub_surface_filter_, sub_indices_filter_);
00303         else
00304           sync_input_normals_surface_indices_e_->connectInput (sub_input_filter_, sub_normals_filter_, sub_surface_filter_, sub_indices_filter_);
00305       }
00306       else                  // Use only indices
00307       {
00308         sub_input_filter_.registerCallback (bind (&FeatureFromNormals::input_callback, this, _1));
00309         if (approximate_sync_)
00310           // surface not enabled, connect the input-indices duo and register
00311           sync_input_normals_surface_indices_a_->connectInput (sub_input_filter_, sub_normals_filter_, nf_pc_, sub_indices_filter_);
00312         else
00313           // surface not enabled, connect the input-indices duo and register
00314           sync_input_normals_surface_indices_e_->connectInput (sub_input_filter_, sub_normals_filter_, nf_pc_, sub_indices_filter_);
00315       }
00316     }
00317     else                    // Use only surface
00318     {
00319       // indices not enabled, connect the input-surface duo and register
00320       sub_surface_filter_.subscribe (*pnh_, "surface", max_queue_size_);
00321 
00322       sub_input_filter_.registerCallback (bind (&FeatureFromNormals::input_callback, this, _1));
00323       if (approximate_sync_)
00324         sync_input_normals_surface_indices_a_->connectInput (sub_input_filter_, sub_normals_filter_, sub_surface_filter_, nf_pi_);
00325       else
00326         sync_input_normals_surface_indices_e_->connectInput (sub_input_filter_, sub_normals_filter_, sub_surface_filter_, nf_pi_);
00327     }
00328   }
00329   else
00330   {
00331     sub_input_filter_.registerCallback (bind (&FeatureFromNormals::input_callback, this, _1));
00332 
00333     if (approximate_sync_)
00334       sync_input_normals_surface_indices_a_->connectInput (sub_input_filter_, sub_normals_filter_, nf_pc_, nf_pi_);
00335     else
00336       sync_input_normals_surface_indices_e_->connectInput (sub_input_filter_, sub_normals_filter_, nf_pc_, nf_pi_);
00337   }
00338 
00339   // Register callbacks
00340   if (approximate_sync_)
00341     sync_input_normals_surface_indices_a_->registerCallback (bind (&FeatureFromNormals::input_normals_surface_indices_callback, this, _1, _2, _3, _4));
00342   else
00343     sync_input_normals_surface_indices_e_->registerCallback (bind (&FeatureFromNormals::input_normals_surface_indices_callback, this, _1, _2, _3, _4));
00344 
00345   NODELET_DEBUG ("[%s::onInit] Nodelet successfully created with the following parameters:\n"
00346                  " - use_surface    : %s\n"
00347                  " - k_search       : %d\n"
00348                  " - radius_search  : %f\n"
00349                  " - spatial_locator: %d",
00350                 getName ().c_str (),
00351                  (use_surface_) ? "true" : "false", k_, search_radius_, spatial_locator_type_);
00352 }
00353 
00355 void
00356 pcl_ros::FeatureFromNormals::input_normals_surface_indices_callback (
00357    const PointCloudInConstPtr &cloud, const PointCloudNConstPtr &cloud_normals,
00358    const PointCloudInConstPtr &cloud_surface, const PointIndicesConstPtr &indices)
00359 {
00360   // No subscribers, no work
00361   if (pub_output_.getNumSubscribers () <= 0)
00362     return;
00363 
00364   // If cloud+normals is given, check if it's valid
00365   if (!isValid (cloud))// || !isValid (cloud_normals, "normals"))
00366   {
00367     NODELET_ERROR ("[%s::input_normals_surface_indices_callback] Invalid input!", getName ().c_str ());
00368     emptyPublish (cloud);
00369     return;
00370   }
00371 
00372   // If surface is given, check if it's valid
00373   if (cloud_surface && !isValid (cloud_surface, "surface"))
00374   {
00375     NODELET_ERROR ("[%s::input_normals_surface_indices_callback] Invalid input surface!", getName ().c_str ());
00376     emptyPublish (cloud);
00377     return;
00378   }
00379     
00380   // If indices are given, check if they are valid
00381   if (indices && !isValid (indices))
00382   {
00383     NODELET_ERROR ("[%s::input_normals_surface_indices_callback] Invalid input indices!", getName ().c_str ());
00384     emptyPublish (cloud);
00385     return;
00386   }
00387 
00389   if (cloud_surface)
00390     if (indices)
00391       NODELET_DEBUG ("[%s::input_normals_surface_indices_callback]\n"
00392                      "                                                 - PointCloud with %d data points (%s), stamp %f, and frame %s on topic %s received.\n"
00393                      "                                                 - PointCloud with %d data points (%s), stamp %f, and frame %s on topic %s received.\n"
00394                      "                                                 - PointCloud with %d data points (%s), stamp %f, and frame %s on topic %s received.\n"
00395                      "                                                 - PointIndices with %zu values, stamp %f, and frame %s on topic %s received.",
00396                      getName ().c_str (),
00397                      cloud->width * cloud->height, pcl::getFieldsList (*cloud).c_str (), cloud->header.stamp.toSec (), cloud->header.frame_id.c_str (), pnh_->resolveName ("input").c_str (),
00398                      cloud_surface->width * cloud_surface->height, pcl::getFieldsList (*cloud_surface).c_str (), cloud_surface->header.stamp.toSec (), cloud_surface->header.frame_id.c_str (), pnh_->resolveName ("surface").c_str (),
00399                      cloud_normals->width * cloud_normals->height, pcl::getFieldsList (*cloud_normals).c_str (), cloud_normals->header.stamp.toSec (), cloud_normals->header.frame_id.c_str (), pnh_->resolveName ("normals").c_str (),
00400                      indices->indices.size (), indices->header.stamp.toSec (), indices->header.frame_id.c_str (), pnh_->resolveName ("indices").c_str ());
00401     else
00402       NODELET_DEBUG ("[%s::input_normals_surface_indices_callback]\n"
00403                      "                                         - PointCloud with %d data points (%s), stamp %f, and frame %s on topic %s received.\n"
00404                      "                                         - PointCloud with %d data points (%s), stamp %f, and frame %s on topic %s received.\n"
00405                      "                                         - PointCloud with %d data points (%s), stamp %f, and frame %s on topic %s received.",
00406                      getName ().c_str (), 
00407                      cloud->width * cloud->height, pcl::getFieldsList (*cloud).c_str (), cloud->header.stamp.toSec (), cloud->header.frame_id.c_str (), pnh_->resolveName ("input").c_str (),
00408                      cloud_surface->width * cloud_surface->height, pcl::getFieldsList (*cloud_surface).c_str (), cloud_surface->header.stamp.toSec (), cloud_surface->header.frame_id.c_str (), pnh_->resolveName ("surface").c_str (),
00409                      cloud_normals->width * cloud_normals->height, pcl::getFieldsList (*cloud_normals).c_str (), cloud_normals->header.stamp.toSec (), cloud_normals->header.frame_id.c_str (), pnh_->resolveName ("normals").c_str ());
00410   else
00411     if (indices)
00412       NODELET_DEBUG ("[%s::input_normals_surface_indices_callback]\n"
00413                      "                                         - PointCloud with %d data points (%s), stamp %f, and frame %s on topic %s received.\n"
00414                      "                                         - PointCloud with %d data points (%s), stamp %f, and frame %s on topic %s received.\n"
00415                      "                                         - PointIndices with %zu values, stamp %f, and frame %s on topic %s received.",
00416                      getName ().c_str (),
00417                      cloud->width * cloud->height, pcl::getFieldsList (*cloud).c_str (), cloud->header.stamp.toSec (), cloud->header.frame_id.c_str (), pnh_->resolveName ("input").c_str (),
00418                      cloud_normals->width * cloud_normals->height, pcl::getFieldsList (*cloud_normals).c_str (), cloud_normals->header.stamp.toSec (), cloud_normals->header.frame_id.c_str (), pnh_->resolveName ("normals").c_str (),
00419                      indices->indices.size (), indices->header.stamp.toSec (), indices->header.frame_id.c_str (), pnh_->resolveName ("indices").c_str ());
00420     else
00421       NODELET_DEBUG ("[%s::input_normals_surface_indices_callback]\n"
00422                      "                                 - PointCloud with %d data points (%s), stamp %f, and frame %s on topic %s received.\n"
00423                      "                                 - PointCloud with %d data points (%s), stamp %f, and frame %s on topic %s received.",
00424                      getName ().c_str (), 
00425                      cloud->width * cloud->height, pcl::getFieldsList (*cloud).c_str (), cloud->header.stamp.toSec (), cloud->header.frame_id.c_str (), pnh_->resolveName ("input").c_str (),
00426                      cloud_normals->width * cloud_normals->height, pcl::getFieldsList (*cloud_normals).c_str (), cloud_normals->header.stamp.toSec (), cloud_normals->header.frame_id.c_str (), pnh_->resolveName ("normals").c_str ());
00428 
00429   if ((int)(cloud->width * cloud->height) < k_)
00430   {
00431     NODELET_ERROR ("[%s::input_normals_surface_indices_callback] Requested number of k-nearest neighbors (%d) is larger than the PointCloud size (%d)!", getName ().c_str (), k_, (int)(cloud->width * cloud->height));
00432     emptyPublish (cloud);
00433     return;
00434   }
00435 
00436   // If indices given...
00437   IndicesPtr vindices;
00438   if (indices && !indices->header.frame_id.empty ())
00439     vindices.reset (new std::vector<int> (indices->indices));
00440 
00441   computePublish (cloud, cloud_normals, cloud_surface, vindices);
00442 }
00443 


pcl_ros
Author(s): Open Perception, Julius Kammerl , William Woodall
autogenerated on Wed Aug 26 2015 15:25:31