Reputation: 13
We had to motion detect a pendulum by filming it,track the pendulum with a given software and store the t,x and y values in a txt-file. Since my hands were very shaky, the graph is very shaky (image attached). data and fit
This is my code:
import sys
sys.path.insert(0, "..")
import numpy as np
import matplotlib.pyplot as plt
from scipy.optimize import curve_fit
%matplotlib inline
import pandas as pd
data = np.loadtxt('newdata.txt', delimiter = ',', skiprows = 1)
t = data[:,0]
x = data[:,1]
def cos_func(times, amplitude, frequency):
return amplitude * np.cos(frequency * times)
def period2freq(period):
return 1.0 / period * 2.0 * np.pi
def freq2period(freq):
return 1.0 / freq * 2.0 * np.pi
popt, pcov = curve_fit(cos_func, # our function
t, # measured x values
x, # measured y values
p0=(200, period2freq(150))) # the initial guess for the two parameters
fig, ax = plt.subplots(1, 1)
ax.plot(t, x, label='Measured')
ax.plot(t, cos_func(t, popt[0], popt[1]), label='Best Fit')
ax.legend()
I tried something, this is my code now and the image, still bad:
# Laden der Daten
data = np.loadtxt('newdata.txt', delimiter = ',', skiprows = 1)
t = data[:,0]
x = data[:,1]
# Definition der Fit-Funktion mit Offset und Phase
def cos_func(times, amplitude, frequency, phase, offset):
return amplitude * np.cos(frequency * times + phase) + offset
# Startparameter für den Fit
initial_amplitude = (np.max(x) - np.min(x)) / 2 # Amplitude als Hälfte der Amplitude der Daten
initial_frequency = 2 * np.pi / 150 # Annahme für die Frequenz
initial_phase = 0 # Startphase
initial_offset = -220 # Ihr Offset-Wert
shift = 10 # Verschiebung um 5 Einheiten nach rechts
# Durchführung des Fits
p0 = (initial_amplitude, initial_frequency, initial_phase, initial_offset)
popt, pcov = curve_fit(cos_func, t, x, p0=p0)
# Anpassen der Phase für die Verschiebung nach rechts
popt[2] += shift * initial_frequency
# Plotten der Daten und des Fits
plt.figure(figsize=(10, 6))
plt.plot(t, x, label='Measured')
plt.plot(t, cos_func(t, *popt), label='Best Fit')
plt.legend()
plt.xlabel('Time')
plt.ylabel('Position')
plt.title('Fit of Pendulum Motion')
plt.show()
I honestly just played around so it looked a bit better, but it's still bad and I don't understand it.
Upvotes: 1
Views: 68
Reputation: 474
The function you are fitting has two properties that the data does not have:
Summarizing you should use a function y(t) = a * cos(b * t + c) + d, with (a,b,c,d) to be determined.
PS: not only were you shaking very importantly, but also you seem to have followed the pendulum with the camera. As a consequence the position of the object on the image does not correspond to the absolute position of the object in space... But well, you'll still get a cosine curve that goes as well as possible through the data points....
Upvotes: 0
Reputation: 26
Have you tried changing your function to:
def cos_func(times, amplitude, frequency, offset):
return amplitude * np.cos(frequency * times) + offset
Upvotes: 0