I have a cube-shaped point cloud whose x, y, & z-coordinates range from -1.0 to 1.0 unit.
#include <pcl/ModelCoefficients.h>
#include <pcl/common/common.h>
#include <pcl/filters/crop_box.h>
#include <pcl/filters/voxel_grid.h>
#include <pcl/io/pcd_io.h>
#include <pcl/point_types.h>
#include <pcl/visualization/pcl_visualizer.h>
#include <iostream>
#include <string>
#include <vector>
int main() {
pcl::PointCloud<pcl::PointXYZRGB>::Ptr
main_cloud_ptr(new pcl::PointCloud<pcl::PointXYZRGB>),
cropped_cloud_ptr1(new pcl::PointCloud<pcl::PointXYZRGB>),
cropped_cloud_ptr2(new pcl::PointCloud<pcl::PointXYZRGB>);
float x_start = -1.0, x_end = 1.0, x_resolution = 0.05;
float y_start = -1.0, y_end = 1.0, y_resolution = 0.05;
float z_start = -1.0, z_end = 1.0, z_resolution = 0.05;
float rgb_color_mul = 5.0;
float rgb_color_add = 10.0;
pcl::PointXYZRGB pt;
for (float i = x_start; i < x_end; i += x_resolution) {
for (float j = y_start; j < y_end; j += y_resolution) {
for (float k = z_start; k < z_end; k += z_resolution) {
pt.x = i;
pt.y = j;
pt.z = k;
pt.r = i * 100 + 100;
pt.g = 200;
pt.b = j * 100 + 50;
main_cloud_ptr->points.push_back(pt);
}
}
}
std::cout << "main_cloud_ptr->points.size() = " << main_cloud_ptr->points.size() << "\n";
pcl::visualization::PCLVisualizer::Ptr visualizer1(new pcl::visualization::PCLVisualizer("visualizer1 -- main_cloud_ptr"));
visualizer1->setBackgroundColor(0, 0, 0);
visualizer1->addPointCloud<pcl::PointXYZRGB>(main_cloud_ptr, "main_cloud_ptr");
visualizer1->setPointCloudRenderingProperties(pcl::visualization::PCL_VISUALIZER_POINT_SIZE, 2, "main_cloud_ptr");
visualizer1->addCoordinateSystem(0.5);
visualizer1->addCube(-1.0, 1.0, -1.0, 1.0, -1.0, 1.0, 1.0, 1.0, 1.0, "cube1");
visualizer1->setRepresentationToWireframeForAllActors();
while (!visualizer1->wasStopped()) {
visualizer1->spinOnce();
}
Now, using pcl::CropBox
filter, I want to accomplish two different tasks and get two different types of slices from my cube-shaped point cloud:
take out a thin slice of the point cloud which is
- parallel to XY plane
- perpendicular to z-axis
- at a certain distance on z-axis from the origin e.g. 0.3-0.5
take out a thin slice of the point cloud
- which is tilted 45° based on the x-axis of the box itself rather than 45° rotation wrt global x-axis
- whose centroid is at 0.4 unit distance on z-axis
For task 1, I did something like this and it's perfectly OK:
pcl::CropBox<pcl::PointXYZRGB> box_filter1;
box_filter1.setMin(Eigen::Vector4f(-1.0, -1.0, 0.3, 1.0));
box_filter1.setMax(Eigen::Vector4f(1.0, 1.0, 0.5, 1.0));
box_filter1.setInputCloud(main_cloud_ptr);
box_filter1.filter(*cropped_cloud_ptr1);
pcl::visualization::PCLVisualizer::Ptr visualizer2(new pcl::visualization::PCLVisualizer("visualizer2 -- cropped_cloud_ptr1"));
visualizer2->setBackgroundColor(0, 0, 0);
visualizer2->addPointCloud<pcl::PointXYZRGB>(cropped_cloud_ptr1, "cropped_cloud_ptr1");
visualizer2->setPointCloudRenderingProperties(pcl::visualization::PCL_VISUALIZER_POINT_SIZE, 2, "cropped_cloud_ptr1");
visualizer2->addCoordinateSystem(0.5);
visualizer2->addCube(-1.0, 1.0, -1.0, 1.0, -1.0, 1.0, 1.0, 1.0, 1.0, "cube2");
visualizer2->setRepresentationToWireframeForAllActors();
while (!visualizer2->wasStopped()) {
visualizer2->spinOnce();
}
For task 2, I almost followed same procedure at task 1 except for setting rotation of pcl::CropBox
using setRotation
method and did something like this:
pcl::CropBox<pcl::PointXYZRGB> box_filter2;
box_filter2.setMin(Eigen::Vector4f(-1.0, -1.0, 0.3, 1.0));
box_filter2.setMax(Eigen::Vector4f(1.0, 1.0, 0.5, 1.0));
box_filter2.setRotation(Eigen::Vector3f(M_PI / 4, 0, 0));
box_filter2.setInputCloud(main_cloud_ptr);
box_filter2.filter(*cropped_cloud_ptr2);
pcl::visualization::PCLVisualizer::Ptr visualizer3(new pcl::visualization::PCLVisualizer("visualizer2 -- cropped_cloud_ptr2"));
visualizer3->setBackgroundColor(0, 0, 0);
visualizer3->addPointCloud<pcl::PointXYZRGB>(cropped_cloud_ptr2, "cropped_cloud_ptr2");
visualizer3->setPointCloudRenderingProperties(pcl::visualization::PCL_VISUALIZER_POINT_SIZE, 2, "cropped_cloud_ptr2");
visualizer3->addCoordinateSystem(0.5);
visualizer3->addCube(-1.0, 1.0, -1.0, 1.0, -1.0, 1.0, 1.0, 1.0, 1.0, "cube3");
visualizer3->setRepresentationToWireframeForAllActors();
while (!visualizer3->wasStopped()) {
visualizer3->spinOnce();
}
return 0;
}
However, in that case, the box gets rotated by global X-axis.
This not what I want. I want to rotate/tilt the box wrt its own x-axis only (i.e. imagine a local coordinate system of the box, origin located at the centroid of box, and all the local x, y, & z-axis are parallel to global x, y, & z-axis.)
I know there is a setTransform
method in pcl::CropBox
which takes an object of Eigen::Affine3f
as input argument. But, how can I use it in my case to rotate/title the cropBox wrt its own x-axis only?
If there are any other ways to solve this problem then also please share your thoughts/solution.
pcl::BoxClipper3D< PointT >
class and for it, it's mentioned that "Implementation of a box clipper in 3D. Actually it allows affine transformations, thus any parallelepiped in general pose. The affine transformation is used to transform the point before clipping it using the unit cube centered at origin and with an extend of -1 to +1 in each dimension." But, how to apply affine transformation usingEigen
? pointclouds.org/documentation/classpcl_1_1_box_clipper3_d.html – Rodmur