PCL创建圆柱面点云

PCL创建各种形状点云

第一章 PCL创建线段点云



前言

点云库 (PCL) 是一个独立的、大规模的、开放的 2D/3D 图像和点云处理项目。PCL功能强大,但是却并不包含创建点云功能,尤其是一些常见的点云,如:线段、球、立方体、圆柱面等,而是仅在可视化visualization类中包含一些常见的几何形状,如:线段、球、立方体等,无法作为点云数据传递,因此打算自己写一下,本文是关于圆柱面点云的创建。
在这里插入图片描述


一、圆柱面是什么?

示例:柱面(cylinder)是直线沿着一条定曲线平行移动所形成的曲面,即动直线沿着一条定曲线平行移动所形成的曲面,动直线称为柱面的直母线,定曲线称为柱面的准线。当准线是圆时所得柱面称为圆柱面,如图所示。当已知圆柱面轴线上的一点、轴线向量和半径(7维数据),就能确定一个圆柱面,这也是PCL中定义圆柱面的方法。

在这里插入图片描述

二、圆柱面点云创建步骤

1.引入库

PCL环境配置参见:Windows系统下5分钟配置好PCL(debug和release)

代码如下:

#include <pcl/point_types.h>
#include <pcl/io/pcd_io.h>
#include <pcl/visualization/pcl_visualizer.h>
#include <pcl/common/transforms.h>
#include <pcl/ModelCoefficients.h>

2.创建圆柱面点云

  1. 检查输入的圆柱面参数是否合法
  2. 先创建中心点为原点,轴线向量为Z轴的圆柱面
  3. 将圆柱面进行刚性变换,旋转平移变换到设置的参数
  4. 可视化验证

关键函数代码如下

//根据圆柱面参数创建空间任意圆柱面点云
//param[in]  pcl::ModelCoefficients::Ptr& coefficients_cylinder://圆柱面参数:系数0、1、2代表圆柱轴线上的原点,3、4、5代表这条轴线的方向向量,系数6就是圆柱的半径。
//param[in] valization:默认可视化
//param[out] cloud:PCD格式的点云文件
void CreatCylinder(pcl::ModelCoefficients::Ptr& coefficients_cylinder, pcl::PointCloud<pcl::PointXYZ>::Ptr& cloud, bool valization = true) {
    
    
	//检查参数
	if (coefficients_cylinder->values.size() != 7) {
    
    
		std::cerr << "参数数目错误。。。" << std::endl;
		system("pause");
	}
	if(coefficients_cylinder->values[6]<=0){
    
    
	    std::cerr << "圆柱面半径不能小于等于0" << std::endl;
		system("pause");
	}
	//先构建轴线为Z轴的圆柱面点云
	int Num = 1200;
	float inter = 2.0 * M_PI / Num;
	Eigen::RowVectorXd vectorx(Num), vectory(Num), vectorz(Num);
	Eigen::RowVector3d axis(coefficients_cylinder->values[3], coefficients_cylinder->values[4], coefficients_cylinder->values[5]);
	float length = axis.norm();
	vectorx.setLinSpaced(Num, 0, Num - 1);
	vectory = vectorx;
	float x0, y0, z0,r0;
	x0 = coefficients_cylinder->values[0];
	y0 = coefficients_cylinder->values[1];
	z0 = coefficients_cylinder->values[2];
	r0 = coefficients_cylinder->values[6];

	pcl::PointCloud<pcl::PointXYZ>::Ptr cylinder(new pcl::PointCloud<pcl::PointXYZ>);

	for (float z(0.0); z <= length; z += 0.05)
	{
    
    
		for (auto i = 0; i < Num; ++i) {
    
    
			pcl::PointXYZ point;
			point.x = r0 * cos(vectorx[i] * inter);
			point.y = r0 * sin(vectory[i] * inter);
			point.z = z;
			cylinder->points.push_back(point);
		}
	}
	
	cylinder->width = (int)cylinder->size();
	cylinder->height = 1;
	cylinder->is_dense = false;


	//点云旋转 Z轴转到axis
	Eigen::RowVector3d  Z(0.0, 0.0, 0.1), T0(0, 0, 0), T(coefficients_cylinder->values[0], coefficients_cylinder->values[1], coefficients_cylinder->values[2]);
	Eigen::Matrix3d R;
	Eigen::Matrix3d E = Eigen::MatrixXd::Identity(3, 3);
	Eigen::Matrix4d Rotate,Translation;
	R = Eigen::Quaterniond::FromTwoVectors(Z, axis).toRotationMatrix();
	Rotate.setIdentity();
	Translation.setIdentity();

	//旋转
	Rotate.block<3, 3>(0, 0) = R;
	Rotate.block<3, 1>(0, 3) = T;
	pcl::transformPointCloud(*cylinder, *cloud, Rotate);
	

	if (valization) {
    
    
		//--------------------------------------可视化--------------------------
		pcl::visualization::PCLVisualizer viewer;
		//创建的点云和直接addcylinder函数创建的圆柱面面片进行必对
		viewer.addPointCloud<pcl::PointXYZ>(cloud, "cloud1");
		viewer.addCylinder(*coefficients_cylinder, "cylinder");
		viewer.addCoordinateSystem();
		while (!viewer.wasStopped())
		{
    
    
			viewer.spinOnce(100);
		}
	}
}

主函数代码如下

int main()
{
    
    
	pcl::ModelCoefficients::Ptr cylinder(new pcl::ModelCoefficients);
	pcl::PointCloud<pcl::PointXYZ>::Ptr cloud(new pcl::PointCloud<pcl::PointXYZ>);
	cylinder->values.resize(7);
	//随便设置参数
	cylinder->values[0] = 1;
	cylinder->values[1] = 2;
	cylinder->values[2] = 3;
	cylinder->values[3] = 4;
	cylinder->values[4] = 5;
	cylinder->values[5] = 6;
	cylinder->values[6] = 7;
	CreatCylinder(cylinder, cloud);
	//点云写入磁盘
	//pcl::io::savePCDFile("cylinder.pcd", *cloud);
	return 0;
}

可视化结果如图
在这里插入图片描述
可知创建的圆柱面点云和addcylinder()函数创建的面片完美契合!


总结

只要已知圆柱面的参数信息,就能创建与之匹配的点云。转载请注明出处!

系数0、1、2代表圆柱轴线上的原点,3、4、5代表这条轴线的方向向量,系数6就是圆柱的半径

猜你喜欢

转载自blog.csdn.net/Dbojuedzw/article/details/127472475