Point Cloud Library (PCL)  1.4.0
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines
point_cloud.h
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-2011, Willow Garage, Inc.
00006  *
00007  *  All rights reserved.
00008  *
00009  *  Redistribution and use in source and binary forms, with or without
00010  *  modification, are permitted provided that the following conditions
00011  *  are met:
00012  *
00013  *   * Redistributions of source code must retain the above copyright
00014  *     notice, this list of conditions and the following disclaimer.
00015  *   * Redistributions in binary form must reproduce the above
00016  *     copyright notice, this list of conditions and the following
00017  *     disclaimer in the documentation and/or other materials provided
00018  *     with the distribution.
00019  *   * Neither the name of Willow Garage, Inc. nor the names of its
00020  *     contributors may be used to endorse or promote products derived
00021  *     from this software without specific prior written permission.
00022  *
00023  *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
00024  *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
00025  *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
00026  *  FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
00027  *  COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
00028  *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
00029  *  BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
00030  *  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
00031  *  CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
00032  *  LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
00033  *  ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
00034  *  POSSIBILITY OF SUCH DAMAGE.
00035  *
00036  * $Id: point_cloud.h 3746 2011-12-31 22:19:47Z rusu $
00037  *
00038  */
00039 
00040 #ifndef PCL_POINT_CLOUD_H_
00041 #define PCL_POINT_CLOUD_H_
00042 
00043 #include <Eigen/StdVector>
00044 #include <Eigen/Geometry>
00045 #include <cstddef>
00046 #include <std_msgs/Header.h>
00047 #include <pcl/pcl_macros.h>
00048 #include <pcl/exceptions.h>
00049 #include <pcl/cloud_properties.h>
00050 #include <pcl/channel_properties.h>
00051 #include <pcl/point_traits.h>
00052 #include <pcl/for_each_type.h>
00053 #include <boost/shared_ptr.hpp>
00054 #include <map>
00055 #include <boost/mpl/size.hpp>
00056 
00057 namespace pcl
00058 {
00059   namespace detail
00060   {
00061     struct FieldMapping
00062     {
00063       size_t serialized_offset;
00064       size_t struct_offset;
00065       size_t size;
00066     };
00067   } // namespace detail
00068 
00069 
00070   // Forward declarations
00071   template <typename PointT> class PointCloud;
00072   typedef std::vector<detail::FieldMapping> MsgFieldMap;
00073   template <typename PointT> struct NdCopyEigenPointFunctor;
00074   template <typename PointT> struct NdCopyPointEigenFunctor;
00075  
00076   namespace detail
00077   {
00078     template <typename PointT> boost::shared_ptr<pcl::MsgFieldMap>&
00079     getMapping (pcl::PointCloud<PointT>& p);
00080   } // namespace detail
00081 
00115   template <typename PointT>
00116   class PointCloud
00117   {
00118     public:
00123       PointCloud () : width (0), height (0), is_dense (true),
00124                       sensor_origin_ (Eigen::Vector4f::Zero ()), sensor_orientation_ (Eigen::Quaternionf::Identity ())
00125       {}
00126 
00130       inline PointCloud (PointCloud<PointT> &pc)
00131       {
00132         *this = pc;
00133       }
00134 
00138       inline PointCloud (const PointCloud<PointT> &pc)
00139       {
00140         *this = pc;
00141       }
00142 
00147       inline PointCloud (const PointCloud<PointT> &pc, 
00148                          const std::vector<int> &indices)
00149       {
00150         // Copy the obvious
00151         width    = indices.size ();
00152         height   = 1;
00153         is_dense = pc.is_dense;
00154         header = pc.header;
00155         sensor_origin_ = pc.sensor_origin_;
00156         sensor_orientation_ = pc.sensor_orientation_;
00157 
00158         assert (indices.size () <= pc.size ());
00159         points.resize (indices.size ());
00160         for (size_t i = 0; i < indices.size (); i++)
00161           points[i] = pc.points[indices[i]];
00162       }
00163 
00168       inline PointCloud (uint32_t width_, uint32_t height_)
00169         : points (width_ * height_)
00170         , width (width_)
00171         , height (height_)
00172         , is_dense (true)
00173         , sensor_origin_ (Eigen::Vector4f::Zero ())
00174         , sensor_orientation_ (Eigen::Quaternionf::Identity ())
00175       {}
00176 
00178       virtual ~PointCloud () {}
00179 
00181 
00185       inline PointCloud&
00186       operator += (const PointCloud& rhs)
00187       {
00188         // Make the resultant point cloud take the newest stamp
00189         if (rhs.header.stamp > header.stamp)
00190           header.stamp = rhs.header.stamp;
00191 
00192         size_t nr_points = points.size ();
00193         points.resize (nr_points + rhs.points.size ());
00194         for (size_t i = nr_points; i < points.size (); ++i)
00195           points[i] = rhs.points[i - nr_points];
00196 
00197         width    = (uint32_t) points.size ();
00198         height   = 1;
00199         if (rhs.is_dense && is_dense)
00200           is_dense = true;
00201         else
00202           is_dense = false;
00203         return (*this);
00204       }
00205 
00207 
00211       inline const PointCloud
00212       operator + (const PointCloud& rhs)
00213       {
00214         return (PointCloud (*this) += rhs);
00215       }
00216       
00218 
00223       inline const PointT&
00224       at (int u, int v) const
00225       {
00226         if (this->height > 1)
00227           return (points.at (v * this->width + u));
00228         else
00229           throw IsNotDenseException ("Can't use 2D indexing with a unorganized point cloud");
00230       }
00231 
00237       inline PointT&
00238       at (int u, int v)
00239       {
00240         if (this->height > 1)
00241           return (points.at (v * this->width + u));
00242         else
00243           throw IsNotDenseException ("Can't use 2D indexing with a unorganized point cloud");
00244       }
00245 
00247 
00252       inline const PointT&
00253       operator () (int u, int v) const
00254       {
00255         return (points[v * this->width + u]);
00256       }
00257 
00263       inline PointT&
00264       operator () (int u, int v)
00265       {
00266         return (points[v * this->width + u]);
00267       }
00268 
00270 
00273       inline bool
00274       isOrganized () const
00275       {
00276         return (height != 1);
00277       }
00278       
00280 
00295       inline Eigen::Map<Eigen::MatrixXf, Eigen::Aligned, Eigen::OuterStride<> > 
00296       getMatrixXfMap (int dim, int stride, int offset)
00297       {
00298         //return Eigen::Map<Eigen::MatrixXf, Eigen::Aligned, Eigen::OuterStride<> >((float*)(&points[0])+offset, dim, points.size(), Eigen::OuterStride<>(stride));
00299         return (Eigen::Map<Eigen::MatrixXf, Eigen::Aligned, Eigen::OuterStride<> >((float*)(&points[0])+offset, points.size (), dim, Eigen::OuterStride<> (stride)));
00300       }
00301 
00317       inline const Eigen::Map<const Eigen::MatrixXf, Eigen::Aligned, Eigen::OuterStride<> >
00318       getMatrixXfMap (int dim, int stride, int offset) const
00319       {
00320         return (Eigen::Map<Eigen::MatrixXf, Eigen::Aligned, Eigen::OuterStride<> >((float*)(&points[0])+offset, points.size (), dim, Eigen::OuterStride<> (stride)));
00321       }
00322 
00324 
00329       inline Eigen::Map<Eigen::MatrixXf, Eigen::Aligned, Eigen::OuterStride<> >
00330       getMatrixXfMap () 
00331       {
00332         return (getMatrixXfMap (sizeof (PointT) / sizeof (float),  sizeof (PointT) / sizeof (float), 0));
00333       }
00334 
00340       inline const Eigen::Map<const Eigen::MatrixXf, Eigen::Aligned, Eigen::OuterStride<> >
00341       getMatrixXfMap () const
00342       {
00343         return (getMatrixXfMap (sizeof (PointT) / sizeof (float),  sizeof (PointT) / sizeof (float), 0));
00344       }
00345 
00347       std_msgs::Header header;
00348 
00350       std::vector<PointT, Eigen::aligned_allocator<PointT> > points;
00351 
00353       uint32_t width;
00355       uint32_t height;
00356 
00358       bool is_dense;
00359 
00361       Eigen::Vector4f    sensor_origin_;
00363       Eigen::Quaternionf sensor_orientation_;
00364 
00365       typedef PointT PointType;  // Make the template class available from the outside
00366       typedef std::vector<PointT, Eigen::aligned_allocator<PointT> > VectorType;
00367       typedef boost::shared_ptr<PointCloud<PointT> > Ptr;
00368       typedef boost::shared_ptr<const PointCloud<PointT> > ConstPtr;
00369 
00370       // iterators
00371       typedef typename VectorType::iterator iterator;
00372       typedef typename VectorType::const_iterator const_iterator;
00373       inline iterator begin () { return (points.begin ()); }
00374       inline iterator end ()   { return (points.end ()); }
00375       inline const_iterator begin () const { return (points.begin ()); }
00376       inline const_iterator end () const  { return (points.end ()); }
00377 
00378       //capacity
00379       inline size_t size () const { return (points.size ()); }
00380       inline void reserve (size_t n) { points.reserve (n); }
00381       inline void resize (size_t n) { points.resize (n); }
00382       inline bool empty () const { return points.empty (); }
00383 
00384       //element access
00385       inline const PointT& operator[] (size_t n) const { return points[n]; }
00386       inline PointT& operator[] (size_t n) { return points[n]; }
00387       inline const PointT& at (size_t n) const { return points.at (n); }
00388       inline PointT& at (size_t n) { return points.at (n); }
00389       inline const PointT& front () const { return points.front (); }
00390       inline PointT& front () { return points.front (); }
00391       inline const PointT& back () const { return points.back (); }
00392       inline PointT& back () { return points.back (); }
00393 
00398       inline void 
00399       push_back (const PointT& pt)
00400       {
00401         points.push_back (pt);
00402         width = points.size ();
00403         height = 1;
00404       }
00405 
00412       inline iterator 
00413       insert (iterator position, const PointT& pt)
00414       {
00415         iterator it = points.insert (position, pt);
00416         width = points.size ();
00417         height = 1;
00418         return (it);
00419       }
00420 
00427       inline void 
00428       insert (iterator position, size_t n, const PointT& pt)
00429       {
00430         points.insert (position, n, pt);
00431         width = points.size ();
00432         height = 1;
00433       }
00434 
00441       template <class InputIterator> inline void 
00442       insert (iterator position, InputIterator first, InputIterator last)
00443       {
00444         points.insert (position, first, last);
00445         width = points.size ();
00446         height = 1;
00447       }
00448 
00454       inline iterator 
00455       erase (iterator position)
00456       {
00457         iterator it = points.erase (position); 
00458         width = points.size ();
00459         height = 1;
00460         return (it);
00461       }
00462 
00469       inline iterator 
00470       erase (iterator first, iterator last)
00471       {
00472         iterator it = points.erase (first, last);
00473         width = points.size ();
00474         height = 1;
00475         return (it);
00476       }
00477 
00481       inline void 
00482       swap (PointCloud<PointT> &rhs)
00483       {
00484         this->points.swap (rhs.points);
00485         std::swap (width, rhs.width);
00486         std::swap (height, rhs.height);
00487         std::swap (is_dense, rhs.is_dense);
00488         std::swap (sensor_origin_, rhs.sensor_origin_);
00489         std::swap (sensor_orientation_, rhs.sensor_orientation_);
00490       }
00491 
00493       inline void 
00494       clear ()
00495       {
00496         points.clear ();
00497         width = 0;
00498         height = 0;
00499       }
00500 
00506       inline Ptr 
00507       makeShared () { return Ptr (new PointCloud<PointT> (*this)); }
00508 
00513       inline ConstPtr 
00514       makeShared () const { return ConstPtr (new PointCloud<PointT> (*this)); }
00515 
00516     protected:
00517       // This is motivated by ROS integration. Users should not need to access mapping_.
00518       boost::shared_ptr<MsgFieldMap> mapping_;
00519 
00520       friend boost::shared_ptr<MsgFieldMap>& detail::getMapping<PointT>(pcl::PointCloud<PointT> &p);
00521 
00522     public:
00523       EIGEN_MAKE_ALIGNED_OPERATOR_NEW;
00524   };
00525 
00544   template <>
00545   class PointCloud<Eigen::MatrixXf> 
00546   {
00547     public:
00551       PointCloud () : 
00552         points (Eigen::MatrixXf (0, 0)), width (0), height (0), is_dense (true)
00553       {}
00554 
00558       inline PointCloud (PointCloud<Eigen::MatrixXf> &pc)
00559       {
00560         *this = pc;
00561       }
00562  
00566       template <typename PointT>
00567       inline PointCloud (PointCloud<PointT> &pc)
00568       {
00569         // Copy the obvious
00570         width    = pc.width;
00571         height   = pc.height;
00572         is_dense = pc.is_dense;
00573         properties.acquisition_time   = pc.header.stamp;
00574         properties.sensor_origin      = pc.sensor_origin_;//.head<3> ();
00575         properties.sensor_orientation = pc.sensor_orientation_;
00576 
00577         typedef typename pcl::traits::fieldList<PointT>::type FieldList;
00578         // Copy the fields
00579         // ...
00580 
00581         // Resize the array
00582         points.resize (pc.points.size (), boost::mpl::size<FieldList>::value);
00583 
00584         for (size_t cp = 0; cp < pc.points.size (); ++cp)
00585           pcl::for_each_type <FieldList> (NdCopyPointEigenFunctor<PointT> (pc.points[cp], points.row (cp)));
00586       }
00587  
00591       inline PointCloud (const PointCloud<Eigen::MatrixXf> &pc)
00592       {
00593         *this = pc;
00594       }
00595 
00599       template <typename PointT>
00600       inline PointCloud (const PointCloud<PointT> &pc)
00601       {
00602         // Copy the obvious
00603         width    = pc.width;
00604         height   = pc.height;
00605         is_dense = pc.is_dense;
00606         properties.acquisition_time   = pc.header.stamp;
00607         properties.sensor_origin      = pc.sensor_origin_;//.head<3> ();
00608         properties.sensor_orientation = pc.sensor_orientation_;
00609 
00610         typedef typename pcl::traits::fieldList<PointT>::type FieldList;
00611 
00612         // Copy the fields
00613         // ...
00614 
00615         // Resize the array
00616         points.resize (pc.points.size (), boost::mpl::size<FieldList>::value);
00617 
00618         for (size_t cp = 0; cp < pc.points.size (); ++cp)
00619           pcl::for_each_type <FieldList> (NdCopyPointEigenFunctor<PointT> (pc.points[cp], points.row (cp)));
00620       }
00621 
00626       inline PointCloud (const PointCloud &pc, 
00627                          const std::vector<int> &indices)
00628       {
00629         // Copy the obvious
00630         width    = indices.size ();
00631         height   = 1;
00632         is_dense = pc.is_dense;
00633         properties = pc.properties;
00634         channels = pc.channels;
00635 
00636         assert ((int)indices.size () <= pc.points.rows ());
00637         points.resize (indices.size (), pc.points.cols ());
00638         for (size_t i = 0; i < indices.size (); i++)
00639           points.row (i) = pc.points.row (indices[i]);
00640       }
00641 
00647       inline PointCloud (uint32_t _width, uint32_t _height, uint32_t _dim)
00648         : points (Eigen::MatrixXf (_width * _height, _dim))
00649         , width (_width)
00650         , height (_height)
00651         , is_dense (true)
00652       {}
00653 
00658       inline PointCloud (uint32_t _num_points, uint32_t _dim)
00659         : points (Eigen::MatrixXf (_num_points, _dim))
00660         , width (_num_points)
00661         , height (1)
00662         , is_dense (true)
00663       {}
00664 
00666       virtual ~PointCloud () {}
00667 
00669 
00673       inline PointCloud&
00674       operator += (const PointCloud& rhs)
00675       {
00676         if (rhs.properties.acquisition_time > properties.acquisition_time)
00677           properties.acquisition_time = rhs.properties.acquisition_time;
00678 
00679         properties.sensor_origin = Eigen::Vector4f::Zero ();
00680         properties.sensor_orientation = Eigen::Quaternionf::Identity ();
00681 
00682         int nr_points = points.rows ();
00683         points.resize (nr_points + rhs.points.rows (), points.cols ());
00684         for (int i = nr_points; i < points.rows (); ++i)
00685           points.row (i) = rhs.points.row (i - nr_points);
00686 
00687         channels = rhs.channels;
00688         width    = (uint32_t) points.rows ();
00689         height   = 1;
00690         if (rhs.is_dense && is_dense)
00691           is_dense = true;
00692         else
00693           is_dense = false;
00694         return (*this);
00695       }
00696       
00698 
00702       inline const PointCloud
00703       operator + (const PointCloud& rhs)
00704       {
00705         return (PointCloud (*this) += rhs);
00706       }
00707 
00709 
00714       inline Eigen::Map<Eigen::VectorXf>
00715       at (int u, int v)
00716       {
00717         if (height > 1)
00718           return (Eigen::VectorXf::Map (&points (v * width + u, 0), points.cols ()));
00719         else
00720           throw IsNotDenseException ("Can't use 2D indexing with a unorganized point cloud");
00721       }
00722 
00724 
00729       inline Eigen::Map<Eigen::VectorXf>
00730       operator () (int u, int v) 
00731       {
00732         return (Eigen::VectorXf::Map (&points (v * width + u, 0), points.cols ()));
00733       }
00734 
00736 
00739       inline bool
00740       isOrganized () const
00741       {
00742         return (height != 1);
00743       }
00744       
00746       pcl::CloudProperties properties;
00747 
00749       Eigen::MatrixXf points;
00750 
00752       std::map<std::string, pcl::ChannelProperties> channels;
00753 
00755       uint32_t width;
00757       uint32_t height;
00758 
00760       bool is_dense;
00761 
00762       typedef boost::shared_ptr<PointCloud<Eigen::MatrixXf> > Ptr;
00763       typedef boost::shared_ptr<const PointCloud<Eigen::MatrixXf> > ConstPtr;
00764 
00768       inline void 
00769       swap (PointCloud<Eigen::MatrixXf> &rhs)
00770       {
00771         std::swap (points, rhs.points);
00772         std::swap (width, rhs.width);
00773         std::swap (height, rhs.height);
00774         std::swap (is_dense, rhs.is_dense);
00775         std::swap (properties, rhs.properties);
00776         std::swap (channels, rhs.channels);
00777       }
00778 
00780       inline void 
00781       clear ()
00782       {
00783         points.resize (0, 0);
00784         width = 0;
00785         height = 0;
00786       }
00787 
00793       inline Ptr 
00794       makeShared () { return Ptr (new PointCloud<Eigen::MatrixXf> (*this)); }
00795 
00800       inline ConstPtr 
00801       makeShared () const { return ConstPtr (new PointCloud<Eigen::MatrixXf> (*this)); }
00802 
00803     public:
00804       EIGEN_MAKE_ALIGNED_OPERATOR_NEW;
00805   };
00806 
00808 
00809   template <typename PointT>
00810   struct NdCopyEigenPointFunctor
00811   {
00812     typedef typename traits::POD<PointT>::type Pod;
00813     
00818     NdCopyEigenPointFunctor (const Eigen::VectorXf &p1, PointT &p2)
00819       : p1_ (p1),
00820         p2_ (reinterpret_cast<Pod&>(p2)),
00821         f_idx_ (0) { }
00822 
00824     template<typename Key> inline void 
00825     operator() ()
00826     {
00827       //boost::fusion::at_key<Key> (p2_) = p1_[f_idx_++];
00828       typedef typename pcl::traits::datatype<PointT, Key>::type T;
00829       uint8_t* data_ptr = reinterpret_cast<uint8_t*>(&p2_) + pcl::traits::offset<PointT, Key>::value;
00830       *reinterpret_cast<T*>(data_ptr) = p1_[f_idx_++];
00831     }
00832 
00833     private:
00834       const Eigen::VectorXf &p1_;
00835       Pod &p2_;
00836       int f_idx_;
00837     public:
00838       EIGEN_MAKE_ALIGNED_OPERATOR_NEW;
00839    };
00840 
00842 
00843   template <typename PointT>
00844   struct NdCopyPointEigenFunctor
00845   {
00846     typedef typename traits::POD<PointT>::type Pod;
00847     
00852      NdCopyPointEigenFunctor (const PointT &p1, Eigen::VectorXf &p2)
00853       : p1_ (reinterpret_cast<const Pod&>(p1)), p2_ (p2), f_idx_ (0) { }
00854 
00856     template<typename Key> inline void 
00857     operator() ()
00858     {
00859       //p2_[f_idx_++] = boost::fusion::at_key<Key> (p1_);
00860       typedef typename pcl::traits::datatype<PointT, Key>::type T;
00861       const uint8_t* data_ptr = reinterpret_cast<const uint8_t*>(&p1_) + pcl::traits::offset<PointT, Key>::value;
00862       p2_[f_idx_++] = *reinterpret_cast<const T*>(data_ptr);
00863     }
00864 
00865     private:
00866       const Pod &p1_;
00867       Eigen::VectorXf &p2_;
00868       int f_idx_;
00869     public:
00870       EIGEN_MAKE_ALIGNED_OPERATOR_NEW;
00871    };
00872 
00874   namespace detail
00875   {
00876     template <typename PointT> boost::shared_ptr<pcl::MsgFieldMap>&
00877     getMapping (pcl::PointCloud<PointT>& p)
00878     {
00879       return (p.mapping_);
00880     }
00881   } // namespace detail
00882 
00883   template <typename PointT> std::ostream&
00884   operator << (std::ostream& s, const pcl::PointCloud<PointT> &p)
00885   {
00886     s << "points[]: " << p.points.size () << std::endl;
00887     s << "width: " << p.width << std::endl;
00888     s << "height: " << p.height << std::endl;
00889     s << "is_dense: " << p.is_dense << std::endl;
00890     return (s);
00891   }
00892 }
00893 
00894 #endif  //#ifndef PCL_POINT_CLOUD_H_
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines