Attention

You are viewing an older version of the documentation. The latest version is 2.2.

Intel® oneAPI Base Toolkit's Iterative Closest Point (ICP)

The standard Iterative Closest Point (ICP) has been optimized using Intel® oneAPI Base Toolkit. Joint ICP and Generalized ICP are not currently optimized with Intel® oneAPI Base Toolkit. This tutorial will cover the standard ICP.

Iterative Closest Point

Iterative closest point (ICP) is an algorithm employed to minimize the difference between two clouds of points.

The ICP steps are:

  1. For each point in the source point cloud, match the closest point in the reference/target point cloud.

  2. Estimate the combination of rotation and translation using a root mean square point to point distance metric minimization technique which will best align each source point to its match found in the previous step.

  3. Transform the source points using the obtained transformation.

  4. Iterate (re-associate the points, and so on).

For details regarding the PCL Registration module and it’s internal algorithmic details, please refer to the registration_api for details.

Note

This tutorial can be run both inside and outside a Docker* image. We assume that the pcl-oneapi-tutorial Deb package has been installed, and the user has copied the tutorial directory from /opt/intel/pcl/oneapi/tutorials/ to a user-writable directory.

  1. Prepare the environment:

    cd <path-to-oneapi-tutorials>/registration
    
    Copy to clipboard
  2. oneapi_icp_example.cpp should be in the directory with following content:

     1#include <pcl/oneapi/registration/icp.h>
     2#include <pcl/console/parse.h>
     3#include <pcl/point_types.h>
     4#include <pcl/point_cloud.h>
     5#include <pcl/point_representation.h>
     6#include <pcl/io/pcd_io.h>
     7
     8
     9using namespace pcl;
    10using namespace pcl::io;
    11using namespace pcl::console;
    12
    13/* ---[ */
    14int
    15main (int argc, char** argv)
    16{
    17  std::cout << "Running on device: " << dpct::get_default_queue().get_device().get_info<sycl::info::device::name>() << "\n";
    18
    19  // Load the files
    20  PointCloud<PointXYZ>::Ptr src, tgt;
    21  src.reset (new PointCloud<PointXYZ>);
    22  tgt.reset (new PointCloud<PointXYZ>);
    23  if (loadPCDFile ("test_P.pcd", *src) == -1 || loadPCDFile ("test_Q.pcd", *tgt) == -1)
    24  {
    25    print_error ("Error reading the input files!\n");
    26    return (-1);
    27  }
    28
    29  PointCloud<PointXYZ> output;
    30  // Compute the best transformtion
    31  pcl::oneapi::IterativeClosestPoint<PointXYZ, PointXYZ> reg;
    32  reg.setMaximumIterations(20);
    33  reg.setTransformationEpsilon(1e-12);
    34  reg.setMaxCorrespondenceDistance(2);
    35
    36  reg.setInputSource(src);
    37  reg.setInputTarget(tgt);
    38
    39  // Register
    40  reg.align(output); //point cloud output of alignment i.e source cloud after transformation is applied.
    41
    42  Eigen::Matrix4f transform = reg.getFinalTransformation();
    43
    44  std::cerr << "Transform Matrix:" << std::endl;
    45  std::cerr << transform << std::endl;
    46  // Write transformed data to disk
    47  savePCDFileBinary ("source_transformed.pcd", output);
    48}
    49/* ]--- */
    
    Copy to clipboard
  3. Source the Intel® oneAPI Base Toolkit environment:

    source /opt/intel/oneapi/setvars.sh
    
    Copy to clipboard
  4. (Optional) Setup proxy setting to download test data:

    export http_proxy="http://<http_proxy>:port"
    export https_proxy="http://<https_proxy>:port"
    
    Copy to clipboard
  5. Build the code:

    mkdir build && cd build
    cmake ../
    make -j
    
    Copy to clipboard
  6. Run the binary:

    ./oneapi_icp_example
    
    Copy to clipboard
  7. Expected results example:

    Transform Matrix:
    0.998899   0.0107221   0.0457259   0.0790768
    -0.00950837    0.999602  -0.0266773   0.0252976
    -0.0459936    0.026213    0.998599   0.0677631
            0           0           0           1
    
    Copy to clipboard

Code Explanation

Define two input point Clouds (src, tgt), declare the output point cloud, and load the test data from GitHub*.

  // Load the files
  PointCloud<PointXYZ>::Ptr src, tgt;
  src.reset (new PointCloud<PointXYZ>);
  tgt.reset (new PointCloud<PointXYZ>);
  if (loadPCDFile ("test_P.pcd", *src) == -1 || loadPCDFile ("test_Q.pcd", *tgt) == -1)
  {
    print_error ("Error reading the input files!\n");
    return (-1);
  }
Copy to clipboard

Declare oneapi ICP, and set the input configuration parameters.

  // Compute the best transformtion
  pcl::oneapi::IterativeClosestPoint<PointXYZ, PointXYZ> reg;
  reg.setMaximumIterations(20);
  reg.setTransformationEpsilon(1e-12);
  reg.setMaxCorrespondenceDistance(2);
Copy to clipboard

Set the two input point clouds for the ICP module, and call the method to align the two point clouds. The align method populates the output point cloud, passed as a parameter, with the src point cloud transformed using the computed transformation matrix.

  reg.setInputSource(src);
  reg.setInputTarget(tgt);

  // Register
  reg.align(output); //point cloud output of alignment i.e source cloud after transformation is applied.
Copy to clipboard

Get the computed matrix transformation, print it, and save the transformed point cloud.

  Eigen::Matrix4f transform = reg.getFinalTransformation();

  std::cerr << "Transform Matrix:" << std::endl;
Copy to clipboard