passthrough.cpp
Go to the documentation of this file.
00001 /*
00002  * Software License Agreement (BSD License)
00003  *
00004  *  Point Cloud Library (PCL) - www.pointclouds.org
00005  *  Copyright (c) 2010, Willow Garage, Inc.
00006  *  Copyright (c) 2012-, Open Perception, Inc.
00007  *
00008  *  All rights reserved.
00009  *
00010  *  Redistribution and use in source and binary forms, with or without
00011  *  modification, are permitted provided that the following conditions
00012  *  are met:
00013  *
00014  *   * Redistributions of source code must retain the above copyright
00015  *     notice, this list of conditions and the following disclaimer.
00016  *   * Redistributions in binary form must reproduce the above
00017  *     copyright notice, this list of conditions and the following
00018  *     disclaimer in the documentation and/or other materials provided
00019  *     with the distribution.
00020  *   * Neither the name of the copyright holder(s) nor the names of its
00021  *     contributors may be used to endorse or promote products derived
00022  *     from this software without specific prior written permission.
00023  *
00024  *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
00025  *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
00026  *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
00027  *  FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
00028  *  COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
00029  *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
00030  *  BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
00031  *  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
00032  *  CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
00033  *  LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
00034  *  ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
00035  *  POSSIBILITY OF SUCH DAMAGE.
00036  *
00037  * $Id$
00038  *
00039  */
00040 
00041 #include <pcl/filters/impl/passthrough.hpp>
00042 
00044 void
00045 pcl::PassThrough<pcl::PCLPointCloud2>::applyFilter (PCLPointCloud2 &output)
00046 {
00047   if (!input_)
00048   {
00049     PCL_ERROR ("[pcl::%s::applyFilter] Input dataset not given!\n", getClassName ().c_str ());
00050     output.width = output.height = 0;
00051     output.data.clear ();
00052     return;
00053   }
00054 
00055   // If fields x/y/z are not present, we cannot filter
00056   if (x_idx_ == -1 || y_idx_ == -1 || z_idx_ == -1)
00057   {
00058     PCL_ERROR ("[pcl::%s::applyFilter] Input dataset doesn't have x-y-z coordinates!\n", getClassName ().c_str ());
00059     output.width = output.height = 0;
00060     output.data.clear ();
00061     return;
00062   }
00063 
00064   int nr_points = input_->width * input_->height;
00065 
00066   // Check if we're going to keep the organized structure of the cloud or not
00067   if (keep_organized_)
00068   {
00069     if (filter_field_name_.empty ())
00070     {
00071       // Silly - if no filtering is actually done, and we want to keep the data organized, 
00072       // just copy everything. Any optimizations that can be done here???
00073       output = *input_;
00074       return;
00075     }
00076 
00077     output.width = input_->width;
00078     output.height = input_->height;
00079     // Check what the user value is: if !finite, set is_dense to false, true otherwise
00080     if (!pcl_isfinite (user_filter_value_))
00081       output.is_dense = false;
00082     else
00083       output.is_dense = input_->is_dense;
00084   }
00085   else
00086   {
00087     // Copy the header (and thus the frame_id) + allocate enough space for points
00088     output.height = 1; // filtering breaks the organized structure
00089     // Because we're doing explit checks for isfinite, is_dense = true
00090     output.is_dense = true;
00091   }
00092   output.row_step = input_->row_step;
00093   output.point_step = input_->point_step;
00094   output.is_bigendian = input_->is_bigendian;
00095   output.data.resize (input_->data.size ());
00096 
00097   removed_indices_->resize (input_->data.size ());
00098 
00099   int nr_p = 0;
00100   int nr_removed_p = 0;
00101   // Create the first xyz_offset
00102   Eigen::Array4i xyz_offset (input_->fields[x_idx_].offset, input_->fields[y_idx_].offset,
00103                              input_->fields[z_idx_].offset, 0);
00104 
00105   Eigen::Vector4f pt = Eigen::Vector4f::Zero ();
00106   // If we don't want to process the entire cloud, but rather filter points far away from the viewpoint first...
00107   if (!filter_field_name_.empty ())
00108   {
00109     // Get the distance field index
00110     int distance_idx = pcl::getFieldIndex (*input_, filter_field_name_);
00111     if (distance_idx == -1)
00112     {
00113       PCL_WARN ("[pcl::%s::applyFilter] Invalid filter field name. Index is %d.\n", getClassName ().c_str (), distance_idx);
00114       output.width = output.height = 0;
00115       output.data.clear ();
00116       return;
00117     }
00118 
00119     // @todo fixme
00120     if (input_->fields[distance_idx].datatype != pcl::PCLPointField::FLOAT32)
00121     {
00122       PCL_ERROR ("[pcl::%s::downsample] Distance filtering requested, but distances are not float/double in the dataset! Only FLOAT32/FLOAT64 distances are supported right now.\n", getClassName ().c_str ());
00123       output.width = output.height = 0;
00124       output.data.clear ();
00125       return;
00126     }
00127 
00128     float badpt = std::numeric_limits<float>::quiet_NaN ();
00129     // Check whether we need to store filtered valued in place
00130     if (keep_organized_)
00131     {
00132       float distance_value = 0;
00133       // Go over all points
00134       for (int cp = 0; cp < nr_points; ++cp, xyz_offset += input_->point_step)
00135       {
00136         // Copy all the fields
00137         memcpy (&output.data[cp * output.point_step], &input_->data[cp * output.point_step], output.point_step);
00138 
00139         // Get the distance value
00140         memcpy (&distance_value, &input_->data[cp * input_->point_step + input_->fields[distance_idx].offset],
00141                 sizeof (float));
00142 
00143         if (filter_limit_negative_)
00144         {
00145           // Use a threshold for cutting out points which inside the interval
00146           if ((distance_value < filter_limit_max_) && (distance_value > filter_limit_min_))
00147           {
00148             // Unoptimized memcpys: assume fields x, y, z are in random order
00149             memcpy (&output.data[xyz_offset[0]], &badpt, sizeof (float));
00150             memcpy (&output.data[xyz_offset[1]], &badpt, sizeof (float));
00151             memcpy (&output.data[xyz_offset[2]], &badpt, sizeof (float));
00152             continue;
00153           }
00154           else
00155           {
00156             if (extract_removed_indices_)
00157               (*removed_indices_)[nr_removed_p++] = cp;
00158           }
00159         }
00160         else
00161         {
00162           // Use a threshold for cutting out points which are too close/far away
00163           if ((distance_value > filter_limit_max_) || (distance_value < filter_limit_min_))
00164           {
00165             // Unoptimized memcpys: assume fields x, y, z are in random order
00166             memcpy (&output.data[xyz_offset[0]], &badpt, sizeof (float));
00167             memcpy (&output.data[xyz_offset[1]], &badpt, sizeof (float));
00168             memcpy (&output.data[xyz_offset[2]], &badpt, sizeof (float));
00169             continue;
00170           }
00171           else
00172           {
00173             if (extract_removed_indices_)
00174               (*removed_indices_)[nr_removed_p++] = cp;
00175           }
00176         }
00177       }
00178     }
00179     // Remove filtered points
00180     else
00181     {
00182       // Go over all points
00183       float distance_value = 0;
00184       for (int cp = 0; cp < nr_points; ++cp, xyz_offset += input_->point_step)
00185       {
00186         // Get the distance value
00187         memcpy (&distance_value, &input_->data[cp * input_->point_step + input_->fields[distance_idx].offset],
00188                 sizeof(float));
00189 
00190         // Remove NAN/INF/-INF values. We expect passthrough to output clean valid data.
00191         if (!pcl_isfinite (distance_value))
00192         {
00193           if (extract_removed_indices_)
00194             (*removed_indices_)[nr_removed_p++] = cp;
00195           continue;
00196         }
00197 
00198         if (filter_limit_negative_)
00199         {
00200           // Use a threshold for cutting out points which inside the interval
00201           if (distance_value < filter_limit_max_ && distance_value > filter_limit_min_)
00202           {
00203             if (extract_removed_indices_)
00204             {
00205               (*removed_indices_)[nr_removed_p] = cp;
00206               nr_removed_p++;
00207             }
00208             continue;
00209           }
00210         }
00211         else
00212         {
00213           // Use a threshold for cutting out points which are too close/far away
00214           if (distance_value > filter_limit_max_ || distance_value < filter_limit_min_)
00215           {
00216             if (extract_removed_indices_)
00217             {
00218               (*removed_indices_)[nr_removed_p] = cp;
00219               nr_removed_p++;
00220             }
00221             continue;
00222           }
00223         }
00224 
00225         // Unoptimized memcpys: assume fields x, y, z are in random order
00226         memcpy (&pt[0], &input_->data[xyz_offset[0]], sizeof(float));
00227         memcpy (&pt[1], &input_->data[xyz_offset[1]], sizeof(float));
00228         memcpy (&pt[2], &input_->data[xyz_offset[2]], sizeof(float));
00229 
00230         // Check if the point is invalid
00231         if (!pcl_isfinite (pt[0]) || !pcl_isfinite (pt[1]) || !pcl_isfinite (pt[2]))
00232         {
00233           if (extract_removed_indices_)
00234           {
00235             (*removed_indices_)[nr_removed_p] = cp;
00236             nr_removed_p++;
00237           }
00238           continue;
00239         }
00240 
00241         // Copy all the fields
00242         memcpy (&output.data[nr_p * output.point_step], &input_->data[cp * output.point_step], output.point_step);
00243         nr_p++;
00244       }
00245       output.width = nr_p;
00246     } // !keep_organized_
00247   }
00248   // No distance filtering, process all data. No need to check for is_organized here as we did it above
00249   else
00250   {
00251     for (int cp = 0; cp < nr_points; ++cp, xyz_offset += input_->point_step)
00252     {
00253       // Unoptimized memcpys: assume fields x, y, z are in random order
00254       memcpy (&pt[0], &input_->data[xyz_offset[0]], sizeof(float));
00255       memcpy (&pt[1], &input_->data[xyz_offset[1]], sizeof(float));
00256       memcpy (&pt[2], &input_->data[xyz_offset[2]], sizeof(float));
00257 
00258       // Check if the point is invalid
00259       if (!pcl_isfinite (pt[0]) || !pcl_isfinite (pt[1]) || !pcl_isfinite (pt[2]))
00260       {
00261         if (extract_removed_indices_)
00262         {
00263           (*removed_indices_)[nr_removed_p] = cp;
00264           nr_removed_p++;
00265         }
00266         continue;
00267       }
00268 
00269       // Copy all the fields
00270       memcpy (&output.data[nr_p * output.point_step], &input_->data[cp * output.point_step], output.point_step);
00271       nr_p++;
00272     }
00273     output.width = nr_p;
00274   }
00275 
00276   output.row_step = output.point_step * output.width;
00277   output.data.resize (output.width * output.height * output.point_step);
00278 
00279   removed_indices_->resize (nr_removed_p);
00280 }
00281 
00282 #ifndef PCL_NO_PRECOMPILE
00283 #include <pcl/impl/instantiate.hpp>
00284 #include <pcl/point_types.h>
00285 
00286 // Instantiations of specific point types
00287 PCL_INSTANTIATE(PassThrough, PCL_XYZ_POINT_TYPES)
00288 
00289 #endif    // PCL_NO_PRECOMPILE
00290 


pcl
Author(s): Open Perception
autogenerated on Wed Aug 26 2015 15:27:44