I have a set of points that I know lie on the same helix but they are not on a regular interval. It’s oriented on the y axis and reversed and has a known pitch and diameter.
I need the equation to be correct for further derivation, and I am validating it by plotting in matplotlib. I believe I have my equations all correct but the resulting helix is off when I plot.
I think the helix is rotated about its axis / has a phase shift, because for each data set I have, I can find a constant value "phi" added to theta that lines up pretty close. I’m stuck on how I can calculate that constant exactly.
I've tried several equations to calculate it but none are correct. What am I missing here?
Resulting plot:
# -*- coding: utf-8 -*-import numpy as npimport matplotlib.pyplot as pltdef 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()