Documentation

The current document explains not only how to add your own PointT point type,
but also what templated point types are in PCL, why do they exist, and how are
they exposed. If you’re already familiar with this information, feel free to
skip to the last part of the document.

The current document is valid only for PCL 0.x and 1.x. Note that at the time
of this writing we are expecting things to be changed in PCL 2.x.

PCL comes with a variety of pre-defined point types, ranging from SSE-aligned
structures for XYZ data, to more complex n-dimensional histogram
representations such as PFH (Point Feature Histograms). These types should be
enough to support all the algorithms and methods implemented in PCL. However,
there are cases where users would like to define new types. This document
describes the steps involved in defining your own custom PointT type and making
sure that your project can be compiled successfully and ran.

PCL’s PointT legacy goes back to the days where it was a library developed
within ROS. The consensus then was that a Point Cloud
is a complicated n-D structure that needs to be able to represent different
types of information. However, the user should know and understand what types
of information need to be passed around, in order to make the code easier to
debug, think about optimizations, etc.

One example is represented by simple operations on XYZ data. The most
efficient way for SSE-enabled processors, is to store the 3 dimensions as
floats, followed by an extra float for padding:

1
2
3
4
5
6
7

structPointXYZ{floatx;floaty;floatz;floatpadding;};

As an example however, in case an user is looking at compiling PCL on an
embedded platform, adding the extra padding can be a waste of memory.
Therefore, a simpler PointXYZ structure without the last float could be used
instead.

Moreover, if your application requires a PointXYZRGBNormal which contains
XYZ 3D data, RGB information (colors), and surface normals estimated at
each point, it is trivial to define a structure with all the above. Since all
algorithms in PCL should be templated, there are no other changes required
other than your structure definition.

To cover all possible cases that we could think of, we defined a plethora of
point types in PCL. The following might be only a snippet, please see
point_types.hpp
for the complete list.

This list is important, because before defining your own custom type, you need
to understand why the existing types were created they way they were. In
addition, the type that you want, might already be defined for you.

PointXYZ - Members: float x, y, z;

This is one of the most used data types, as it represents 3D xyz information
only. The 3 floats are padded with an additional float for SSE alignment. The
user can either access points[i].data[0] or points[i].x for accessing
say, the x coordinate.

union{floatdata[4];struct{floatx;floaty;floatz;};};

PointXYZI - Members: float x, y, z, intensity;

Simple XYZ + intensity point type. In an ideal world, these 4 components
would create a single structure, SSE-aligned. However, because the majority
of point operations will either set the last component of the data[4] array
(from the xyz union) to 0 or 1 (for transformations), we cannot make
intensity a member of the same structure, as its contents will be
overwritten. For example, a dot product between two points will set their 4th
component to 0, otherwise the dot product doesn’t make sense, etc.

Therefore for SSE-alignment, we pad intensity with 3 extra floats.
Inefficient in terms of storage, but good in terms of memory alignment.

Similar to PointXYZRGBA, except rgb represents the RGBA information packed into a float.

Note

The reason why rgb data is being packed as a float comes from the early
development of PCL as part of the ROS project, where RGB data is still being
sent by wire as float numbers. We expect this data type to be dropped as
soon as all legacy code has been rewritten (most likely in PCL 2.x).

One of the other most used data types, the Normal structure represents the
surface normal at a given point, and a measure of curvature (which is
obtained in the same call as a relationship between the eigenvalues of a
surface patch – see the NormalEstimation class API for more information).

Because operation on surface normals are quite common in PCL, we pad the 3
components with a fourth one, in order to be SSE-aligned and computationally
efficient. The user can either access points[i].data_n[0] or
points[i].normal[0] or points[i].normal_x for accessing say, the first
coordinate of the normal vector. Again, curvature cannot be stored in the
same structure as it would be overwritten by operations on the normal data.

Similar to PointXYZI, except scale contains the scale at which a certain
point was considered for a geometric operation (e.g. the radius of the sphere
for its nearest neighbors computation, the window size, etc).

Because of its large size, and because it’s a template library, including many
PCL algorithms in one source file can slow down the compilation process. At the
time of writing this document, most C++ compilers still haven’t been properly
optimized to deal with large sets of templated files, especially when
optimizations (-O2 or -O3) are involved.

To speed up user code that includes and links against PCL, we are using
explicit template instantiations, by including all possible combinations in
which all algorithms could be called using the already defined point types from
PCL. This means that once PCL is compiled as a library, any user code will not
require to compile templated code, thus speeding up compile time. The trick
involves separating the templated implementations from the headers which
forward declare our classes and methods, and resolving at link time. Here’s a
fictitious example:

And finally, the above shows the way the explicit instantiations are done in
PCL. The macro PCL_INSTANTIATE does nothing else but go over a given list of
types and creates an explicit instantiation for each. From pcl/include/pcl/impl/instantiate.hpp:

Then, you need to make sure your code includes the template header
implementation of the specific class/algorithm in PCL that you want your new
point type MyPointType to work with. For example, say you want to use
pcl::PassThrough. All you would have to do is:

#define PCL_NO_PRECOMPILE#include<pcl/filters/passthrough.h>#include<pcl/filters/impl/passthrough.hpp>// the rest of the code goes here

If your code is part of the library, which gets used by others, it might also
make sense to try to use explicit instantiations for your MyPointType types,
for any classes that you expose (from PCL our outside PCL).

Note

Starting with PCL-1.7 you need to define PCL_NO_PRECOMPILE before you include
any PCL headers to include the templated algorithms as well.