Context: For university I have to write a program that calculates the position and value of a runout error for drills.
Idea: My idea is with Fourier transformation I only look at the noise and calculate the runout error only of that signal
Problem: The values of the error are way too small to be true. The series I copied below is made with a "Concentricity standard" (translated with google. basically a bar with 4/100 mm error). You could use min max functions here but not with a real drill
Values below are in 1/1000 mm The calculated error here is 4.0689482653531e-17
1;1174
2;1174
3;1174
4;1174
5;1174
6;1174
7;1174
8;1174
9;1174
10;1174
11;1174
12;1174
13;1176
14;1176
15;1176
16;1176
17;1176
18;1176
19;1176
20;1176
21;1178
22;1178
23;1178
24;1180
25;1178
26;1180
27;1180
28;1180
29;1182
30;1182
31;1182
32;1182
33;1184
34;1184
35;1184
36;1184
37;1186
38;1186
39;1186
40;1186
41;1188
42;1188
43;1188
44;1188
45;1188
46;1188
47;1190
48;1190
49;1190
50;1190
51;1190
52;1192
53;1192
54;1194
55;1194
56;1194
57;1195
58;1195
59;1195
60;1197
61;1195
62;1197
63;1197
64;1199
65;1199
66;1199
67;1199
68;1199
69;1201
70;1201
71;1201
72;1203
73;1203
74;1203
75;1203
76;1205
77;1203
78;1205
79;1205
80;1207
81;1205
82;1207
83;1207
84;1207
85;1207
86;1209
87;1209
88;1209
89;1209
90;1211
91;1211
92;1211
93;1211
94;1213
95;1213
96;1213
97;1213
98;1215
99;1213
100;1215
101;1213
102;1215
103;1215
104;1215
105;1215
106;1215
107;1217
108;1217
109;1217
110;1217
111;1217
112;1217
113;1219
114;1217
115;1219
116;1219
117;1217
118;1219
119;1219
120;1219
121;1220
122;1220
123;1220
124;1219
125;1220
126;1219
127;1219
128;1219
129;1220
130;1220
131;1220
132;1220
133;1220
134;1220
135;1220
136;1220
137;1220
138;1220
139;1220
140;1220
141;1220
142;1220
143;1220
144;1220
145;1220
146;1220
147;1220
148;1220
149;1220
150;1220
151;1219
152;1220
153;1219
154;1219
155;1219
156;1220
157;1219
158;1219
159;1219
160;1220
161;1219
162;1219
163;1219
164;1219
165;1219
166;1217
167;1217
168;1217
169;1217
170;1217
171;1217
172;1217
173;1217
174;1215
175;1215
176;1215
177;1215
178;1215
179;1215
180;1213
181;1213
182;1213
183;1213
184;1213
185;1213
186;1211
187;1213
188;1211
189;1211
190;1209
191;1209
192;1209
193;1209
194;1209
195;1209
196;1209
197;1207
198;1207
199;1207
200;1205
201;1205
202;1205
203;1205
204;1203
205;1205
206;1203
207;1201
208;1201
209;1201
210;1201
211;1201
212;1199
213;1199
214;1199
215;1199
216;1197
217;1197
218;1197
219;1195
220;1197
221;1195
222;1195
223;1195
224;1195
225;1195
226;1194
227;1194
228;1192
229;1192
230;1192
231;1190
232;1192
233;1190
234;1188
235;1190
236;1188
237;1188
238;1186
239;1186
240;1186
241;1186
242;1186
243;1184
244;1184
245;1184
246;1184
247;1182
248;1182
249;1182
250;1180
251;1180
252;1180
253;1180
254;1178
255;1178
256;1178
257;1178
258;1178
259;1178
260;1176
261;1174
262;1174
263;1174
264;1174
265;1172
266;1172
267;1172
268;1172
269;1171
270;1172
271;1172
272;1171
273;1171
274;1171
275;1171
276;1169
277;1169
278;1169
279;1169
280;1167
281;1169
282;1167
283;1167
284;1167
285;1167
286;1167
287;1167
288;1167
289;1165
290;1165
291;1165
292;1165
293;1163
294;1163
295;1163
296;1163
297;1163
298;1163
299;1163
300;1163
301;1161
302;1163
303;1161
304;1161
305;1161
306;1163
307;1161
308;1163
309;1161
310;1161
311;1161
312;1161
313;1161
314;1161
315;1163
316;1161
317;1163
318;1161
319;1161
320;1161
321;1163
322;1161
323;1161
324;1161
325;1163
326;1163
327;1163
328;1161
329;1161
330;1161
331;1161
332;1163
333;1161
334;1163
335;1163
336;1161
337;1163
338;1163
339;1163
340;1163
341;1165
342;1163
343;1163
344;1163
345;1165
346;1163
347;1163
348;1165
349;1165
350;1165
351;1165
352;1165
353;1167
354;1165
355;1167
356;1167
357;1167
358;1167
359;1167
360;1167
You have to look at the graphics manually and find a point for the cutoff.
Do you have ideas to improve this or an even better way to solve this problem?
def fourier_analysis(data, cutoff = 10_000):
n = len(data.Degree)
fhat = np.fft.fft(data.Distance, n )
PSD = fhat * np.conj(fhat) / n
freq = (1 / n) * np.arange(n)
L = np.arange(1,np.floor(n/2), dtype='int')
# Frequenzen filtern
yf = np.fft.fft(data['Distance'].values)
filtered_yf = np.where(np.abs(fft(data['Distance'].values)) < cutoff, 0, yf)
filtered_noise = np.where(np.abs(fft(data['Distance'].values)) > cutoff, 0, yf)
# Inverse FFT
reconstructed_signal = ifft(filtered_yf)
noise_signal = ifft(filtered_noise)
return noise_signal , reconstructed_signal , PSD, L , freq
def calc_runout_error(noise_signal):
df = pd.DataFrame()
noise = np.real(noise_signal)
for i , j in enumerate(noise):
df.loc[i,'x'] = j * np.cos(math.radians(i))
df.loc[i,'y'] = j * np.sin(math.radians(i))
center_x = np.mean(df['x'])
center_y = np.mean(df['y'])
deg = math.degrees(math.atan2(center_y, center_x))
if deg < 0:
deg += 360
distance = math.sqrt(center_x**2 + center_y**2)
return deg , distance , df
def show_runout_error(df, cutoff=10_000, plots = False, y_lim_value=500, x_lim_left= -0.01, x_lim_right= 0.1):
print(df.loc[0,'Filename'])
# Analysis
noise_signal , reconstructed_signal , PSD, L , freq = fourier_analysis(df,cutoff)
deg , distance, df_error = calc_runout_error(noise_signal)
if plots == True:
min_val = min(df['Distance'].min(), np.real(reconstructed_signal).min())
max_val = max(df['Distance'].max(), np.real(reconstructed_signal).max())
# plot results
fig = plt.figure(figsize=(10,16))
# show original
plt.subplot(3, 2, 1)
plt.plot(df['Degree'], df['Distance'])
plt.title('original data')
plt.xlabel('deg')
plt.ylabel('distance')
plt.ylim(min_val, max_val)
# show filtered
plt.subplot(3, 2, 2)
plt.plot(df['Degree'], np.real(reconstructed_signal))
plt.title('filtered data')
plt.xlabel('deg')
plt.ylabel('distance')
plt.ylim(min_val, max_val)
#show fourier
plt.subplot(3, 2, 3)
plt.plot(freq[L], np.real(PSD[L]), color='r', linewidth=2)
plt.ylim(0,y_lim_value)
plt.xlim(x_lim_left, x_lim_right)
plt.title('fourier transformation')
plt.xlabel('frequency')
plt.ylabel('power spectrum density (PSD)')
# show scatter
plt.subplot(3, 2, 4)
plt.scatter(x=df_error['x'], y=df_error['y'], color='blue', s=5)
plt.xlabel('x-coordinate')
plt.ylabel('y-coordinate')
plt.title('runout error in cartesian')
plt.grid(True)
# Noise
plt.subplot(3, 1, 3)
plt.plot(df.Degree, np.real(noise_signal), color='red')
plt.title('runout error (noise)')
plt.xlabel('deg')
plt.ylabel('distance')
plt.show()
print('Degree: ', deg , ' Distance: ', distance)
return deg , distance, reconstructed_signal
deg,distance, reconstructed_signal = show_runout_error(list_df[5],
cutoff=2500,
plots=True,
y_lim_value=20_000,
x_lim_right=0.1
)
but that is not the Problem
... then, what is the problem $\endgroup$