|
Point Cloud Library (PCL)
1.4.0
|
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_
1.7.6.1