Concatenate the fields of two Point Clouds
In this tutorial we will learn how to concatenating the fields (e.g., dimensions) of two different point clouds. The constraint imposed here is that the number of points in the two datasets has to be equal.
The code
First, create a file, let’s say, concatenate_fields.cpp
in your favorite
editor, and place the following code inside it:
1#include <iostream>
2#include <pcl/common/io.h> // for concatenateFields
3#include <pcl/point_types.h>
4
5int
6 main ()
7{
8 pcl::PointCloud<pcl::PointXYZ> cloud_a;
9 pcl::PointCloud<pcl::Normal> cloud_b;
10 pcl::PointCloud<pcl::PointNormal> cloud_c;
11
12 // Fill in the cloud data
13 cloud_a.width = cloud_b.width = 5;
14 cloud_a.height = cloud_b.height = 1;
15 cloud_a.resize (cloud_a.width * cloud_a.height);
16 cloud_b.resize (cloud_b.width * cloud_b.height);
17
18 for (std::size_t i = 0; i < cloud_a.size (); ++i)
19 {
20 cloud_a[i].x = 1024 * rand () / (RAND_MAX + 1.0f);
21 cloud_a[i].y = 1024 * rand () / (RAND_MAX + 1.0f);
22 cloud_a[i].z = 1024 * rand () / (RAND_MAX + 1.0f);
23 }
24
25 for (std::size_t i = 0; i < cloud_b.size (); ++i)
26 {
27 cloud_b[i].normal[0] = 1024 * rand () / (RAND_MAX + 1.0f);
28 cloud_b[i].normal[1] = 1024 * rand () / (RAND_MAX + 1.0f);
29 cloud_b[i].normal[2] = 1024 * rand () / (RAND_MAX + 1.0f);
30 }
31
32 std::cerr << "Cloud A: " << std::endl;
33 for (std::size_t i = 0; i < cloud_a.size (); ++i)
34 std::cerr << " " << cloud_a[i].x << " " << cloud_a[i].y << " " << cloud_a[i].z << std::endl;
35
36 std::cerr << "Cloud B: " << std::endl;
37 for (std::size_t i = 0; i < cloud_b.size (); ++i)
38 std::cerr << " " << cloud_b[i].normal[0] << " " << cloud_b[i].normal[1] << " " << cloud_b[i].normal[2] << std::endl;
39
40 pcl::concatenateFields (cloud_a, cloud_b, cloud_c);
41 std::cerr << "Cloud C: " << std::endl;
42 for (std::size_t i = 0; i < cloud_c.size (); ++i)
43 std::cerr << " " <<
44 cloud_c[i].x << " " << cloud_c[i].y << " " << cloud_c[i].z << " " <<
45 cloud_c[i].normal[0] << " " << cloud_c[i].normal[1] << " " << cloud_c[i].normal[2] << std::endl;
46
47 return (0);
48}
The explanation
Now, let’s break down the code piece by piece.
pcl::PointCloud<pcl::PointXYZ> cloud_a;
pcl::PointCloud<pcl::Normal> cloud_b;
pcl::PointCloud<pcl::PointNormal> cloud_c;
define the three Point Clouds: two inputs (cloud_a and cloud_b), one output (cloud_c).
The lines:
// Fill in the cloud data
cloud_a.width = cloud_b.width = 5;
cloud_a.height = cloud_b.height = 1;
cloud_a.resize (cloud_a.width * cloud_a.height);
cloud_b.resize (cloud_b.width * cloud_b.height);
for (std::size_t i = 0; i < cloud_a.size (); ++i)
{
cloud_a[i].x = 1024 * rand () / (RAND_MAX + 1.0f);
cloud_a[i].y = 1024 * rand () / (RAND_MAX + 1.0f);
cloud_a[i].z = 1024 * rand () / (RAND_MAX + 1.0f);
}
for (std::size_t i = 0; i < cloud_b.size (); ++i)
{
cloud_b[i].normal[0] = 1024 * rand () / (RAND_MAX + 1.0f);
cloud_b[i].normal[1] = 1024 * rand () / (RAND_MAX + 1.0f);
cloud_b[i].normal[2] = 1024 * rand () / (RAND_MAX + 1.0f);
}
fill in the data for the two input point clouds.
Then, lines:
std::cerr << "Cloud A: " << std::endl;
for (std::size_t i = 0; i < cloud_a.size (); ++i)
std::cerr << " " << cloud_a[i].x << " " << cloud_a[i].y << " " << cloud_a[i].z << std::endl;
std::cerr << "Cloud B: " << std::endl;
for (std::size_t i = 0; i < cloud_b.size (); ++i)
std::cerr << " " << cloud_b[i].normal[0] << " " << cloud_b[i].normal[1] << " " << cloud_b[i].normal[2] << std::endl;
display the content of cloud_a and cloud_b to screen.
In line:
pcl::concatenateFields (cloud_a, cloud_b, cloud_c);
we create cloud_c by concatenating the fields of cloud_a and cloud_b together.
Finally:
std::cerr << "Cloud C: " << std::endl;
for (std::size_t i = 0; i < cloud_c.size (); ++i)
std::cerr << " " <<
cloud_c[i].x << " " << cloud_c[i].y << " " << cloud_c[i].z << " " <<
cloud_c[i].normal[0] << " " << cloud_c[i].normal[1] << " " << cloud_c[i].normal[2] << std::endl;
is used to show the content of cloud_c.
Compiling and running the program
Add the following lines to your CMakeLists.txt file:
1cmake_minimum_required(VERSION 3.5 FATAL_ERROR)
2
3project(concatenate_fields)
4
5find_package(PCL 1.2 REQUIRED)
6
7include_directories(${PCL_INCLUDE_DIRS})
8link_directories(${PCL_LIBRARY_DIRS})
9add_definitions(${PCL_DEFINITIONS})
10
11add_executable (concatenate_fields concatenate_fields.cpp)
12target_link_libraries (concatenate_fields ${PCL_LIBRARIES})
After you have made the executable, you can run it. Simply do:
$ ./concatenate_fields
You will see something similar to:
Cloud A:
0.352222 -0.151883 -0.106395
-0.397406 -0.473106 0.292602
-0.731898 0.667105 0.441304
-0.734766 0.854581 -0.0361733
-0.4607 -0.277468 -0.916762
Cloud B:
0.183749 0.968809 0.512055
-0.998983 -0.463871 0.691785
0.716053 0.525135 -0.523004
0.439387 0.56706 0.905417
-0.579787 0.898706 -0.504929
Cloud C:
0.352222 -0.151883 -0.106395 0.183749 0.968809 0.512055
-0.397406 -0.473106 0.292602 -0.998983 -0.463871 0.691785
-0.731898 0.667105 0.441304 0.716053 0.525135 -0.523004
-0.734766 0.854581 -0.0361733 0.439387 0.56706 0.905417
-0.4607 -0.277468 -0.916762 -0.579787 0.898706 -0.504929