Chapter 6. Point Clouds

Point clouds appeared in the robotics toolbox as a way to intuitively represent and manipulate the information provided by 3D sensors, such as time-of-flight cameras and laser scanners, in which the space is sampled in a finite set of points in a 3D frame of reference. The Point Cloud Library (PCL) provides a number of data types and data structures to easily represent not only the points of our sampled space, but also the different properties of the sampled space, such as color, normal vectors, and so on. PCL also provides a number of state-of-the-art algorithms to perform data processing on our data samples, such as filtering, model estimation, surface reconstruction, and much more.

ROS provides a message-based interface through which PCL point clouds can be efficiently communicated, and a set of conversion functions from native PCL types to ROS messages, in much the same way as it is done with OpenCV images. Aside from the standard capabilities of the ROS API, there are a number of standard packages that can be used to interact with common 3D sensors, such as the widely used Microsoft Kinect or the Hokuyo laser, and visualize the data in different reference frames with RViz.

This chapter will provide a background on the PCL library, relevant data types, and ROS interface messages that will be used throughout the rest of the sections. Later, a number of techniques will be presented on how to perform data processing using the PCL library and how to communicate the incoming and outgoing data through ROS.

Understanding the point cloud library

Before we dive into the code, it's important to understand the basic concepts of both the Point Cloud Library and the PCL interface for ROS. As mentioned before, the former provides a set of data structures and algorithms for 3D data processing, and the latter provides a set of messages and conversion functions between messages and PCL data structures. All of these software packages and libraries, in combination with the capabilities of the distributed communication layer provided by ROS, open up possibilities for many new applications in the robotics field.

In general, PCL contains one very important data structure, which is PointCloud. This data structure is designed as a template class that takes the type of point to be used as a template parameter. As a result of this, the point cloud class is not much more than a container of points that includes all of the common information required by all point clouds regardless of their point type. The following are the most important public fields in a point cloud:

  • header: This field is of the pcl::PCLHeader type and specifies the acquisition time of the point cloud.
  • points: This field is of the std::vector<PointT, ... > type and is the container where all of the points are stored. PointT in the vector definition corresponds to the class template parameter, that is, the point type.
  • width: This field specifies the width of the point cloud when organized as an image; otherwise, it contains the number of points in the cloud.
  • height: This field specifies the height of the point cloud when organized as an image; otherwise, it's always one.
  • is_dense: This field specifies whether the cloud contains invalid values (infinite or NaN).
  • sensor_origin_: This field is of the Eigen::Vector4f type, and it defines the sensor acquisition pose in terms of a translation from the origin.
  • sensor_orientation_: This field is of the Eigen::Quaternionf type, and it defines the sensor acquisition pose as a rotation.

These fields are used by PCL algorithms to perform data processing and can be used by the user to create their own algorithms. Once the point cloud structure is understood, the next step is to understand the different point types a point cloud can contain, how PCL works, and the PCL interface for ROS.

Different point cloud types

As described earlier, pcl::PointCloud contains a field that serves as a container for the points; this field is of the PointT type, which is the template parameter of the pcl::PointCloud class and defines the type of point the cloud is meant to store. PCL defines many types of points, but a few of the most commonly used ones are the following:

  • pcl::PointXYZ: This is the simplest type of point and probably one of the most used; it stores only 3D xyz information.
  • pcl::PointXYZI: This type of point is very similar to the previous one, but it also includes a field for the intensity of the point. Intensity can be useful when obtaining points based on a certain level of return from a sensor. There are two other standard identical point types to this one: the first one is pcl::InterestPoint, which has a field to store strength instead of intensity, and pcl::PointWithRange, which has a field to store the range instead of either intensity or strength.
  • pcl::PointXYZRGBA: This type of point stores 3D information as well as color (RGB = Red, Green, Blue) and transparency (A = Alpha).
  • pcl::PointXYZRGB: This type is similar to the previous point type, but it differs in that it lacks the transparency field.
  • pcl::Normal: This is one of the most used types of points; it represents the surface normal at a given point and a measure of its curvature.
  • pcl::PointNormal: This type is exactly the same as the previous one; it contains the surface normal and curvature information at a given point, but it also includes the 3D xyz coordinates of the point. Variants of this point are PointXYZRGBNormal and the PointXYZINormal, which, as the names suggest, include color (former) and intensity (latter).

