diff --git a/scripts/first_order.py b/scripts/first_order.py new file mode 100644 index 0000000..52d3215 --- /dev/null +++ b/scripts/first_order.py @@ -0,0 +1,36 @@ + +import scipy.signal as sig +import matplotlib.pyplot as plt +import numpy as np + +# simple first order step response simulation +# www.halvorsen.blog/documents/programming/python/resources/powerpoints/State Space Models with Python.pdf + +# simulation Parameters + +x0 = [0, 0] +start = 0 +stop = 30 +step = 1 + +t = np.arange(start,stop,step) +K = 3 +T = 4 + +# state-space Model +A = [[-1/T, 0], [0, 0]] +B = [[K/T], [0]] +C = [[1, 0]] +D = 0 +sys = sig.StateSpace(A, B, C, D) + +# step Response +t, y = sig.step(sys, x0, t) + +# plotting +plt.plot(t, y) +plt.title("Step Response") +plt.xlabel("t") +plt.ylabel("y") +plt.grid() +plt.show() diff --git a/scripts/string_model.py b/scripts/string_model.py index 38a0f90..936fb14 100644 --- a/scripts/string_model.py +++ b/scripts/string_model.py @@ -2,29 +2,76 @@ import scipy.signal as sig import matplotlib.pyplot as plt import numpy as np +import math # simple first order step response simulation # www.halvorsen.blog/documents/programming/python/resources/powerpoints/State Space Models with Python.pdf # simulation Parameters -x0 = [0, 0] + +# string pde (wave equation) +# rho*A*d2y(x,t)/dt2 + c*dy(x,t)/dt - T*d2y(x,t)/dx2 = f(x,t) +# where rho*A = 1 dimensional string density, c = string damping, T = string tension, y(x,t) = displacement, f(x,t) = exitation force + +# assume fixed ends: y(0, t) = y(L, t) = 0 + +# displacement y(x,t) can be represented as the sum from n=1 to N of qn(t)*sin(n*pi*x/L) where q_n(t) is the modal coordinate of mode n (displacement is the sum of all resonating modes) +# therefore: +# q..n + 2*zeta_n*omega_n*q.n + omega_n2*q_n = b_n*u(t) +# where omega_n = n*pi/L * sqrt(T/(rho*A)) for an ideal string +# and b_n = sin(n*pi*x_h/L) but assuming the hammer strikes at midpoint, x_h = L/2 ( b_n = sin(n*pi/2) ) + +# state space representation: +# each mode: +#「 q_n_dot | =「 0 1 | 「 q_n | + 「 0 |* u +# L q_n_dot_dot 」= L -omega_n^2 -2*zeta_n*omega_n 」 L q_ndot 」 L b_n 」 +# and x_dot = Ax + Bu +# where A = diagonal matrix of A_n and B = [ 0 b_1 0 b_2 ... b_n]^T + +# lets start with 3 nodes where the string is tuned to 440hz (we'll get to arbitrary modes evantually) +f_1 = 440 # fundamental frequency +def f_n(n): + return f_1 * n +def omega_n(n): + return 2*math.pi*f_n(n) # a cooler option would be omega_n = c*n*omega_1*sqrt(1+B*n^2) to factor in string stiffness to its vibration mode + +# x = [ q1, q1dot, q2, q2dot, q3, q3dot ]^T < --state vector +omega_1 = omega_n(1) +omega_2 = omega_n(2) +omega_3 = omega_n(3) +zeta_1 = 0.0001 # i guessed +zeta_2 = 2 * zeta_1 +zeta_3 = 3 * zeta_1 +A = [ + [ 0, 1, 0, 0, 0, 0], + [-omega_1**2, -2*zeta_1*omega_1, 0, 0, 0, 0], + [ 0, 0, 0, 1, 0, 0], + [ 0, 0, -omega_2**2, -2*zeta_2*omega_2, 0, 0], + [ 0, 0, 0, 0, 0, 1], + [ 0, 0, 0, 0, -omega_3**2, -2*zeta_3*omega_3] + ] # isnt this formatting gorgeous + +B = [ [0], [0.707], [0], [0], [0], [-0.707] ] +c_1 = 0.001 +c_2 = c_1 / 2 +c_3 = c_1 / 3 +C = [[-c_1*omega_1**2, -2*c_1*zeta_1*omega_1, -c_2*omega_2**2, -2*c_2*zeta_2*omega_2, -c_3*omega_3**2, -2*c_3*zeta_3*omega_3]] +D = c_1 * 0.707 + c_2 * 0 + c_3 * (-0.707) + +# input +#v_h = 100 # hammer velocity +#u = v_h * impulse(t) + +x0 = [[0], [0], [0], [0], [0], [0]] start = 0 -stop = 30 -step = 1 +stop = 10 +step = 1/44100 t = np.arange(start,stop,step) -K = 3 -T = 4 - -# state-space Model -A = [[-1/T, 0], [0, 0]] -B = [[K/T], [0]] -C = [[1, 0]] -D = 0 sys = sig.StateSpace(A, B, C, D) # step Response -t, y = sig.step(sys, x0, t) +t, y = sig.impulse(sys, T=t) # plotting plt.plot(t, y)