PCL 生成任意椭球点云
目录
- 一、算法原理
- 1、椭球定义
- 2、任意位姿的椭球
- 3、推导步骤
- 4、关键公式总结
- 二、代码实现
- 三、结果展示
一、算法原理
1、椭球定义
椭球是三维空间中的二次曲面,其标准方程为:
x 2 a 2 + y 2 b 2 + z 2 c 2 = 1 (1) \frac{x^2}{a^2} + \frac{y^2}{b^2} + \frac{z^2}{c^2} = 1\tag{1} a2x2+b2y2+c2z2=1(1)
式中, ( x , y , z ) (x, y, z) (x,y,z) 是椭球表面点的坐标, a , b , c a, b, c a,b,c 是三个半轴长度(分别对应x、y、z方向), 中心点位于坐标原点 ( 0 , 0 , 0 ) (0,0,0) (0,0,0)。
2、任意位姿的椭球
实际应用中,椭球可能位于任意位置并具有任意旋转姿态。因此,椭球表面点的通用参数化方程为:
p ( θ , ϕ ) = c + a cos θ sin ϕ ⋅ u ⃗ + b sin θ sin ϕ ⋅ v ⃗ + c cos ϕ ⋅ w ⃗ (2) p(\theta, \phi) = c + a\cos\theta\sin\phi \cdot \vec{u} + b\sin\theta\sin\phi \cdot \vec{v} + c\cos\phi \cdot \vec{w}\tag{2} p(θ,ϕ)=c+acosθsinϕ⋅u+bsinθsinϕ⋅v+ccosϕ⋅w(2)
式中, θ ∈ [ 0 , 2 π ) \theta \in [0, 2\pi) θ∈[0,2π):方位角(xy平面内的角度), ϕ ∈ [ 0 , π ] \phi \in [0, \pi] ϕ∈[0,π]:极角(从z轴正方向开始)。
3、推导步骤
-
建立局部坐标系:
{ u ⃗ = 给定方向向量 ∣ ∣ 给定方向向量 ∣ ∣ v ⃗ = u ⃗ × 全局参考向量 ∣ ∣ u ⃗ × 全局参考向量 ∣ ∣ ( 如全局参考向量 ( 1 , 0 , 0 ) ) w ⃗ = u ⃗ × v ⃗ \begin{cases} \vec{u} = \frac{\text{给定方向向量}}{||\text{给定方向向量}||} \\ \vec{v} = \frac{\vec{u} \times \text{全局参考向量}}{||\vec{u} \times \text{全局参考向量}||} \quad (\text{如全局参考向量}(1,0,0)) \\ \vec{w} = \vec{u} \times \vec{v} \end{cases} ⎩ ⎨ ⎧u=∣∣给定方向向量∣∣给定方向向量v=∣∣u×全局参考向量∣∣u×全局参考向量(如全局参考向量(1,0,0))w=u×v -
将单位球面上的点 ( x s , y s , z s ) (x_s, y_s, z_s) (xs,ys,zs) 映射到椭球:
( x y z ) = c + [ u ⃗ v ⃗ w ⃗ ] ( a x s b y s c z s ) \begin{pmatrix} x \\ y \\ z \end{pmatrix} = c + \begin{bmatrix} \vec{u} & \vec{v} & \vec{w} \end{bmatrix} \begin{pmatrix} a x_s \\ b y_s \\ c z_s \end{pmatrix} xyz =c+[uvw] axsbysczs
4、关键公式总结
概念 | 公式 |
---|---|
方向向量归一化 | u ⃗ = u ⃗ input ∣ u ⃗ input ∣ \vec{u} = \frac{\vec{u}_{\text{input}}}{|\vec{u}_{\text{input}}|} u=∣uinput∣uinput |
正交向量计算 | v ⃗ = u ⃗ × r ⃗ ∣ u ⃗ × r ⃗ ∣ \vec{v} = \frac{\vec{u} \times \vec{r}}{|\vec{u} \times \vec{r}|} v=∣u×r∣u×r |
第三个轴向 | w ⃗ = u ⃗ × v ⃗ \vec{w} = \vec{u} \times \vec{v} w=u×v |
表面点坐标 | p = c + a cos θ sin ϕ ⋅ u ⃗ + b sin θ sin ϕ ⋅ v ⃗ + c cos ϕ ⋅ w ⃗ p = c + a\cos\theta\sin\phi \cdot \vec{u} + b\sin\theta\sin\phi \cdot \vec{v} + c\cos\phi \cdot \vec{w} p=c+acosθsinϕ⋅u+bsinθsinϕ⋅v+ccosϕ⋅w |
二、代码实现
#include <vector>
#include <iostream>
#include <corecrt_math_defines.h>
#include <pcl/point_types.h>
#include <pcl/point_cloud.h>
#include <pcl/visualization/pcl_visualizer.h>
#include <boost/thread/thread.hpp>int main()
{// 定义椭球参数Eigen::Vector3f center(1.0, 2.0, 3.0); // 中心点float a = 2.0, b = 1.0, c = 1.5; // 半轴长度Eigen::Vector3f u_dir(1, 1, 0); // 初始方向向量// 计算正交基u_dir.normalize(); // u = u/||u||Eigen::Vector3f global_ref(1, 0, 0);Eigen::Vector3f v_dir = u_dir.cross(global_ref).normalized(); // v = (u×ref)/||u×ref||Eigen::Vector3f w_dir = u_dir.cross(v_dir); // w = u×v// 生成点云pcl::PointCloud<pcl::PointXYZ>::Ptr cloud(new pcl::PointCloud<pcl::PointXYZ>);const int num_points = 10000; // 点云密度for (int i = 0; i < num_points; ++i) {float theta = 2 * M_PI * rand() / RAND_MAX; // [0, 2π]float phi = M_PI * rand() / RAND_MAX; // [0, π]// 计算点坐标Eigen::Vector3f point = center+ a * cos(theta) * sin(phi) * u_dir+ b * sin(theta) * sin(phi) * v_dir+ c * cos(phi) * w_dir;cloud->push_back(pcl::PointXYZ(point.x(), point.y(), point.z()));}boost::shared_ptr<pcl::visualization::PCLVisualizer> viewer(new pcl::visualization::PCLVisualizer("3D Viewer"));viewer->setWindowName("椭球点云");viewer->addPointCloud<pcl::PointXYZ>(cloud, "cloud");viewer->setPointCloudRenderingProperties(pcl::visualization::PCL_VISUALIZER_COLOR, 1, 1, 1, "cloud");while (!viewer->wasStopped()){viewer->spinOnce(100);boost::this_thread::sleep(boost::posix_time::microseconds(100000));}return 0;
}