2. PCL Basics

The source code of PCL library can be found on github:

https://github.com/PointCloudLibrary/pcl/

In the source directory you can find tools, examples and test. In the doc directory you can find the tutorials source code as well as the explanation in reStructuredText. The tutorials are also accessible on the PCL website under documentation.

when installed the tools are available as command line. For example you can run pcl_viewer

pcl_viewer table_scene_mug_stereo_textured.pcd

The command will open a window with point cloud data. The pcd file can be found in the tutorials source code. A lot of point cloud files can be found also in the test directory.

Third party file may have the ply file format, The command line pcl_ply2pcd can be used to get pcd files.

// ASCII format
pcl_ply2pcd 0 input.ply output.pcd
// binary format
pcl_ply2pcd 1 input.ply output.pcd

2.1. First example

Read a point file, pcd, and wiew the content.

#include <iostream>
#include <pcl/io/pcd_io.h>
#include <pcl/point_types.h>
#include <pcl/visualization/cloud_viewer.h>

int main(int argc, char **argv)
{
  pcl::PointCloud<pcl::PointXYZ>::Ptr cloud(new pcl::PointCloud<pcl::PointXYZ>);

  if (pcl::io::loadPCDFile<pcl::PointXYZ>("test_pcd.pcd", *cloud) == -1) //* load the file
  {
    PCL_ERROR("Couldn't read file test_pcd.pcd \n");
    return (-1);
  }

  std::cout << "Loaded "
            << cloud->width * cloud->height
            << " data points from test_pcd.pcd with the following fields: "
            << std::endl;
  for (size_t i = 0; i < cloud->points.size(); ++i)
    std::cout << "    " << cloud->points[i].x
              << " " << cloud->points[i].y
              << " " << cloud->points[i].z << std::endl;

  pcl::visualization::CloudViewer viewer("Simple Cloud Viewer");
  viewer.showCloud(cloud);
  while (!viewer.wasStopped())
  {
  }

  return (0);
}
cmake_minimum_required(VERSION 2.8 FATAL_ERROR)

project(FirstExample)

find_package(PCL 1.2 REQUIRED)

include_directories(${PCL_INCLUDE_DIRS})
link_directories(${PCL_LIBRARY_DIRS})
add_definitions(${PCL_DEFINITIONS})

add_executable (first_example first_example.cpp)
target_link_libraries (first_example ${PCL_LIBRARIES})

To build and run the example:

mkdir build
cd build
cmake ..
make

./first_example

2.2. Data structures

The main data structure in PCL is the template class pcl::PointCloud<pcl::PointTemplate>. The template types could be:

  • pcl::PointXYZ: 3D XYZ
  • pcl::PointXYZI: 3D XYZ plus intensity of the point
  • pcl::PointXYZRGB: 3D XYZ plus rgb colors
  • pcl::Normal: it represents the surface normal at a given point and a measure of its curvature
  • pcl::PointNormal: 3D XYZ coordinates and the surface normal

Refer to the documentation for a complete list of supported point types. Note that you can define you own data types.

Create a PointCloud object with PointXYZ point type:

pcl::PointCloud<pcl::PointXYZ> cloud;

Create a Boost pointer

pcl::PointCloud<pcl::PointXYZ>::Ptr cloud (new pcl::PointCloud<pcl::PointXYZ>);

2.3. Algorithms design patterns

The following code read point cloud data, apply a filter then save the filtered data to a file.

#include <iostream>
#include <pcl/io/pcd_io.h>
#include <pcl/point_types.h>
#include <pcl/filters/statistical_outlier_removal.h>

int
main (int argc, char** argv)
{
  pcl::PointCloud<pcl::PointXYZ>::Ptr cloud (new pcl::PointCloud<pcl::PointXYZ>);
  pcl::PointCloud<pcl::PointXYZ>::Ptr cloud_filtered (new pcl::PointCloud<pcl::PointXYZ>);

  // Fill in the cloud data
  pcl::PCDReader reader;
  // Replace the path below with the path where you saved your file
  reader.read<pcl::PointXYZ> ("table_scene_lms400.pcd", *cloud);

  std::cerr << "Cloud before filtering: " << std::endl;
  std::cerr << *cloud << std::endl;

  // Create the filtering object
  pcl::StatisticalOutlierRemoval<pcl::PointXYZ> sor;
  sor.setInputCloud (cloud);
  sor.setMeanK (50);
  sor.setStddevMulThresh (1.0);
  sor.filter (*cloud_filtered);

  std::cerr << "Cloud after filtering: " << std::endl;
  std::cerr << *cloud_filtered << std::endl;

  pcl::PCDWriter writer;
  writer.write<pcl::PointXYZ> ("table_scene_lms400_inliers.pcd", *cloud_filtered, false);

  sor.setNegative (true);
  sor.filter (*cloud_filtered);
  writer.write<pcl::PointXYZ> ("table_scene_lms400_outliers.pcd", *cloud_filtered, false);

  return (0);
}

Algorithms in PCL are almost all templated and follow the same structure. First an algorithm object is created, parameters are set using setter accessors and then the result is accessed.

In this example, a pcl::StatisticalOutlierRemoval filter is created. The number of neighbors to analyze for each point is set to 50, and the standard deviation multiplier to 1. What this means is that all points who have a distance larger than 1 standard deviation of the mean distance to the query point will be marked as outliers and removed. The output is computed and stored in cloud_filtered.

// Create the filtering object
pcl::StatisticalOutlierRemoval<pcl::PointXYZ> sor;
sor.setInputCloud (cloud);
sor.setMeanK (50);
sor.setStddevMulThresh (1.0);
sor.filter (*cloud_filtered);

Changing the filter parameters we can get the outliers:

sor.setNegative (true);
sor.filter (*cloud_filtered);

Refer to the official tutorial, Writing a new PCL class, to understand better how algorithm are designed.

2.4. PCD file format

Different file formats are supported by PCL. The PCD that is Point Cloud Data can be found in binary format or in ASCII format. The following snippet represent a pcd file where are saved 5 point clouds of type x,y,z.

# .PCD v.5 - Point Cloud Data file format
FIELDS x y z
SIZE 4 4 4
TYPE F F F
WIDTH 5
HEIGHT 1
POINTS 5
DATA ascii
0.35222 -0.15188 -0.1064
-0.39741 -0.47311 0.2926
-0.7319 0.6671 0.4413
-0.73477 0.85458 -0.036173
-0.4607 -0.27747 -0.91676

2.5. PCL and ROS

2.6. PCL and Qt