iLab Neuromorphic Robotics Toolkit  0.1
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
PointCloud2.H
Go to the documentation of this file.
1 /*! @file
2  @author Shane Grant
3  @copyright GNU Public License (GPL v3)
4  @section License
5  @verbatim
6  // ////////////////////////////////////////////////////////////////////////
7  // The iLab Neuromorphic Robotics Toolkit (NRT) //
8  // Copyright 2010-2012 by the University of Southern California (USC) //
9  // and the iLab at USC. //
10  // //
11  // iLab - University of Southern California //
12  // Hedco Neurociences Building, Room HNB-10 //
13  // Los Angeles, Ca 90089-2520 - USA //
14  // //
15  // See http://ilab.usc.edu for information about this project. //
16  // ////////////////////////////////////////////////////////////////////////
17  // This file is part of The iLab Neuromorphic Robotics Toolkit. //
18  // //
19  // The iLab Neuromorphic Robotics Toolkit is free software: you can //
20  // redistribute it and/or modify it under the terms of the GNU General //
21  // Public License as published by the Free Software Foundation, either //
22  // version 3 of the License, or (at your option) any later version. //
23  // //
24  // The iLab Neuromorphic Robotics Toolkit is distributed in the hope //
25  // that it will be useful, but WITHOUT ANY WARRANTY; without even the //
26  // implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR //
27  // PURPOSE. See the GNU General Public License for more details. //
28  // //
29  // You should have received a copy of the GNU General Public License //
30  // along with The iLab Neuromorphic Robotics Toolkit. If not, see //
31  // <http://www.gnu.org/licenses/>. //
32  // ////////////////////////////////////////////////////////////////////////
33  @endverbatim */
34 
35 #ifndef INCLUDE_NRT_POINTCLOUD2_POINTCLOUD2_H
36 #define INCLUDE_NRT_POINTCLOUD2_POINTCLOUD2_H
37 
38 #include <nrt/config.h>
39 #ifdef NRT_HAVE_CLOUD
40 
41 #include <type_traits>
42 #include <memory>
48 
50 
51 #include <nrt/External/cereal/types/memory.hpp>
52 
53 namespace nrt
54 {
55  //! A class for representing point clouds
56  /*! PointClouds are collections of data associated with
57  geometrically defined points. This class allows for
58  arbitrary data to be associated with a point cloud
59  in addition to the basic geometry.
60 
61  A CMAKE compilation flag, POINTCLOUD_DOUBLE, determines whether
62  the base type of the point cloud will use single or double
63  precision floating point numbers for the geometry. The
64  geometry fields will define a three dimensional homogenous point
65  (XYZ + W) that is the core of a pointcloud.
66 
67  Additional fields can be added onto a point cloud allowing
68  each geometrical point to be associated with additional data.
69  These fields can be dense or sparse but will always be tied
70  to an existing geometrical point in the point cloud. Point
71  clouds cannot store information that does not directly
72  relate to their geometry.
73 
74  Dense fields will have a 1:1 correspondence with geometry
75  while sparse fields do not need to obey this; you are allowed
76  to have a geometrical entry without having an associated
77  sparse entry.
78 
79  Sparse fields are denoted as sparse when they are created
80  by wrapping a type in the SparseField<> template,
81  but apart from that point operate without the need for
82  an explicit demarcation. Point clouds have the restriction
83  that any field added, regardless of whether it is dense or
84  sparse, must be unique when judged on an std::is_same
85  basis.
86 
87  In general sparse data will be slower to access or insert
88  and should only be used when the tradeoff between size and
89  decreased performance makes sense.
90 
91  It should be noted that regardless of the data type accessed
92  in a Point Cloud, if it is specified as a specific dense
93  or sparse field as a template parameter, there is a small
94  cost associated with an implementation specific lookup that
95  must occur. This means that code that relies on calling
96  functionality that specifies explicit fields should be be
97  avoided in loops if possible. For example, the creation of
98  iterator objects incurs this lookup cost, but the actual use
99  of iterators does not - thus for maximum performance if the
100  size/order of a point cloud will not change during iteration,
101  it is best to avoid calculating end iterators at each
102  iteration. The cost of this lookup is small in isolation, but
103  used incorrectly in looping situations can result in degraded
104  performance.
105 
106  PointClouds are reference counted and utilize a copy-on-write
107  mechanism similar to nrt::Array. This means that any
108  function of PointCloud2 that can modify its contents in any fashion
109  may perform a deep copy to obtain unique ownership of the underlying
110  data. Constant accessors will never perform a deep copy. If you
111  are the sole owner of the data, a deep copy will not occur.
112 
113  Since PointClouds use reference counting to manage their memory, you
114  should follow sensible conventions in multi-threaded environments
115  regarding passing by value or by reference: if it is not known whether
116  a stable reference to a cloud exists, pass by value: it will increment
117  the reference count and keep the memory safe until it has been used.
118  Otherwise, if it is known that a stable reference to a cloud will exist
119  throughout the lifetime of a function where it has been passed by reference,
120  then there is no need to pass by value. Passing by value incurs a slightly
121  higher overhead due to an atomic lookup that must occur. This information
122  only applies to clouds that are passed as const. Non const clouds will
123  always incur a deep copy as soon as they are modified.
124 
125  @ingroup pointcloud
126  */
128  {
129  public:
130  /*! @anchor PointCloud2TypedefsGroup
131  @name Convenience typedefs
132  The following typedefs allow easy access of related structures
133  that depend upon the point cloud base type */
134  //! @{
135  //! The base type for a point cloud, determined by a CMAKE compilation flag
136  typedef POINTCLOUD2_BASE_TYPE BaseType;
137 
138  //! The type of the underlying geometry
140 
141  //! A 3x1 vector
142  typedef Eigen::Matrix<POINTCLOUD2_BASE_TYPE, 3, 1> Vector3;
143  //! A 4x1 vector
144  typedef Eigen::Matrix<POINTCLOUD2_BASE_TYPE, 4, 1> Vector4;
145  //! An Nx1 vector
146  typedef Eigen::Matrix<POINTCLOUD2_BASE_TYPE, Eigen::Dynamic, 1> VectorX;
147 
148  //! A 3x3 matrix
149  typedef Eigen::Matrix<POINTCLOUD2_BASE_TYPE, 3, 3> Matrix3;
150  //! A 4x4 matrix
151  typedef Eigen::Matrix<POINTCLOUD2_BASE_TYPE, 4, 4> Matrix4;
152  //! An NxN matrix
153  typedef Eigen::Matrix<POINTCLOUD2_BASE_TYPE, Eigen::Dynamic, Eigen::Dynamic> MatrixX;
154 
155  //! An affine transformation matrix
156  typedef Eigen::Transform<POINTCLOUD2_BASE_TYPE, 3, Eigen::Affine> AffineTransform;
157  //! @}
158 
159  /*! @name Constructors and assignment operators
160  @anchor PointCloud2ConstructorGroup */
161  //! @{
162 
163  //! Create an empty point cloud with no fields
164  /*! The created point cloud will have geometrical data
165  (as all point clouds do), but no additional dense
166  or sparse fields
167  @param initialSize The initial size for the point cloud. Note that any
168  geometry allocated here will be completely zero valued
169  and thus not a valid homogenous point. It is best to
170  consider the data as allocated but un-initialized. */
171  PointCloud2( size_t initialSize = 0);
172 
173  //! @}
174 
175  //! Create an empty point cloud with a set of fields
176  /*! This adds fields to the point cloud, giving it
177  the capability of storing various data types.
178  Data types must be distinct from an std::is_same
179  basis regardless of whether they are dense or sparse.
180 
181  Data types are assumed to be dense by default and can
182  be marked as sparse by wrapping in the template class
183  SparseField<>. Fields marked as sparse only need
184  to be marked as sparse during insertion and can
185  be utilized without the SparseField<> template
186  wrapper in all other functions.
187 
188  Sparse fields will only store data for indicies that
189  have been initialized with some information. Sparse
190  fields are slower to access and should be used
191  when the tradeoff between space and time makes sense.
192 
193  The point cloud will also, as all clouds do, contain
194  geometrical data for each entry.
195 
196  @tparam Fields A set of fields to add
197  @param initialSize The initial size for the point cloud. Note that any
198  geometry or other fields allocated here will be completely
199  zero valued and thus likely not valid data. It is best
200  to consider the data (including geometry) as allocated
201  but not initialized */
202  template <class ... Fields>
203  static PointCloud2 create( size_t initialSize = 0 );
204 
205  /*! @name Constructors and assignment operators */
206  //! @{
207 
208  //! Create from an already existing cloud
209  /*! This will create a shallow copy of the other cloud
210  that will only become a deep copy upon modification
211  or an explicit call to deepCopy() */
212  PointCloud2( PointCloud2 const & other );
213 
214  //! Move from an already existing cloud
215  /*! This will move the data from another cloud into this one
216  and cause the other cloud to become invalid. Using an
217  invalid cloud will result in undefined behavior */
218  PointCloud2( PointCloud2 && other );
219 
220  //! Destructor
221  ~PointCloud2();
222 
223  //! Assignment operator
224  /*! This will create a shallow copy of the other cloud
225  that will only become a deep copy upon modification
226  or an explicit call to deepCopy() */
227  PointCloud2 & operator=( PointCloud2 const & other );
228 
229  //! R value move assignment operator
230  /*! This will result in the other point cloud being made
231  invalid; using an invalid point cloud will result in
232  undefined behavior */
233  PointCloud2 & operator=( PointCloud2 && other );
234 
235  //! @}
236  /*! @anchor PointCloud2FieldOperationsGroup
237  @name Field operations
238  Functionality concerned with inserting, deleting,
239  or otherwise querying the dense or sparse fields
240  of a point cloud. */
241  //! @{
242 
243  //! Adds fields to this point cloud
244  /*! This adds a field to the point cloud, giving it
245  the capability of storing a particular data type.
246  Data types must be distinct from an std::is_same
247  basis regardless of whether they are dense or sparse.
248 
249  Data types are assumed to be dense by default and can
250  be marked as sparse by wrapping in the template class
251  SparseField<>. Fields marked as sparse only need
252  to be marked as sparse during insertion and can
253  be utilized without the SparseField<> template
254  wrapper in all other functions.
255 
256  Sparse fields will only store data for indicies that
257  have been initialized with some information. Sparse
258  fields are slower to access and should be used
259  when the tradeoff between space and time makes sense.
260 
261  Dense fields will be initialized with zero valued data
262  which may be invalid depending on their type.
263 
264  If a field already exists, calling addField with it again
265  will do nothing.
266 
267  @tparam Fields A set of fields to add */
268  template <class ... Fields>
269  void addField();
270 
271  //! Removes fields from the point cloud
272  /*! Removing a field will delete all data associated with
273  it in the point cloud.
274 
275  For sparse fields, there is no need to specify the
276  type as sparse with SparseField<> as this will be
277  automatically inferred for a sparse field. If
278  this is specified, it will be automatically stripped.
279 
280  @tparam Fields The fields to remove */
281  template <class ... Fields>
282  void removeField();
283 
284  //! Checks if the point cloud contains a specific field, dense or sparse
285  /*! SparseField<> will be stripped if present and is
286  not necessary.
287  @tparam T The field type to check */
288  template <class T>
289  bool hasField() const;
290 
291  //! Checks if the point cloud contains a specific dense field
292  template <class T>
293  bool hasDenseField() const;
294 
295  //! Checks if the point cloud contains a specific sparse field
296  /*! SparseField<> will be stripped if present and is
297  not necessary.
298  @tparam T The field type to check */
299  template <class T>
300  bool hasSparseField() const;
301 
302  //! Checks whether a specific index in the point cloud contains data of a particular sparse type
303  /*! SparseField<> will be stripped if present and is not necessary
304  @tparam T The field type to check
305  @param index The index to check
306  @return Whether the requested index contains the type of sparse data */
307  template <class T>
308  bool hasSparseData( size_t const index ) const;
309 
310  //! Assuming the requested field is sparse, retrieves all indices that contain the field
311  /*! SparseField<> will be stripped if present and is not necessary
312  @tparam T The field type to check
313  @return All indices that contain the sparse data. */
314  template <class T>
315  Indices getSparseIndices() const;
316 
317  //! Checks if a point cloud has the same fields as another
318  bool hasSameFields( PointCloud2 const other ) const;
319 
320  //! Gets the number of dense entries in the point cloud
321  size_t size() const;
322 
323  //! Gets the number of entries for a particular field
324  /*! SparseField<> will be stripped if present and is
325  not necessary
326  @tparam T The type to check the size of */
327  template <class T>
328  size_t size() const;
329 
330  //! Gets whether the cloud is completely empty (no dense entries)
331  bool empty() const;
332 
333  //! @}
334 
335  //! @anchor PointCloud2ElementAccessGroup
336  /*! @name Individual element access
337  Functions to query individual elements from a point
338  cloud. In general, this will be slower than using
339  iterators to access multiple elements */
340  //! @{
341 
342  //! Returns a reference to the geometry at the specified index
343  Geometry & operator[]( size_t index );
344 
345  //! Returns a const reference to the geometry at the specified index
346  Geometry const & operator[]( size_t index ) const;
347 
348  //! Returns a reference to the geometry at the specified index
349  /*! The data contained in the returned point will reference data
350  stored in the cloud; modifying this structure will directly
351  modify the data internal to the point cloud */
352  PointCloud2DataRef<> get( size_t index );
353 
354  //! Returns a reference to fields at the requested index
355  /*! If the requested fields do not exist inside of the point cloud,
356  an exception will be thrown.
357 
358  Sparse fields do not (and should not) need to be explicitly specified as sparse
359  using SparseField<>. This will be stripped if present.
360 
361  Geometry is always included regardless of fields specified.
362 
363  @tparam Fields The fields to iterate over
364 
365  @throws PointCloud2FieldsException If at least one field does not exist in the cloud */
366  template <class ... Fields>
368 
369  //! Returns a constant reference to the geometry at the specified index
370  PointCloud2ConstDataRef<> at( size_t index ) const;
371 
372  //! Returns a constant reference to fields at the requested index
373  /*! If the requested fields do not exist inside of the point cloud,
374  an exception will be thrown.
375 
376  Sparse fields do not (and should not) need to be explicitly specified as sparse
377  using SparseField<>. This will be stripped if present.
378 
379  Geometry is always included regardless of fields specified.
380 
381  @tparam Fields The fields to iterate over
382 
383  @throws PointCloud2FieldsException If at least one field does not exist in the cloud */
384  template <class ... Fields>
386 
387  //! @}
388 
389  //! An iterator for going over only geometry
391  //! An iterator for going over only constant geometry
393 
394  //! An iterator over geometry and other fields
395  /*! Creating one of these iterators may cause a deep copy of the underlying data to occur if
396  not the sole owner of the data. When possible, constant iterators should be used as
397  these do not incur a deep copy penalty
398 
399  Iterators will always include a reference to the geometry and this needs not be
400  specified during their creation.
401 
402  Dereferencing an iterator works in a similar fashion to the get() and at() functions of
403  PointCloud2 - this will return a PointCloud2DataRef that contains references to the
404  actual data in the point cloud. Modifying this PointCloud2DataRef will change the data
405  in the point cloud directly.
406 
407  Iterators provide two additional functions, sparse(), which returns true if the iterator
408  includes sparse data, and index(), which returns the index of the current value in
409  the point cloud. index() is especially useful if traversing over sparse data or a subset,
410  since it gives a way to index back into the original point cloud.
411 
412  Also see: @ref IteratorBase for empty template instantiation and
413  @ref IteratorVariadic for variadic instantiation. */
414  template <class ... Fields> class Iterator;
415  template <class ... Fields> friend class Iterator;
416 
417  //! A constant iterator over geometry and other fields
418  /*! Constant iterators do not need to perform deep copies since they cannot modify the
419  data. Thus these will in general be much more efficient to use if multiple references
420  to the underlying data exist.
421 
422  Iterators will always include a reference to the geometry and this needs not be
423  specified during their creation.
424 
425  Dereferencing an iterator works in a similar fashion to the get() and at() functions of
426  PointCloud2 - this will return a constant PointCloud2DataRef that contains references to the
427  actual data in the point cloud. Modifying this PointCloud2DataRef is not possible and data
428  cannot be changed in the original point cloud.
429 
430  Iterators provide two additional functions, sparse(), which returns true if the iterator
431  includes sparse data, and index(), which returns the index of the current value in
432  the point cloud. index() is especially useful if traversing over sparse data or a subset,
433  since it gives a way to index back into the original point cloud.
434 
435  Also see: @ref ConstIteratorBase for empty template instantiation and
436  @ref ConstIteratorVariadic for variadic instantiation. */
437  template <class ... Fields> class ConstIterator;
438  template <class ... Fields> friend class ConstIterator;
439 
440  //! @anchor PointCloud2IteratorsGroup
441  /*! @name Iterators
442  The following iterators provide efficient access to the contents of a point cloud */
443  //! @{
444 
445  //! Get a basic iterator (includes geometry) to the beginning of the data
446  /*! Will perform a deep copy if not the sole owner of underlying data */
447  Iterator<> begin();
448 
449  //! Get a basic iterator (includes geometry) to the beginning of the data
450  ConstIterator<> begin() const;
451 
452  //! Get a basic iterator (includes geometry) to the beginning of the data
454 
455  //! Get an iterator to the requested fields, including geometry
456  /*! If the requested fields do not exist inside of the point cloud,
457  an exception will be thrown. Iterators with sparse fields
458  will perform more slowly than those with dense only fields,
459  especially during iterator creation. Iterator traversal time
460  should be similar in both cases.
461 
462  Sparse fields do not (and should not) need to be explicitly specified as sparse
463  using SparseField<>. This will be stripped if present.
464 
465  If at least one requested field is sparse, the strictest intersection of the
466  sparse indices will be iterated over by the iterator. Creation time will be
467  longer than creating a dense iterator and scale with the size of the
468  strictest subset and the number of fields to be iterated.
469 
470  Will perform a deep copy if not the sole owner of underlying data.
471 
472  @tparam T The first field requested to be iterated over
473  @tparam OtherT The other fields requested to be iterated over.
474  @throws PointCloud2FieldsException If at least one field does not exist in the cloud or
475  if no valid sparse intersection can be found in the case
476  when a sparse field is specified */
477  template <class T, class ... OtherT>
479 
480  //! Get a constant iterator to the requested fields, including geometry
481  /*! If the requested fields do not exist inside of the point cloud,
482  an exception will be thrown. Iterators with sparse fields
483  will perform more slowly than those with dense only fields,
484  especially during iterator creation. Iterator traversal time
485  should be similar in both cases.
486 
487  Sparse fields do not (and should not) need to be explicitly specified as sparse
488  using SparseField<>. This will be stripped if present.
489 
490  If at least one requested field is sparse, the strictest intersection of the
491  sparse indices will be iterated over by the iterator. Creation time will be
492  longer than creating a dense iterator and scale with the size of the
493  strictest subset and the number of fields to be iterated.
494 
495  @tparam T The first field requested to be iterated over
496  @tparam OtherT The other fields requested to be iterated over.
497  @throws PointCloud2FieldsException If at least one field does not exist in the cloud or
498  if no valid sparse intersection can be found in the case
499  when a sparse field is specified */
500  template <class T, class ... OtherT>
502 
503  //! Get a constant iterator to the requested fields, including geometry
504  /*! If the requested fields do not exist inside of the point cloud,
505  an exception will be thrown. Iterators with sparse fields
506  will perform more slowly than those with dense only fields,
507  especially during iterator creation. Iterator traversal time
508  should be similar in both cases.
509 
510  Sparse fields do not (and should not) need to be explicitly specified as sparse
511  using SparseField<>. This will be stripped if present.
512 
513  If at least one requested field is sparse, the strictest intersection of the
514  sparse indices will be iterated over by the iterator. Creation time will be
515  longer than creating a dense iterator and scale with the size of the
516  strictest subset and the number of fields to be iterated.
517 
518  @tparam T The first field requested to be iterated over
519  @tparam OtherT The other fields requested to be iterated over.
520  @throws PointCloud2FieldsException If at least one field does not exist in the cloud or
521  if no valid sparse intersection can be found in the case
522  when a sparse field is specified */
523  template <class T, class ... OtherT>
525 
526  //! Get a basic iterator (includes geometry) to one past the end of the data
527  /*! Will perform a deep copy if not the sole owner of underlying data. */
528  Iterator<> end();
529 
530  //! Get a basic iterator (includes geometry) to one past the end of the data
531  ConstIterator<> end() const;
532 
533  //! Get a basic iterator (includes geometry) to one past the end of the data
534  ConstIterator<> const_end() const;
535 
536  //! Get an iterator to the requested fields, including geometry
537  /*! If the requested fields do not exist inside of the point cloud,
538  an exception will be thrown. Iterators with sparse fields
539  will perform more slowly than those with dense only fields,
540  especially during iterator creation. Iterator traversal time
541  should be similar in both cases.
542 
543  Sparse fields do not (and should not) need to be explicitly specified as sparse
544  using SparseField<>. This will be stripped if present.
545 
546  If at least one requested field is sparse, the strictest intersection of the
547  sparse indices will be iterated over by the iterator. Creation time will be
548  longer than creating a dense iterator and scale with the size of the
549  strictest subset and the number of fields to be iterated.
550 
551  Will perform a deep copy if not the sole owner of underlying data.
552 
553  @tparam T The first field requested to be iterated over
554  @tparam OtherT The other fields requested to be iterated over.
555  @throws PointCloud2FieldsException If at least one field does not exist in the cloud or
556  if no valid sparse intersection can be found in the case
557  when a sparse field is specified */
558  template <class T, class ... OtherT>
560 
561  //! Get a constant iterator to the requested fields, including geometry
562  /*! If the requested fields do not exist inside of the point cloud,
563  an exception will be thrown. Iterators with sparse fields
564  will perform more slowly than those with dense only fields,
565  especially during iterator creation. Iterator traversal time
566  should be similar in both cases.
567 
568  Sparse fields do not (and should not) need to be explicitly specified as sparse
569  using SparseField<>. This will be stripped if present.
570 
571  If at least one requested field is sparse, the strictest intersection of the
572  sparse indices will be iterated over by the iterator. Creation time will be
573  longer than creating a dense iterator and scale with the size of the
574  strictest subset and the number of fields to be iterated.
575 
576  @tparam T The first field requested to be iterated over
577  @tparam OtherT The other fields requested to be iterated over.
578  @throws PointCloud2FieldsException If at least one field does not exist in the cloud or
579  if no valid sparse intersection can be found in the case
580  when a sparse field is specified */
581  template <class T, class ... OtherT>
583 
584  //! Get a constant iterator to the requested fields, including geometry
585  /*! If the requested fields do not exist inside of the point cloud,
586  an exception will be thrown. Iterators with sparse fields
587  will perform more slowly than those with dense only fields,
588  especially during iterator creation. Iterator traversal time
589  should be similar in both cases.
590 
591  Sparse fields do not (and should not) need to be explicitly specified as sparse
592  using SparseField<>. This will be stripped if present.
593 
594  If at least one requested field is sparse, the strictest intersection of the
595  sparse indices will be iterated over by the iterator. Creation time will be
596  longer than creating a dense iterator and scale with the size of the
597  strictest subset and the number of fields to be iterated.
598 
599  @tparam T The first field requested to be iterated over
600  @tparam OtherT The other fields requested to be iterated over.
601  @throws PointCloud2FieldsException If at least one field does not exist in the cloud or
602  if no valid sparse intersection can be found in the case
603  when a sparse field is specified */
604  template <class T, class ... OtherT>
606 
607  //! Gets an iterator to only geometrical data (first entry)
609 
610  //! Gets an iterator to only geometrical data (first entry)
612 
613  //! Gets an iterator to only geometrical data (first entry)
615 
616  //! Gets an iterator to only geometrical data (past the last entry)
618 
619  //! Gets an iterator to only geometrical data (past the last entry)
621 
622  //! Gets an iterator to only geometrical data (past the last entry)
624 
625  //! @}
626 
627  /*! @name Subset iterators
628  The following subset iterators provide access to only specified indices
629  of a point cloud */
630  //! @{
631 
632  //! Get a basic iterator (includes geometry) to the beginning of the subset
633  /*! Will perform a deep copy if not the sole owner of underlying data
634  @param indices The indices of the subset to iterate on
635  @throws PointCloud2SubsetException if an empty set of indices is passed */
636  Iterator<> subset_begin( Indices const indices );
637 
638  //! Get a basic iterator (includes geometry) to the beginning of the subset
639  /*! @param indices The indices of the subset to iterate on
640  @throws PointCloud2SubsetException if an empty set of indices is passed */
641  ConstIterator<> subset_begin( Indices const indices ) const;
642 
643  //! Get a basic iterator (includes geometry) to the beginning of the subset
644  /*! @param indices The indices of the subset to iterate on
645  @throws PointCloud2SubsetException if an empty set of indices is passed */
646  ConstIterator<> subset_const_begin( Indices const indices ) const;
647 
648  //! Get an iterator to the requested fields in a subset, including geometry
649  /*! If the requested fields do not exist inside of the point cloud,
650  an exception will be thrown. Iterators with sparse fields
651  will perform more slowly than those with dense only fields,
652  especially during iterator creation. Iterator traversal time
653  should be similar in both cases.
654 
655  Sparse fields do not (and should not) need to be explicitly specified as sparse
656  using SparseField<>. This will be stripped if present.
657 
658  If at least one requested field is sparse, the strictest intersection of the
659  sparse indices will be iterated over by the iterator. Creation time will be
660  longer than creating a dense iterator and scale with the size of the
661  strictest subset and the number of fields to be iterated.
662 
663  Will perform a deep copy if not the sole owner of underlying data.
664 
665  @tparam T The first field requested to be iterated over
666  @tparam OtherT The other fields requested to be iterated over.
667  @param indices The indices of the subset to iterate on
668  @throws PointCloud2FieldsException If at least one field does not exist in the cloud or
669  if at least one sparse field is specified that does
670  not have data for a provided index */
671  template <class T, class ... OtherT>
673 
674  //! Get an constant iterator to the requested fields in a subset, including geometry
675  /*! If the requested fields do not exist inside of the point cloud,
676  an exception will be thrown. Iterators with sparse fields
677  will perform more slowly than those with dense only fields,
678  especially during iterator creation. Iterator traversal time
679  should be similar in both cases.
680 
681  Sparse fields do not (and should not) need to be explicitly specified as sparse
682  using SparseField<>. This will be stripped if present.
683 
684  If at least one requested field is sparse, the strictest intersection of the
685  sparse indices will be iterated over by the iterator. Creation time will be
686  longer than creating a dense iterator and scale with the size of the
687  strictest subset and the number of fields to be iterated.
688 
689  @tparam T The first field requested to be iterated over
690  @tparam OtherT The other fields requested to be iterated over.
691  @param indices The indices of the subset to iterate on
692  @throws PointCloud2FieldsException If at least one field does not exist in the cloud or
693  if at least one sparse field is specified that does
694  not have data for a provided index */
695  template <class T, class ... OtherT>
697 
698  //! Get an constant iterator to the requested fields in a subset, including geometry
699  /*! If the requested fields do not exist inside of the point cloud,
700  an exception will be thrown. Iterators with sparse fields
701  will perform more slowly than those with dense only fields,
702  especially during iterator creation. Iterator traversal time
703  should be similar in both cases.
704 
705  Sparse fields do not (and should not) need to be explicitly specified as sparse
706  using SparseField<>. This will be stripped if present.
707 
708  If at least one requested field is sparse, the strictest intersection of the
709  sparse indices will be iterated over by the iterator. Creation time will be
710  longer than creating a dense iterator and scale with the size of the
711  strictest subset and the number of fields to be iterated.
712 
713  @tparam T The first field requested to be iterated over
714  @tparam OtherT The other fields requested to be iterated over.
715  @param indices The indices of the subset to iterate on
716  @throws PointCloud2FieldsException If at least one field does not exist in the cloud or
717  if at least one sparse field is specified that does
718  not have data for a provided index */
719  template <class T, class ... OtherT>
721 
722  //! Get a basic iterator (includes geometry) to one past the end of the subset
723  /*! Will perform a deep copy if not the sole owner of underlying data
724  @param indices The indices of the subset to iterate on
725  @throws PointCloud2SubsetException if an empty set of indices is passed */
726  Iterator<> subset_end( Indices const indices );
727 
728  //! Get a basic iterator (includes geometry) to one past the end of the subset
729  /*! @param indices The indices of the subset to iterate on
730  @throws PointCloud2SubsetException if an empty set of indices is passed */
731  ConstIterator<> subset_end( Indices const indices ) const;
732 
733  //! Get a basic iterator (includes geometry) to one past the end of the subset
734  /*! @param indices The indices of the subset to iterate on
735  @throws PointCloud2SubsetException if an empty set of indices is passed */
736  ConstIterator<> subset_const_end( Indices const indices ) const;
737 
738  //! Get an iterator to one past the end of the requested fields in a subset, including geometry
739  /*! If the requested fields do not exist inside of the point cloud,
740  an exception will be thrown. Iterators with sparse fields
741  will perform more slowly than those with dense only fields,
742  especially during iterator creation. Iterator traversal time
743  should be similar in both cases.
744 
745  Sparse fields do not (and should not) need to be explicitly specified as sparse
746  using SparseField<>. This will be stripped if present.
747 
748  If at least one requested field is sparse, the strictest intersection of the
749  sparse indices will be iterated over by the iterator. Creation time will be
750  longer than creating a dense iterator and scale with the size of the
751  strictest subset and the number of fields to be iterated.
752 
753  Will perform a deep copy if not the sole owner of underlying data.
754 
755  @tparam T The first field requested to be iterated over
756  @tparam OtherT The other fields requested to be iterated over.
757  @param indices The indices of the subset to iterate on
758  @throws PointCloud2FieldsException If at least one field does not exist in the cloud or
759  if at least one sparse field is specified that does
760  not have data for a provided index */
761  template <class T, class ... OtherT>
763 
764  //! Get an constant iterator to one past the end of the requested fields in a subset, including geometry
765  /*! If the requested fields do not exist inside of the point cloud,
766  an exception will be thrown. Iterators with sparse fields
767  will perform more slowly than those with dense only fields,
768  especially during iterator creation. Iterator traversal time
769  should be similar in both cases.
770 
771  Sparse fields do not (and should not) need to be explicitly specified as sparse
772  using SparseField<>. This will be stripped if present.
773 
774  If at least one requested field is sparse, the strictest intersection of the
775  sparse indices will be iterated over by the iterator. Creation time will be
776  longer than creating a dense iterator and scale with the size of the
777  strictest subset and the number of fields to be iterated.
778 
779  @tparam T The first field requested to be iterated over
780  @tparam OtherT The other fields requested to be iterated over.
781  @param indices The indices of the subset to iterate on
782  @throws PointCloud2FieldsException If at least one field does not exist in the cloud or
783  if at least one sparse field is specified that does
784  not have data for a provided index */
785  template <class T, class ... OtherT>
787 
788  //! Get an constant iterator to one past the end of the requested fields in a subset, including geometry
789  /*! If the requested fields do not exist inside of the point cloud,
790  an exception will be thrown. Iterators with sparse fields
791  will perform more slowly than those with dense only fields,
792  especially during iterator creation. Iterator traversal time
793  should be similar in both cases.
794 
795  Sparse fields do not (and should not) need to be explicitly specified as sparse
796  using SparseField<>. This will be stripped if present.
797 
798  If at least one requested field is sparse, the strictest intersection of the
799  sparse indices will be iterated over by the iterator. Creation time will be
800  longer than creating a dense iterator and scale with the size of the
801  strictest subset and the number of fields to be iterated.
802 
803  @tparam T The first field requested to be iterated over
804  @tparam OtherT The other fields requested to be iterated over.
805  @param indices The indices of the subset to iterate on
806  @throws PointCloud2FieldsException If at least one field does not exist in the cloud or
807  if at least one sparse field is specified that does
808  not have data for a provided index */
809  template <class T, class ... OtherT>
811 
812  //! @}
813 
814  //! @anchor PointCloud2RangesGroup
815  /*! @name Ranges
816  The following classes provide a lightweight range access to the contents of a point cloud
817 
818  Creating a range may cause a deep copy of the underlying data to occur if not the sole
819  owner of the data while requesting a non constant range. Ranges wrap up a begin and
820  end iterator and give a convenient way to access point cloud data using mechanisms such
821  as a range based for loop.
822 
823  Ranges will always include a reference to the geometry and this needs not be specified
824  during their creation. */
825  //! @{
826 
827  //! Gets a range that only includes raw geometry over the entire point cloud
828  /*! Unlike regular ranges, a geometry_range will directly access geometry data
829  and will not be wrapped in a PointCloud2DataRef<>. This means that
830  your iteration should look something like:
831 
832  @code
833  for( PointCloud2::Geometry const & p : myCloud.geometry_range() )
834  p.x() = p.y();
835  @endcode
836 
837  Will perform a deep copy if not the owner of underlying data */
839 
840  //! Gets a range that only includes raw constant geometry over the entire point cloud
842 
843  //! Gets a range that only includes raw constant geometry over the entire point cloud
845 
846  //! Gets a range that only includes geometry over the entire point cloud
847  /*! Ranges will return PointCloud2DataRef<> r-values which contain references to
848  point cloud data. This means that data iterated over by a range is already by
849  reference and can be modified directly:
850 
851  @code
852  for( PointCloud2DataRef<> data : myCloud.range() ) // note the lack of & on data
853  data.geometry().x() = 3.4f; // changes a value inside of the cloud
854  @endcode
855 
856  Will perform a deep copy if not the sole owner of underlying data. */
858 
859  //! Gets a range that only includes constant geometry over the entire point cloud
861 
862  //! Gets a range that only includes constant geometry over the entire point cloud
864 
865  //! Gets a range that only includes geometry over a subset of the cloud
866  /*! Will perform a deep copy if not the sole owner of underlying data. */
868 
869  //! Gets a range that only includes constant geometry over a subset of the cloud
870  IteratorRange<ConstIterator<>> subset_range( Indices const indices ) const;
871 
872  //! Gets a range that only includes constant geometry over a subset of the cloud
874 
875  //! Gets a range over the requested fields for the entire point cloud
876  /*! If the requested fields do not exist inside of the point cloud,
877  an exception will be thrown. Ranges with sparse fields
878  will perform more slowly than those with dense only fields,
879  especially during range creation. Range traversal time
880  should be similar in both cases.
881 
882  Sparse fields do not (and should not) need to be explicitly specified as sparse
883  using SparseField<>. This will be stripped if present.
884 
885  If at least one requested field is sparse, the strictest intersection of the
886  sparse indices will be iterated over by the range. Creation time will be
887  longer than creating a dense range and scale with the size of the
888  strictest subset and the number of fields to be ranged over.
889 
890  Will perform a deep copy if not the sole owner of underlying data.
891 
892  @tparam T The first field requested in the range.
893  @tparam OtherT The other fields requested in the range
894  @throws PointCloud2FieldsException If at least one field does not exist in the cloud or
895  if at least one sparse field is specified that does
896  not have data for a provided index */
897  template <class T, class ... OtherT>
899 
900  //! Gets a range over the requested fields for the entire point cloud
901  /*! If the requested fields do not exist inside of the point cloud,
902  an exception will be thrown. Ranges with sparse fields
903  will perform more slowly than those with dense only fields,
904  especially during range creation. Range traversal time
905  should be similar in both cases.
906 
907  Sparse fields do not (and should not) need to be explicitly specified as sparse
908  using SparseField<>. This will be stripped if present.
909 
910  If at least one requested field is sparse, the strictest intersection of the
911  sparse indices will be iterated over by the range. Creation time will be
912  longer than creating a dense range and scale with the size of the
913  strictest subset and the number of fields to be ranged over.
914 
915  @tparam T The first field requested in the range.
916  @tparam OtherT The other fields requested in the range
917  @throws PointCloud2FieldsException If at least one field does not exist in the cloud or
918  if at least one sparse field is specified that does
919  not have data for a provided index */
920  template <class T, class ... OtherT>
922 
923  //! Gets a range over the requested fields for the entire point cloud
924  /*! If the requested fields do not exist inside of the point cloud,
925  an exception will be thrown. Ranges with sparse fields
926  will perform more slowly than those with dense only fields,
927  especially during range creation. Range traversal time
928  should be similar in both cases.
929 
930  Sparse fields do not (and should not) need to be explicitly specified as sparse
931  using SparseField<>. This will be stripped if present.
932 
933  If at least one requested field is sparse, the strictest intersection of the
934  sparse indices will be iterated over by the range. Creation time will be
935  longer than creating a dense range and scale with the size of the
936  strictest subset and the number of fields to be ranged over.
937 
938  @tparam T The first field requested in the range.
939  @tparam OtherT The other fields requested in the range
940  @throws PointCloud2FieldsException If at least one field does not exist in the cloud or
941  if at least one sparse field is specified that does
942  not have data for a provided index */
943  template <class T, class ... OtherT>
945 
946  //! Gets a range over the requested fields for some subset
947  /*! If the requested fields do not exist inside of the point cloud,
948  an exception will be thrown. Ranges with sparse fields
949  will perform more slowly than those with dense only fields,
950  especially during range creation. Range traversal time
951  should be similar in both cases.
952 
953  Sparse fields do not (and should not) need to be explicitly specified as sparse
954  using SparseField<>. This will be stripped if present.
955 
956  If at least one requested field is sparse, the strictest intersection of the
957  sparse indices will be iterated over by the range. Creation time will be
958  longer than creating a dense range and scale with the size of the
959  strictest subset and the number of fields to be ranged over.
960 
961  Will perform a deep copy if not the sole owner of underlying data.
962 
963  @tparam T The first field requested in the range.
964  @tparam OtherT The other fields requested in the range
965  @param indices The indices of the subset to range over
966  @throws PointCloud2FieldsException If at least one field does not exist in the cloud or
967  if at least one sparse field is specified that does
968  not have data for a provided index */
969  template <class T, class ... OtherT>
971 
972  //! Gets a range over the requested fields for the entire point cloud
973  /*! If the requested fields do not exist inside of the point cloud,
974  an exception will be thrown. Ranges with sparse fields
975  will perform more slowly than those with dense only fields,
976  especially during range creation. Range traversal time
977  should be similar in both cases.
978 
979  Sparse fields do not (and should not) need to be explicitly specified as sparse
980  using SparseField<>. This will be stripped if present.
981 
982  If at least one requested field is sparse, the strictest intersection of the
983  sparse indices will be iterated over by the range. Creation time will be
984  longer than creating a dense range and scale with the size of the
985  strictest subset and the number of fields to be ranged over.
986 
987  @tparam T The first field requested in the range.
988  @tparam OtherT The other fields requested in the range
989  @param indices The indices of the subset to range over
990  @throws PointCloud2FieldsException If at least one field does not exist in the cloud or
991  if at least one sparse field is specified that does
992  not have data for a provided index */
993  template <class T, class ... OtherT>
995 
996  //! Gets a range over the requested fields for the entire point cloud
997  /*! If the requested fields do not exist inside of the point cloud,
998  an exception will be thrown. Ranges with sparse fields
999  will perform more slowly than those with dense only fields,
1000  especially during range creation. Range traversal time
1001  should be similar in both cases.
1002 
1003  Sparse fields do not (and should not) need to be explicitly specified as sparse
1004  using SparseField<>. This will be stripped if present.
1005 
1006  If at least one requested field is sparse, the strictest intersection of the
1007  sparse indices will be iterated over by the range. Creation time will be
1008  longer than creating a dense range and scale with the size of the
1009  strictest subset and the number of fields to be ranged over.
1010 
1011  @tparam T The first field requested in the range.
1012  @tparam OtherT The other fields requested in the range
1013  @param indices The indices of the subset to range over
1014  @throws PointCloud2FieldsException If at least one field does not exist in the cloud or
1015  if at least one sparse field is specified that does
1016  not have data for a provided index */
1017  template <class T, class ... OtherT>
1019 
1020  //! @}
1021 
1022  /*! @name Cloud insertion and deletion
1023  Functionality for inserting elements, resizing the point cloud, and
1024  clearing elements or the entire cloud */
1025  //! @{
1026 
1027  //! Resizes the point cloud
1028  /*! If the new size is greater than the old size, dense
1029  data will be created to fill the new indices. The newly
1030  created dense data is not guaranteed to be valid.
1031 
1032  If the size causes a reduction in the size of the
1033  point cloud, any dense data exceeding the new size
1034  will be removed. This will also cause any sparse data
1035  data associated with indices that no longer exist to be
1036  removed. This removal of sparse data takes time linear
1037  in the difference of cloud size and logarithmic in the number
1038  of elements in a sparse field.
1039 
1040  @param size The new size for the point cloud */
1041  void resize( size_t size );
1042 
1043  //! Removes all data in every field (but does not remove fields) including geometry
1044  void clear();
1045 
1046  //! Inserts a single geometrical point at the end of the cloud
1047  /*! Any dense fields currently contained in the point cloud will be given
1048  zero valued data to correspond with the dense entry created by this insertion.
1049  Depending on the data type, this may result in invalid data for those dense
1050  fields. It is suggested to fully specify all types in the cloud, if possible,
1051  when calling the templated version of insert to prevent any invalid data
1052  from existing. */
1053  void insert( Geometry const & geo );
1054 
1055  //! Inserts a single point at the end of the cloud
1056  /*! If any dense fields currently contained in the point cloud are not specified
1057  in the input data, they will be given zero valued data to correspond with
1058  the dense entry created by this insertion. Depending on the data type,
1059  this may result in invalid data. Therefor it is suggested to always fully
1060  specify dense types during an insertion if possible.
1061 
1062  @tparam Fields The fields to insert, which may include any fields (dense or
1063  sparse) in the point cloud. Sparse fields should not be
1064  wrapped in SparseField<>.
1065  @throws PointCloud2FieldsException If any single field listed does not exist */
1066  template <class ... Fields>
1067  void insert( PointCloud2Data<Fields...> const & point );
1068 
1069  //! Adds sparse data to a point
1070  /*! This function adds sparse data entries to some point that was previously only
1071  associated with dense data. The sparse fields must exist in the point cloud
1072  prior to calling this function. If the assigned index already contains the
1073  sparse data passed in, it will be overwritten.
1074 
1075  After calling this, the data at the specified index will be associated with
1076  the provided sparse data as well as any data it was previously associated with.
1077 
1078  @tparam Fields The sparse fields to be inserted. Do not wrap with SparseField<>.
1079  If any field does not exist in the point cloud, an exception
1080  will be thrown.
1081  @param index The index to insert sparse data at. If this index does not exist
1082  in the point cloud, an exception will be thrown.
1083  @param data The sparse data to be inserted. If the data already exists, it will be
1084  overwritten */
1085  template <class ... Fields>
1086  void insertSparse( size_t const index, StreamableGenericBag<Fields...> const & data );
1087 
1088  //! Appends all data from another point cloud to this one
1089  /*! This will add all of the data from another point cloud to the end of the data
1090  in this point cloud, increasing its size by the size of the other point cloud.
1091 
1092  This is intended to combine two same configured point clouds together and is not
1093  meant for use with mixed types, since the behavior in that situation can be
1094  ambiguous.
1095 
1096  If the two point clouds do not have identical configurations, an exception will
1097  be thrown.
1098 
1099  Dense data will merely be appended to the current data. Sparse data in the other
1100  point cloud will have its index adjusted by the new starting index of data from
1101  the other point cloud. For example, if our current cloud is size 100 and we merge
1102  a size 50 cloud, a sparse field from the other cloud that was at index 2 is now at
1103  index 102.
1104 
1105  @return A reference to this, which will now contain the data from the other cloud as well
1106  @throws PointCloud2FieldsException If the two clouds do not have exactly the same set
1107  of fields */
1108  PointCloud2 & append( PointCloud2 const other );
1109 
1110  //! Remove all data (from every field) associated with a specific index
1111  void remove( size_t index );
1112 
1113  //! Remove the sparse data of a specific field associated with a point
1114  /*! It is not necessary to wrap the template parameter with SparseField<>.
1115  If specified, it will be stripped automatically.
1116 
1117  @throws PointCloud2FieldsException If the requested field does not exist in the cloud */
1118  template <class Field>
1119  void remove( size_t index );
1120 
1121  //! Remove all data (from every field) associated with a specific index,
1122  //! not preserving ordering
1123  /*! This is generally a faster operation than remove() but will not
1124  preserve the ordering of points within the cloud */
1125  void quickRemove( size_t index );
1126 
1127  //! Remove all data (from every field) associated with every index in a subset
1128  //! not preserving ordering
1129  /*! This is generally a faster operation than calling remove() or quickRemove() on several
1130  indices to remove.
1131 
1132  Because quickRemove does not preserve ordering, the input must be sorted or the sort
1133  flag should be specified so that this function handles the sorting.
1134 
1135  @param indices The subset to remove
1136  @param sort Whether we need to sort the input */
1137  void quickRemove( Indices const indices, bool sort = false );
1138 
1139  //! @}
1140 
1141  /*! @name Memory manipulation and reference counting
1142  Functionality for comparing and manipulating the actual reference
1143  counted memory of the point cloud */
1144  //! @{
1145 
1146  //! Performs a deep copy of the underlying data
1147  /*! After calling deepcopy, a deep copy of all underlying data will occur and this PointCloud2
1148  will have unique ownership of its data until another reference is created.
1149 
1150  The reference count will be one after this operation and any existing references will be
1151  decremented. */
1152  void deepCopy();
1153 
1154  //! Check whether this cloud is equal (same internal data) as some other
1155  bool operator==( PointCloud2 const & other ) const;
1156 
1157  //! Check whether this cloud is not equal (not same internal data) as some other
1158  bool operator!=( PointCloud2 const & other ) const;
1159 
1160  //! @}
1161  private:
1162  //! Used for iterators
1163  template <class ... Fields> friend struct subsetHelper;
1164 
1165  //! A struct that helps insert fields
1166  template <class ... Fields> struct addFieldHelper;
1167  template <class ... Fields> friend struct addFieldHelper;
1168 
1169  //! A struct that helps remove fields
1170  template <class ... Fields> struct removeFieldHelper;
1171  template <class ... Fields> friend struct removeFieldHelper;
1172 
1173  //! A struct that helps insert new data
1174  template <size_t Index> struct insertDataHelper;
1175  template <size_t Index> friend struct insertDataHelper;
1176 
1177  //! A struct that checks for all dense fields and that sparse fields exist, during insertion
1178  template <class ... T> struct insertionChecker;
1179  template <class ... T> friend struct insertionChecker;
1180 
1181  //! A struct that helps lookup existing data
1182  template <class RetT, class ... T> struct lookupHelper;
1183  template <class RetT, class ... T> friend struct lookupHelper;
1184 
1185  //! A struct used to build a bag of dense pointers
1186  template <class RetT, class ... T> struct pointerHelper;
1187  template <class RetT, class ... T> friend struct pointerHelper;
1188 
1189  //! used for checking if a list of fields constains a sparse field
1190  template <class ... T> struct sparseExistHelper;
1191  template <class ... T> friend struct sparseExistHelper;
1192 
1193 
1194  //! used to find the strictest subset of indices for some sparse fields
1195  template <class ... T> struct subsetHelper;
1196  template <class ... T> friend struct subsetHelper;
1197 
1198  //! checks that all of the fields provided are sparse
1199  template <class ... T> struct sparseOnlyExistHelper;
1200  template <class ... T> friend struct sparseOnlyExistHelper;
1201 
1202  //! handles inserting junk data when adding sparse data to an index
1203  template <class ... T> struct sparseInsertHelper;
1204  template <class ... T> friend struct sparseInsertHelper;
1205 
1206  //! Adds a dense field to the point cloud
1207  template <class T>
1208  typename std::enable_if<!std::is_base_of<SparseFieldCore, T>::value, void>::type
1209  addDataField();
1210 
1211  //! Adds a sparse field to the point cloud
1212  template <class T>
1213  typename std::enable_if<std::is_base_of<SparseFieldCore, T>::value, void>::type
1214  addDataField();
1215 
1216  //! Removes a field from the point cloud
1217  template <class T>
1218  void removeDataField();
1219 
1220  //! inserts data into a specific field
1221  /*! @param index The index to use, if a sparse entry
1222  @param data The data to insert */
1223  template <class T>
1224  void insertFieldData( size_t index, T const & data );
1225 
1226  //! gets data from a specific field
1227  /*! @param index The index to use */
1228  template <class T>
1229  T & getFieldData( size_t index );
1230 
1231  //! gets data from a specific field
1232  /*! @param index The index to use */
1233  template <class T>
1234  T const & getFieldData( size_t index ) const;
1235 
1236  //! Causes a deep copy to occur if we do not have unique access to our data
1237  void deepCopyIfNotUnique();
1238 
1239  //! insert junk (zero valued) data into all dense fields that
1240  //! were not specified explicitly during an insert
1241  /*! @param size The current number of dense fields fully specified */
1242  void insertEqualize( size_t const size );
1243 
1244  //! Invalidates all local caching
1245  /*! Various lookups are cached, mainly when calculating iterators, that
1246  must be invalidated if the structure of the underlying data changes.
1247  These changes can occur on the following conditions:
1248  Fields are added or removed to the cloud
1249  Data is inserted or removed from the cloud
1250  The memory pointer is changed */
1251  void invalidateCache();
1252 
1253  private:
1254  //! Copy on write memory class forward decl
1255  class Memory;
1256 
1257  //! The data associated with this cloud
1258  std::shared_ptr<Memory> itsData;
1259 
1260  //! Fast access to the size of the cloud
1261  size_t itsSize;
1262 
1263  //! Caches lookup for whether a sparse field exists in a set of fields
1264  mutable LookupCache itsSparseExistCache;
1265 
1266  //! Caches lookup for building a dense set of pointers
1267  mutable LookupCache itsPointerCache;
1268 
1269  friend class cereal::access;
1270 
1271  //! Handles serialization saving
1272  template <class Archive> inline
1273  void save( Archive & ar ) const
1274  {
1275  ar( itsData,
1276  itsSize,
1277  itsSparseExistCache,
1278  itsPointerCache );
1279  }
1280 
1281  //! Handles serialization loading
1282  template <class Archive> inline
1283  void load( Archive & ar )
1284  {
1285  ar( itsData,
1286  itsSize,
1287  itsSparseExistCache,
1288  itsPointerCache );
1289 
1290  invalidateCache();
1291  }
1292  }; // class PointCloud2
1293 
1294  namespace exception
1295  {
1296  //! An exception that is thrown whenever there is an error related to the requested fields
1298  {
1299  public:
1300  //! Construct a new exception for an incompatible set of fields
1301  PointCloud2FieldsException() noexcept;
1302 
1303  //! Construct a new exception when number of fields is incorrect
1304  PointCloud2FieldsException( size_t count, size_t expected ) noexcept;
1305 
1306  //! Construct a new exception with a specific field
1307  /*! @param field The first field that encountered an error */
1308  PointCloud2FieldsException( std::string const & field ) noexcept;
1309 
1310  //! Construct a new exception with a specific field and specific error message
1311  /*! @param field The first field that encountered an error
1312  @param message A message to be output after the field is listed */
1313  PointCloud2FieldsException( std::string const & field, std::string const & message ) noexcept;
1314 
1315  virtual ~PointCloud2FieldsException() noexcept;
1316 
1317  //! Get the field name that caused the error
1318  std::string const & field() const;
1319 
1320  private:
1321  std::string itsField;
1322  std::string whatstring;
1323  };
1324 
1325  //! Exception thrown when errors occur with subsets
1327  {
1328  public:
1329  //! Constructor for an empty subset
1330  PointCloud2SubsetException() noexcept;
1331 
1332  virtual ~PointCloud2SubsetException() noexcept;
1333 
1334  private:
1335  std::string whatstring;
1336  };
1337  } // namespace exception
1338 } // namespace nrt
1339 
1341 
1342 #endif // INCLUDE_NRT_POINTCLOUD2_POINTCLOUD2_H
1343 #endif // NRT_HAVE_CLOUD