这篇文章整理了常用PCL函数(用途、参数的意义,必要时也会列出该函数所在的头文件)以及一些其它关于PCL库的知识。

Empirical Observation

sort by alphabet.

pcl::Octree

adoptBoundingBoxToPoint

This function can adjust bounding box even the box has been defined manually.

defineBoundingBox

pcl::Octree::OctreePointCloud::defineBoundingBox: input bounding box will be used as initial bounding box first. Then the box will be adjusted to a cube. The adjusted bounding box always is different with the initial bounding box. #####

一、基础知识

1. data()

2

chapter 2 octree

getIntersectedVoxelCenters

pcl::octree::OctreePointCloudSearch::getIntersectedVoxelCenters(Eigen::Vector3f origin,
                                                                Eigen::Vector3f direction,
                                                                AlignedPointTVector& voxel_center_list,
                                                                int max_voxel_count);

whether normalize direction can influence the result.

  1. Best Case $𝑂(log⁡(𝑁))$ In the ideal case, the octree is well-balanced, and the ray intersects only a small number of voxels, minimizing traversal.
  2. Average Case $𝑂(𝑘+log(𝑁))$ Where 𝑘 is the number of voxels intersected by the ray. Traversing the octree to find the ray’s starting position is $𝑂(log⁡(𝑁))$, and processing intersected voxels depends on 𝑘.
  3. Worst Case $𝑂(𝑘)$ If the ray intersects a large number of voxels (e.g., when the ray passes through the entire octree), the complexity is proportional to the number of intersected voxels.

三、位姿变换

#include <pcl/common/transforms.h> //主要内容为:表示位姿的几种方法之间的转换
//cloud_in和cloud_out为::Ptr点云指针; Matrix4f=Affine3f
void pcl::transformPointCloud(const *cloud_in, *cloud_out, const Eigen::Matrix4f  & transform)
2. pcl/common/eigen.h

4×4变换矩阵 transformation Eigen::Affine3f 仿射矩阵 –> pos和rpy 位置和角度 6D位姿 ;输入和输出参数为float

#include <pcl/common/eigen.h>

// 精度可能存在问题
pcl::getTranslationAndEulerAngles(imuOdomAffineLast, x, y, z, roll, pitch, yaw);

// 输入和输出参数为float
Eigen::Affine3f lastPoseInMapAff = pcl::getTransformation(x, y, z, roll, pitch, yaw);

四、匹配和配准

1. ndt.h

setTransformationEpsilon(ndt_epsilon_); // the transformation epsilon in order for an optimization to be considered as having converged to the final solution.
setStepSize(ndt_step_size_); // Set the newton line search maximum step length.
setResolution(ndt_resolution_); // Set the voxel grid resolution.
getFitnessScore	(	double 	max_range = std::numeric_limits<double>::max()	); // Obtain the Euclidean fitness score (e.g., mean of squared distances from the source to the target)

2. pcl/kdtree/kdtree_flann.h

#include <pcl/kdtree/kdtree_flann.h>
// max_nn: num of returned points, if max_nn==0, return all.
kdtreeSurroundingKeyPoses->radiusSearch(point, radius, k_indices, k_sqr_distances,	max_nn);

pcl::moveFromROSMsg(currentCloudMsg, *laserCloudIn);

3. pcl/registration/icp.h

#include <pcl/registration/icp.h>
pcl::IterativeClosestPoint<pcl::PointXYZ, pcl::PointXYZ> icp;
pcl::PointCloud<pcl::PointXYZ>::Ptr loopSourceCorner;
icp.setInputSource(loopSourceCorner); //注意输入的点云的数据类型为Ptr

五、文件处理

1. 加载文件
#include <pcl/io/pcd_io.h>
//temFilePath包含文件名和后缀;thisCornerCloud为::Ptr点云指针;
pcl::io::loadPCDFile(temFilePath, *thisCornerCloud);


2

other

1.

You can use the following code to print out the fields of your registered point type and verify the order:

