空间平面旋转与xoy平行

发布于:2025-08-03 ⋅ 阅读:(16) ⋅ 点赞:(0)

空间平面旋转与xoy平行

法向量

空间平面ax+by+cz+d=0的其中一个法向量(a,b,c),法向量垂直于空间平面。目标平面平行于xoy的平面为0x+0y+cz+d=0;其中一个法向量为(0,0,c),c可以为不为0的任意值,取(0,0,1),目标平面的的法向量垂直于xoy平面

向量叉乘点乘

两个向量的点乘叉乘的区别
点乘计算两向量的投影关系并返回标量,反映两向量方向相似性
叉乘则生成垂直于原向量平面的新向量并反映空间结构关系
点乘获取旋转角度
叉乘获取旋转轴

// 平面生成
void generatePlanePointCloud(float a, float b, float c, float d,
	pcl::PointCloud<pcl::PointXYZ>::Ptr& cloud) 
{

	for (int i = 0; i < 10000; i++)
	{
		double x = rand() % 500;
		double y = rand() % 500;
		double z = (a * x + b * y + d) / (0 - c);//假设平面方程类型 ax+by+cz+d=0
		Eigen::Vector3f point(x, y, z);
		cloud->points.emplace_back(point.x(), point.y(), point.z());
	}
}
int main() 
{
	pcl::PointCloud<pcl::PointXYZ>::Ptr cloud(new pcl::PointCloud<pcl::PointXYZ>());

	// 定义平面 ax + by + cz + d = 0 的参数
	float a = -2.0f, b = -9.0f, c = 8.0f, d = 100.0f;

	// 调用函数生成平面点云
	generatePlanePointCloud(a, b, c, d, cloud);
	
	//点云几何中心 可平移点云到坐标原点
	Eigen::Vector4f centroid;					
	pcl::compute3DCentroid(*cloud, centroid);
	Eigen::Matrix4f transform_matrix = Eigen::Matrix4f::Identity();
	Eigen::Vector3f translationxyz(-centroid(0), -centroid(1), -centroid(2));
	transform_matrix.block<3, 1>(0, 3) = translationxyz;
	pcl::PointCloud<pcl::PointXYZ>::Ptr ocloud(new pcl::PointCloud<pcl::PointXYZ>);
	pcl::transformPointCloud(*cloud, *ocloud, transform_matrix);
   // 平面法向量和目标平面法向量
	Eigen::Vector3f v1(a, b, c), v2(0, 0, 1);
	// 点乘获取旋转夹角
	float RotateRad = pcl::getAngle3D(v1, v2);
	// 叉乘获取旋转轴 旋转轴需要单位化
	Eigen::Vector3f RotateAxis = v1.cross(v2).normalized();
	// 点乘获取旋转夹角
	float RotateRad1 = RotateRad;
	float angle = acos(v1.normalized().dot(v2.normalized()));
   // 生成放射变换单位矩阵4x4 Affine3f不是matrix但是有matrix函数
	Eigen::Affine3f rotation = Eigen::Affine3f::Identity();
	// 将旋转轴和旋转角添加到仿射矩阵
	rotation.rotate(Eigen::AngleAxisf(RotateRad1, RotateAxis));
	
	// 生成单位旋转矩阵3x3
	Eigen::Matrix3f rotation_matrix = Eigen::Matrix3f::Identity();
	// 生成旋转向量
	Eigen::AngleAxisf rotation_vector(RotateRad, RotateAxis); 
	// 注意:旋转轴必须为单位向量
	rotation_matrix = rotation_vector.toRotationMatrix();
	// 使用罗德里格斯公式得到旋转矩阵
	
	// 初始化平移向量(此处为0)
	Eigen::Vector3f translation(0, 0, 0);
	// 创建4x4变换矩阵
	Eigen::Matrix4f transform_matrix1 = Eigen::Matrix4f::Identity();
	transform_matrix1.block<3, 3>(0, 0) = rotation_matrix; // 设置旋转部分
	transform_matrix1.block<3, 1>(0, 3) = translation;     // 设置平移部分
	
	pcl::PointCloud<pcl::PointXYZ>::Ptr xcloud(new pcl::PointCloud<pcl::PointXYZ>);
	// 平面点云进行仿射变换
	pcl::transformPointCloud(*ocloud, *xcloud, transform_matrix1);
	pcl::PointCloud<pcl::PointXYZ>::Ptr ycloud(new pcl::PointCloud<pcl::PointXYZ>);
	// 平面点云进行仿射变换
	pcl::transformPointCloud(*cloud, *ycloud, rotation);
	
	boost::shared_ptr<pcl::visualization::PCLVisualizer> view(new pcl::visualization::PCLVisualizer("3D Viewer"));
	pcl::visualization::PointCloudColorHandlerCustom<pcl::PointXYZ> src_h(xcloud, 0, 255, 0);//定义颜色 
	pcl::visualization::PointCloudColorHandlerCustom<pcl::PointXYZ> src_h1(ycloud, 0, 0, 255);//定义颜色 
	pcl::visualization::PointCloudColorHandlerCustom<pcl::PointXYZ> src_h2(ocloud, 0, 255, 255);//定义颜色 
	view->addCoordinateSystem(500.0,0,0,0); // 添加坐标轴,大小为500.0
	view->addPointCloud<pcl::PointXYZ>(cloud, "cloud_in");

	view->addPointCloud<pcl::PointXYZ>(xcloud, src_h, "clound_xuanzhuan");
	view->addPointCloud<pcl::PointXYZ>(ycloud, src_h1, "xuanzhuan1");
	//view->addPointCloud<pcl::PointXYZ>(ocloud, src_h2, "xuanzhuan2");
	view->setPointCloudRenderingProperties(pcl::visualization::PCL_VISUALIZER_COLOR, 1, 0, 0, "cloud_in");
	while (!view->wasStopped())
	{
		view->spinOnce(100);
		boost::this_thread::sleep(boost::posix_time::microseconds(100000));
	}
	return 0;
}

点云图