Aside from these common types of points, there are many more standard PCL types, such as PointWithViewpoint, MomentInvariants, Boundary, PrincipalCurvatures, Histogram, and many more. More importantly, the PCL algorithms are all templated so that not only the available types can be used, but also semantically valid user-defined types can be used.

Algorithms in PCL

PCL uses a very specific design pattern throughout the entire library to define point cloud processing algorithms. In general, the problem with these types of algorithms is that they can be highly configurable, and in order to deliver their full potential, the library must provide a mechanism for the user to specify all of the parameters required as well as the commonly used defaults.

In order to solve this problem, PCL developers decided to make each algorithm a class belonging to a hierarchy of classes with specific commonalities. This approach allows PCL developers to reuse existing algorithms in the hierarchy by deriving from them and adding the required parameters for the new algorithm, and it also allows the user to easily provide the parameter values it requires through accessors, leaving the rest to their default value. The following snippet shows how using a PCL algorithm usually looks:

pcl::PointCloud<pcl::PointXYZ>::Ptr cloud(new pcl::PointCloud<pcl::PointXYZ>);
pcl::PointCloud<pcl::PointXYZ>::Ptr result(new pcl::PointCloud<pcl::PointXYZ>);
 
pcl::Algorithm<pcl::PointXYZ> algorithm;
algorithm.setInputCloud(cloud);
algorithm.setParameter(1.0);
algorithm.setAnotherParameter(0.33);
algorithm.process (*result);

This approach is only followed when required within the library, so there might be exceptions to the rule, such as the I/O functionality, which are not bound by the same requirements.

The PCL interface for ROS

The PCL interface for ROS provides the means required to communicate PCL data structures through the message-based communication system provided by ROS. To do so, there are several message types defined to hold point clouds as well as other data products from the PCL algorithms. In combination with these message types, a set of conversion functions are also provided to convert from native PCL data types to messages. Some of the most useful message types are the following:

  • std_msgs::Header: This is not really a message type, but it is usually part of every ROS message; it holds the information about when the message was sent as well a sequence number and the frame name. The PCL equivalent is pcl::Header type.
  • sensor_msgs::PointCloud2: This is possibly the most important type; this message is used to transfer the pcl::PointCloud type. However, it is important to take into account that this message will be deprecated in future versions of PCL in favor of pcl::PCLPointCloud2.
  • pcl_msgs::PointIndices: This type stores indices of points belonging to a point cloud; the PCL equivalent type is pcl::PointIndices.
  • pcl_msgs::PolygonMesh: This holds the information required to describe meshes, that is, vertices and polygons; the PCL equivalent type is pcl::PolygonMesh.
  • pcl_msgs::Vertices: This type holds a set of the vertices as indices in an array, for example, to describe a polygon. The PCL equivalent type is pcl::Vertices.
  • pcl_msgs::ModelCoefficients: This stores the values of the different coefficients of a model, for example, the four coefficients required to describe a plane. The PCL equivalent type is pcl::ModelCoefficients.

The previous messages can be converted to and from PCL types with the conversion functions provided by the ROS PCL package. All of the functions have a similar signature, which means that once we know how to convert one type, we know how to convert them all. The following functions are provided in the pcl_conversions namespace:

void fromPCL(const <PCL Type> &, <ROS Message type> &);
void moveFromPCL(<PCL Type> &, <ROS Message type> &);
void toPCL(const <ROS Message type> &, <PCL Type> &);
void moveToPCL(<ROS Message type> &, <PCL Type> &);

Here, the PCL type must be replaced by one of the previously specified PCL types and the ROS message types by their message counterpart. sensor_msgs::PointCloud2 has a specific set of functions to perform the conversions:

void toROSMsg(const pcl::PointCloud<T> &, sensor_msgs::PointCloud2 &);
void fromROSMsg(const sensor_msgs::PointCloud2 &, pcl::PointCloud<T> &);
void moveFromROSMsg(sensor_msgs::PointCloud2 &, pcl::PointCloud<T> &);

You might be wondering about what the difference between each function and its move version is. The answer is simple, the normal version performs a deep copy of the data, while the move versions perform a shallow copy and nullify the source data container. This is referred to as "move semantics".

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.128.199.130