我有一组点,我知道它们位于同一螺旋上,但它们的间隔不规则。它在 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()
只需根据数据计算实际的
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)