根据点和已知参数计算螺旋方程

问题描述 投票:0回答:1

我有一组点,我知道它们位于同一螺旋上,但它们的间隔不规则。它在 y 轴上定向并反转,并具有已知的节距和直径。

我需要正确的方程才能进一步推导,并且我通过在 matplotlib 中绘图来验证它。我相信我的方程都是正确的,但当我绘图时,所得的螺旋线是关闭的。

我认为螺旋绕其轴旋转/具有相移,因为对于我拥有的每个数据集,我可以找到添加到 theta 上的常数值“phi”,该值非常接近。我不知道如何准确计算该常数。

我尝试了几个方程式来计算它,但没有一个是正确的。我在这里缺少什么?

结果图:

# -*- coding: utf-8 -*-
 
import numpy as np
import matplotlib.pyplot as plt
 
 
def main():
 
    x_0, z_0 = (0, 0) # Initial XZ translation of the helix
    pitch = 5
    r_helix = 21.5
    points = [# Points are always sorted by increasing y-coordinate
        [20.706544339200267, 51.9046499762355, -5.788595251885937],
        [19.212903026597925, 52.05814477857687, -9.650552848362423],
        [17.00664971029413, 52.211639580918224, -13.15456870905615],
        [14.16961495005295, 52.36513438325957, -16.17067789422802],
        [10.807025167874555, 52.51862918560093, -18.587012060787742],
        [7.04359977022926, 52.672123987942285, -20.31394869079267],
        [3.0189252699820353, 52.825618790283634, -21.28743521599688],
        [-1.1177220168658544, 52.979113592624984, -21.471364745731137],
        [-5.212912671975268, 53.13260839496634, -20.85891528169458],
        [-9.11475491520846, 53.28610319730769, -19.472802747801666],
        # Some data omitted
        [-20.544641484739234, 59.42589529096156, 6.339282819338791],
        [-20.48822155492154, 68.94257303612517, -6.51932342611974],
        [8.197335651860236, 72.62644829231755, -19.876430708539715],
        [-5.395754482518458, 75.23585993212036, 20.812367447290228],
        [-21.278276786591253, 79.07322999065414, -3.082813189435626],
        [19.868218515870804, 81.3756520257743, 8.217220101810312],
        #
        [-7.6638231725025365, 80.14769360704351, 20.088171117827414],
        [-3.6709266068804496, 80.30118840938484, 21.18473751524141],
        [0.4581256711564359, 80.45468321172619, 21.495556003964907],
        [4.570185944294954, 80.60817801406753, 21.009098238304716],
        [8.512736733491103, 80.76167281640888, 19.743407074433094],
        [12.13954771442364, 80.91516761875025, 17.745427355746926],
        [15.316099441598734, 81.06866242109157, 15.089264715343518],
        [17.92457271264586, 81.22215722343293, 11.87343697712015],
        [19.868218515870804, 81.3756520257743, 8.217220101810312],
        [21.07494647847481, 81.52914682811566, 4.256224207850664]]
 
    t = np.linspace(points[0][1], points[-1][1], 200)
    theta = 2 * np.pi * t / pitch
    x = -r_helix * np.cos(theta) + x_0
    y = t
    z = r_helix * np.sin(theta) + z_0
    pts = np.column_stack((x, y, z))
    
    # phi = np.arccos(points[0][0]/-r_helix) - 2 * np.pi * t[0] / pitch 
    # phi = np.arcsin((points[0][2] - z_0)/r_helix) - t[0]
    # phi = np.arctan((points[0][0]-pts[0][0])/(points[0][2]-pts[0][2]))
    _phi = 1.0207
    _theta = theta + _phi
    _x = -r_helix * np.cos(_theta) + x_0
    _z = r_helix * np.sin(_theta) + z_0
    _pts = np.column_stack((_x, y, _z))
    
    
    
    # PLOTTING
    plt.rcParams.update({
        'xtick.color':'w', 'ytick.color':'w',
        'axes.edgecolor':'w', 'axes.labelcolor':'w',
        'font.size':24, 'xtick.major.pad':15, 'ytick.major.pad':15,
        })
    fig = plt.figure(facecolor='grey',)
    subplot = fig.add_subplot(projection='3d', facecolor='grey',
                              xlabel='X', ylabel='Y', zlabel='Z',
                              title= f'Original (cyan), Error: {np.linalg.norm(pts[0] - points[0])} mm'
          f'\nWith phi (green), Error: {np.linalg.norm(_pts[0] - points[0])} mm')
    for (x, y, z) in points:
        plt.plot(x, y, z, marker='o', color='w')
        
    for point_set, color in ((pts, 'cyan'), (_pts, 'green')):
        subplot.plot(tuple(i[0] for i in point_set), 
                     tuple(i[1] for i in point_set),
                     tuple(i[2] for i in point_set), 
                     color=color, linestyle='dashdot',
                     )
    
 
 
if __name__ == '__main__':
    main()
python numpy matplotlib math geometry
1个回答
0
投票

只需根据数据计算实际的

theta
;始终使用 arctan2 因为你要处理所有方向的角度 (-pi, pi] -
arctan
只能 求 (-pi/2...pi/2) 中的角度。

计算出

phi
之后——计算出的
theta
与理想的
theta = 2 * np.pi * y / pitch
之间的差异,您必须将其减少到区间
(-pi, pi]
。我使用了公式
np.arctan2(np.sin(phi), np.cos(phi))
来实现这一点。

    # computing from the average of all points (recommended)
    x_p = [x_0 - x for (x, y, z) in points]
    z_p = [z - z_0 for (x, y, z) in points]
    theta_xy = np.arctan2(z_p, x_p)  # actual theta, from points coordinates x and z
    theta_p = [2 * np.pi * y / pitch for (x, y, z) in points]  # "ideal" theta from y
    phi_p = theta_xy - theta_p
    phi_p = np.arctan2(np.sin(phi_p), np.cos(phi_p))  # one way to reduce phi to -pi...pi
    # print(phi_p)
    phi = np.average(phi_p)
    print(phi)

    # computing just from the first point
    theta_xy = np.arctan2(points[0][2] - z_0, x_0 - points[0][0])
    phi = theta_xy - 2 * np.pi * points[0][1] / pitch
    phi = np.arctan2(np.sin(phi), np.cos(phi))
    print(phi)
© www.soinside.com 2019 - 2024. All rights reserved.