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.创建圆柱面点云
- 检查输入的圆柱面参数是否合法
- 先创建中心点为原点,轴线向量为Z轴的圆柱面
- 将圆柱面进行刚性变换,旋转平移变换到设置的参数
- 可视化验证
关键函数代码如下
//根据圆柱面参数创建空间任意圆柱面点云
//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就是圆柱的半径