template <typename PointT>
void printPointTypeFields() {
    std::cout << "Fields in the point type:\n";
    for (const auto& field : pcl::traits::fieldList<PointT>::type::fields) {
        std::cout << "  " << field.name << "\n";
    }
}
2. pcl::octree

the returned value of pcl::Octree::getIntersectedVoxels is not guaranteed to be sorted by default.

3.

leaf_begin(): breadth-first leaf_depth_begin(): depth-first manner

末、Q&A

1.

运行pcl_viewer时提示错误segment fault(core dump)。可能是因为驱动安装有问题,或者pcl的版本不适配。

2.

code below is used to define and register a point type to PCL.

#include <pcl/point_types.h>

namespace custom_pcl
{
  struct MyCustomPoint
  {
    PCL_ADD_POINT4D;  // This macro adds padding for alignment and the XYZ fields
    int id;           // Add the custom field `id`
    EIGEN_MAKE_ALIGNED_OPERATOR_NEW  // Ensure proper alignment
  };
}

POINT_CLOUD_REGISTER_POINT_STRUCT(
  custom_pcl::MyCustomPoint,  // Fully qualified name of the struct
  (float, x, x)               // Mapping: type, field name in struct, field name in PCL
  (float, y, y)
  (float, z, z)
  (int, id, id)               // Include the new `id` field
)

Note that the POINT_CLOUD_REGISTER_POINT_STRUCT macro must be placed in the global namespace. You cannot place it inside a namespace because the macro relies on global templates and compile-time mechanisms that PCL expects in the global scope. However, you can still define your custom point type within a namespace. Only the macro itself has to remain in the global scope.

3.

Define a point type from existing point type in PCL

namespace custom_pcl
{
  struct EIGEN_ALIGN16 MyCustomPoint : public pcl::PointXYZINormal
  {
    int id;  // Additional field
    EIGEN_MAKE_ALIGNED_OPERATOR_NEW  // Ensure proper memory alignment
  };
}

POINT_CLOUD_REGISTER_POINT_STRUCT(
  custom_pcl::MyCustomPoint,
  (float, x, x)
  (float, y, y)
  (float, z, z)
  (float, intensity, intensity)
  (float, normal_x, normal_x)
  (float, normal_y, normal_y)
  (float, normal_z, normal_z)
  (float, curvature, curvature)
  (int, id, id)
)

Then I got a warning.

warning: offsetof within non-standard-layout type 'sinoslam::Pointid' is conditionally-supported [-Winvalid-offsetof]

Standard Layout Requirements:

  1. A standard-layout type is one where all non-static data members are laid out in a well-defined order in memory, and there is no ambiguity due to inheritance.
  2. Adding new fields to a derived class makes the layout non-standard because the base class may already contain its own fields, making offsets potentially ambiguous.
4.

code below

template <class PointT>
bool calculateNormal(const pcl::PointCloud<PointT>::Ptr &cloud, Eigen::Vector3f &normal) {}

I got an error during compilation:

error : need 'typename' before 'pcl::PointCloud<PointT>::Ptr' because 'pcl::PointCloud<PointT>' is a dependent bool calculateNormal(const pcl::PointCloud<PointT>::Ptr &cloud, Eigen::Vector3f &normal)

The error arises because in a templated function, PointT is a dependent type, and the compiler needs explicit help to identify pcl::PointCloud::Ptr as a type. To fix this, you must use the typename keyword to specify that it is a type. Here's the corrected code:

template <typename PointT>
bool calculateNormal(const typename pcl::PointCloud<PointT>::Ptr &cloud, Eigen::Vector3f &normal) {}

In fact, the corrected code can’t be compiled successfully. Because

5
octree_search.hpp : 396 : 46 : error : 'const struct custom::Pointid' has no member named 'getVector3fMap' return (point_a.getVector3fMap() - point_b.getVector3fMap()).squaredNorm();

The error indicates that the structure custom::Pointid does not have a member function or attribute named getVector3fMap. This function is a part of the PCL library for points that are derived from pcl::PointXYZ or similar types. Your custom Pointid struct likely does not inherit from a pcl::PointXYZ-like structure or does not implement this function.