PCL自定义点云结构
1 背景
以前在使用PCL进行点云处理中,基本都使用PCL自带结构。最近工作中,拿到车端语义点云数据,其中一个任务就是需要点云融合对齐(内部涉及到矢量提取)。由于输出点云需要带对应属性,在PCL采样后也能正常绑定点云结构信息,这时就涉及到自定义点云结构。由于PCL自定义结构有自己的特殊方式,在使用中踩过一些坑,有坑就得填,因此单开篇填坑。
2 方式
2.1 原方式
这里可以按类似如下方式编写代码,然后使用自定义类CustomPoint_t
#define PCL_NO_PRECOMPILE
#include <pcl/point_types.h>
#include <pcl/point_cloud.h>
//1. 自定义结构
struct EIGEN_ALIGN16 CustomPoint_t
{
EIGEN_MAKE_ALIGNED_OPERATOR_NEW //1.1 申明内存对齐
PCL_ADD_POINT4D; //1.2 PCL宏里定义了x,y,z以及一些函数接口
int other; //1.3 定义的其它属性
};
//2. 注册自定义结构
POINT_CLOUD_REGISTER_POINT_STRUCT(CustomPoint_t,
(float, x, x)
(float, y, y)
(float, z, z)
(int, other, other));
//3. 测试使用
void test()
{
pcl::PointCloud<custompoint_t> cloud;
...
}
上面代码里需要注意几个点:
(1) PCL_NO_PRECOMPILE: 定义代码放在包含PCL头文件前面。
(2) PCL_ADD_POINT4D : 结构体里尽量使用这个宏,不要自己单独定义(x,y,z)坐标,否则还需要单独实现一些函数接口。
(3) POINT_CLOUD_REGISTER_POINT_STRUCT : 这个宏一定放在没有namespace的外面,如果放在namespace内,会编译报错,如下代码就会报错(注意,注释1里的自定义结构不受这个限制)
...
namespace point
{
//1. 自定义结构
struct EIGEN_ALIGN16 CustomPoint_t
{
EIGEN_MAKE_ALIGNED_OPERATOR_NEW
PCL_ADD_POINT4D;
int other;
};
//2. 注册自定义结构
POINT_CLOUD_REGISTER_POINT_STRUCT(CustomPoint_t,
(float, x, x)
(float, y, y)
(float, z, z)
(int, other, other));
}
...
2.2 新方式
这里约定编译环境A满足如下条件:
(1) Eigen版本不低于3.3.7
(2) c++编译版本不低于17
(3) 编译器支持(2)的情况下,自动处理内存对齐问题
如果PCL的库由编译环境A编译出,实际工程项目也是在环境A里编译,那么上面EIGEN_ALIGN16与EIGEN_MAKE_ALIGNED_OPERATOR_NEW宏可以不再使用,示例中自定义结构部分代码可以改写为如下方式
struct CustomPoint_t
{
PCL_ADD_POINT4D; //PCL宏里定义了x,y,z以及一些函数接口
int other; //定义的其它属性
};
这里需要注意的是,如果PCL库不是在A环境下编译生成,但项目是在A环境下编译,这时使用新的非申明方式编译,可能出现内存对齐错误。即使在代码里进行了宏申明也会可能出错,因为最新的Eigen里已经自动将A环境下的宏定义为了一个空的代码,和不申明宏没有区别。在种情况下,最好的办法就是,PCL源码在当前项目环境进行编译,然后链接。